1. redirect와 forward의 처리 과정 비교
1.1 redirect
/ch2/write.jsp를 요청 했고, 응답으로 상태코드 302번으로 응답했다. 300번대는 Redirect이다. 다른 URL로 재요청하라는 말이다. 응답에 헤더는 있고 바디는 없다.
응답 헤더에 Location:/ch2/login.jsp로 브라우저가 자동으로 새로운 요청을 한다. 사용자가 아니라 브라우저가 자동으로 한다. 첫 번째 요청은 수동이지만 두 번째 요청은 자동이기 때문에 둘은 다른 객체이다. 첫 번째 객체가 GET, POST 상관 없이 redirect한 요청은 무조건 GET 요청이다.
1.2 forward
클라이언트가 /ch2/write.jsp를 요청했을 때 자기가 처리할 요청이 아닐때 혹은 일부만 처리하고 /ch2/login.jsp로 넘기는 것이 forward이다. 사용자의 요청을 그대로 전달한다. request, response 둘 다 전달해서 login.jsp가 응답을 할 수 있다. redirect와 forward의 차이는 redirect는 요청이 2번 forward는 요청이 1번 이뤄진다. forward에서 login.jsp가 view, request가 Model, write.jsp가 Controller 역할을 한다. spring이 forward를 이용해서 MVC를 구현했다.
2. RedirectView
클라이언트가 /ch2/register/save를 요청하면 DispatcherServlet이 이 요청을 받고 Controller가 URL에 mappign되어 있는 메서드를 호출한다. save 메서드에서 유효성 검사를 통과하지 못해 "forward:/register/add" 문자열이 반환되었다. Controller는 view의 이름 대신에 문자열을 DispatcherServlet에 전달한다.
Controller가 반환한 문자열에 redirect가 들어있어 RedirectView에게 전달한다. RedirectView는 응답 헤더를 만든다. 클라이언트는 이 응답을 받고 300번 이기 때문에 redirect를 인지하고 Location에 있는 URL로 요청을 다시한다. spring에서 RedirectView의 역할은 따로 없고 응답 헤더를 만든다. 이 과정은 브라우저가 자동으로 처리한다.
3. JstlView
/ch2/register/add 요청이 들어오면 DispatcherServlet이 해당 요청을 받고 Controller에게 전달한다. "/register/add"에 연결된 메서드가 register이고 registerForm view 이름을 반환한다. InternalResource ViewResolver에게 "registerForm" 문자열을 전달하고 이 것이 어떤 view인지 해석한다. 그리고 /WEB-INF/views/registerForm.jsp를 반환한다. view 이름을 문자열로 받으면 InternalResource ViewResolver가 DispatcherServlet에게 경로가 붙은 이름을 반환해서 JstlView에게 전달한다. JstlView는 데이터가 담긴 Model을 registerForm.jsp에게 전달해서 최종 응답을 한다. JstlView에서 Jstl인 이유는 spring에는 많은 view의 종류가 있는데 그 중에 jsp를 사용했기 때문이다.
servlet-context 파일을 열어보면 InternalResourceViewResolver가 있다. servlet-context은 spring의 web설정 관련 파일이므로 DispathcerServlet이 view 이름을 문자열로 받으면 InternalResourceViewResolver가 접두사 접미사를 붙여준다.
4. InternalResourceView
InternalResourceView는 forward에서 사용하는 view이다. 사용자가 요청을 하는데 반환하는 문자열의 첫 글자가 forward이다. "/register/add"로 forward하라는 말이다. DispatcherServlet이 문자열 forward:/register/add를 받으면 forwarding을 인식하고 InternalResourceView에게 전달한다. InternalResourceView는 DispatcherServlet에게 /register/add를 호출하라고 알려준다.
5. forward의 예시
"download?type="에서 pdf, excel, csv에 따라 type이 지정되고 아무것도 없으면 defaultValue가 빈 문자열 이기 때문에 txtView로 text가 출력된다.
redirect를 확인하기 위해 타당성 검사를 false로 바꾼다.
save의 응답 헤더를 보면 300번으로 redirect이다. Location은 재요청할 URL이다. URL의 msg뒤에 나온 문자는 "id를 잘못입력하셨습니다."가 출력되었다. 첫 번째 요청이 save이고 두 번째 요청이 add?인데 우리는 add?를 요청한 적이 없다. 브라우저가 300번 응답을 받으면 자동으로 Location의 URL을 요청한다.
요청 방식을 redirect에서 forward로 바꾼다.
요청할 경우 에러가 발생한다. register/save는 POST방식이어서 register/add로 넘어갈 때 POST로 넘어간다. 하지만 register/add는 GET밖에 처리하지 못해 에러가 발생한다.
요청을 GET, POST 둘 다 받을 수 있게 바꾼다.
view-controller는 GET만 처리할 수 있으므로 주석 처리한다.
요청하고 submit하면 URL은 register/save인데 forward는 register/add로 한다. register/save로 전달한 요청을 register/add로 forwarding했다. forward는 전달한 것이고 요청을 1번만 하기 때문에 redirect처럼 요청이 save만 있다. 또한 300번대가 아니라 200번 대인 차이가 있다.
'스프링의 정석 > Ch. 02 Spring MVC' 카테고리의 다른 글
24. 세션(Session) - 이론 (0) | 2023.08.14 |
---|---|
23. 쿠키(Cookie)란 (0) | 2023.08.13 |
21. @GetMapping, @PostMapping (2) (0) | 2023.07.27 |
20. @GetMapping, @PostMapping (1) (0) | 2023.07.25 |
19. 회원가입 화면 작성하기 (0) | 2023.07.22 |