[Study-NextStep] 2022-02-05

jeonye·2022년 2월 2일
0

Study

목록 보기
1/8

일시 : 2022-02-05
범위 : 자바 웹 프로그래밍 Next Step 9장 실습(p306-p331)
목적 : 지금까지 학습한 내용을 최종 점검
실습 : https://github.com/jeonye/jwp-basic/tree/paractice-step7-self-check

문제1, 2를 풀었던 2022-01-31 Study에 이어서 학습

Question

Tomcat 실행

WebServerLauncher를 실행시키면 톰캣이 구동된다.
톰캣이 구동된 후 http://localhost:8080/ URL을 실행하면 아래와 같은 Exception이 발생한다.

The absolute uri: http://java.sun.com/jsp/jstl/core cannot be resolved in either web.xml or the jar files deployed with this application

✳︎ 구글링을 해보니 $TOMCAT_HOME$/lib 에 jstl1.2.jar 파일을 추가 하면된다고 한다.

하지만, WebServerLauncher를 통해서가 아닌 Tomcat을 직접 구동시키면 정상적으로 질문 목록이 표시된다. 무슨 차이일까?

AddQuestionController

AddQuestionController에서 return할 때, 저장한 질문 데이터를 함께 return 했는가?
'/'로 이동할 경우 HomeController에서 질문 목록을 재조회하기 때문에 나는 넘기지 않았다.

return jspView("/");

A) Object 넘기지 않고, '/'로 리다이렉트

수정 가능 여부 확인

글쓴이와 로그인 사용자가 같은 경우에만 질문 수정이 가능해야한다.
질문의 writer에는 사용자ID가 아닌 사용자명이 저장되기 때문에, 사용자명으로 수정 가능 여부를 체크해야하는데 동명이인인 경우에는 어떻게하지?

  • 방법 1 : writer에 사용자명이 아닌 사용자ID가 저장되도록 변경
  • 방법 2 : '사용자ID + 구분자 + 사용자명'을 writer 컬럼에 저장한 후, 화면에 글쓴이 표시할 때 사용자명만 추출해서 표시
  • 방법 3 : 질문 테이블에 사용자ID도 함께 저장하도록 컬럼 추가

A) 방법3으로 대응

Traning

문제7

ShowController는 멀티스레드 상황에서 문제가 발생할 수 있다.
멀티스레드 상황에서 문제가 발생하지 않도록 수정하고, 문제가 되는 이유를 설명하라.

내가 생각한 답

  • ShowController는 프로젝트 초기화 과정에서 인스턴스를 생성한다.
  • 해당 인스턴스는 이후 여러 요청에서 사용된다.(싱글톤)
  • ShowController에는 Model 객체가 전역변수로 선언되어 있다.
public class ShowController extends AbstractController {
    private Question question;
    private List<Answer> answers;
}
  • 전역변수로 선언된 Model 객체를 ShowController에서 참조한다.
  • 여러 스레드가 execute() 메소드를 실행시킨만큼 Model 인스턴스가 생성된다.
  • ShowController 1 : 多 Model 인스턴스인 상황이 발생한다.
  • 여러개의 Model 인스턴스 중 ShowController가 참조하는 Model 인스턴스는 1개이다.
  • 따라서, 요청 내용과는 다른 Model 정보가 반환될 수 있다.

이를 해결하기 위해서는 스레드별로 인스턴스를 생성하도록 전역변수로 선언된 Model 객체를 지역변수로 변경해야한다.

▶︎ 수정 전

public class ShowController extends AbstractController {
    private QuestionDao questionDao = new QuestionDao();
    private AnswerDao answerDao = new AnswerDao();
    private Question question;
    private List<Answer> answers;

    @Override
    public ModelAndView execute(HttpServletRequest req, HttpServletResponse response) throws Exception {
    	...
    }
}

▶︎ 수정 후

public class ShowController extends AbstractController {
    private QuestionDao questionDao = new QuestionDao();
    private AnswerDao answerDao = new AnswerDao();
    
    @Override
    public ModelAndView execute(HttpServletRequest req, HttpServletResponse response) throws Exception {
	    ...
        Question question = questionDao.findById(questionId);
        List<Answer> answers = answerDao.findAllByQuestionId(questionId);
    	...
    }
}

책에 기재된 답

별도 게시글에 책 내용을 옮겨놓았으니 별도 게시글에서 확인한다.

Realize

Servlet Filter

자바 기반으로 웹 프로그래밍을 할 경우 한글이 깨진다. 이러한 문제는 ServletFilter를 활용해 해결할 수 있다.

web.xml을 통해 서블릿, 필터 설정을 해야하지만, 서블릿 3.0부터는 자바 소스상에서 대체할 수 있는 @WebFilter 어노테이션이 추가되었다.

@WebFilter 어노테이션을 통해 특정 url패턴에 매핑되는 필터를 설정할 수 있으며, 만약 필터 초기화시에 설정할 파라미터를 지정하고 싶은 경우에는 initParams 속성에 @WebInitParam 어노테이션을 사용하여 속성명과 속성값을 지정해주면 된다.

@WebFilter(
value= {"/*"},
initParams=@WebInitParam(name="encoding", value="utf-8")
)

<참고>

접속 기기 확인

아래와 같이 웹 브라우저에서 접속했는지, 모바일에서 접속했는지 확인할 수 있다.

private static final String IS_MOBILE = "MOBI";
private static final String IS_PC = "PC";

public static String isDevice(HttpServletRequest req) {
	String userAgent = req.getHeader("User-Agent").toUpperCase();
	if(userAgent.indexOf(IS_MOBILE) > -1) {
		return IS_MOBILE;
	} else {
		return IS_PC;
	}
}

Reflect

안전한 웹 애플리케이션 개발

11번 문제는 글쓴이와 로그인 사용자가 같은 경우에만 질문 수정이 가능하도록 구현하는 것이었다.

자신의 글인 경우에만 화면에서 수정/삭제 버튼이 보이고, 다른 사람의 글에는 수정/삭제 버튼이 보이지 않도록 구현했다.

이렇게 클라이언트 화면 구현만으로 구현을 완료한 경우, 해커는 브라우저가 아닌 다른 HTTP 클라이언트나 브라우저 플러그인을 통해 웹 서버에 요청을 보내 다른 사람의 글을 수정하고 삭제할 수 있다.

따라서, 서버측에서도 처리할 수 있도록 고려해야한다.

추가로 서버측 처리 중 로그인 사용자를 조회할 때, 쿠키를 통해 사용자 정보를 얻는 것 보다는 가능하면 세션에서 사용자 정보를 조회하는 것이 좋다.

0개의 댓글