[Spring] Spring MVC 응답 처리 - ModelAndView, ViewResolver, forward vs redirect
by 우와한개발자

1. ModelAndView
- 모델 데이터와 뷰 이름을 함께 담은 객체로 Controller가 반환
- DispatcherServlet은 최종적으로 View에게 Model 객체만 전달 (ModelAndView 아님)
| 구분 | Model | ModelAndView |
| 역할 | 데이터를 담음 | 데이터와 뷰 이름을 함께 담음 |
| 뷰 이름 포함 여부 | 없음 | 있음 |
| 주 사용 방식 | 파라미터로 받음 | 반환값으로 사용 |
| 예시 | model.addAttribute("name", "kim") | new ModelAndView("home") |
@GetMapping("/user")
public ModelAndView getUser() {
ModelAndView mav = new ModelAndView();
mav.addObject("user", new User("홍길동"));
mav.setViewName("user/detail"); // /WEB-INF/views/user/detail.jsp
return mav;
}
2. ViewResolver
- 컨트롤러에서 반환한 문자열(뷰 이름)을 실제 View 객체로 변환
- Spring은 컨트롤러 메서드의 반환 타입과 어노테이션을 보고 ViewResolver를 거칠지, 아닐지 판단
- prefix + 뷰이름 + suffix 조합으로 JSP 경로 결정
<beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<beans:property name="prefix" value="/WEB-INF/views/" />
<beans:property name="suffix" value=".jsp" />
</beans:bean>
1) <mvc:view-controller>
- 컨트롤러 메서드 없이 URL과 View를 바로 연결할 때 사용.
- 단순히 화면만 이동하면 되는 경우 컨트롤러를 따로 만들 필요 없이 servlet-context.xml에 설정만으로 처리할 수 있음.
<!-- /home 요청 → home.jsp로 바로 이동 -->
<mvc:view-controller path="/home" view-name="home"/>
→ "home" 반환 시 → /WEB-INF/views/home.jsp
2) ViewResolver가 View를 찾는 순서
1. BeanNameViewResolver → 해당 이름의 View 빈 있는지 확인
2. ContentNegotiatingViewResolver → 조건에 맞는 View 있는지 확인
3. InternalResourceViewResolver → /WEB-INF/views/{뷰이름}.jsp 렌더링
4. 모두 없으면 → HTTP 500 오류
3. View
- 최종적으로 사용자에게 보여지는 화면
- DispatcherServlet이 Model 객체를 View에 전달
- View가 데이터를 기반으로 HTML을 완성해 응답
[ forward와 redirect]
1. forward 란?
- 서버 내부에서 요청을 다른 페이지로 넘기는 방식
- 클라이언트(브라우저)는 이동이 일어난 사실을 모름.
- URL(주소창)이 변경되지 않음
- request / response 객체를 서블릿과 JSP가 동일하게 공유
- 첫 번째 JSP → 서블릿 → 두 번째 JSP로 포워딩 시, setAttribute 없이도 두 번째 JSP에서 request.getParameter()로 값 사용 가능
- Spring MVC에서는 return "뷰이름"이 기본값으로 forward 방식
return "home"; // forward (기본값)
return "forward:/home"; // forward 명시
⚠️ URL이 변경되지 않았는데 새로고침하게되면?
- 해당 URL에 다시 요청을 보내기 때문에 서블릿의 service 메서드가 한 번 더 동작함.
- 회원가입, 결제 등 등록 처리 후 forward를 사용하면 중복 요청이 발생할 수 있음.
2. redirect 란?
- 서버가 브라우저에게 "이 URL로 다시 요청해"라고 지시하는 방식
- 리다이렉트로 응답받은 브라우저는 서버에 새로운 요청을 한 번 더 보냄.
- URL(주소창)이 변경됨
- 요청이 2번 발생하기 때문에 request / response 객체가 새로 생성됨
- 데이터 공유 불가함 데이터 전달이 필요하면 RedirectAttributes 사용
- HTTP Status Code 302 를 브라우저에 응답하면 브라우저가 새 URL로 재요청
return "redirect:/home";
3.Spring의"forward:"와 "redirect:" 문자열 인식
- Spring은 컨트롤러가 반환한 문자열을 ViewResolver에 넘기기 전에 접두어(prefix)를 먼저 확인.
- UrlBasedViewResolver : 내부적으로 redirect:와 forward:를 약속된 키워드로 인식하도록 하드코딩되어 있음
return "redirect:/home"
↓
DispatcherServlet이 문자열 받음
↓
ViewResolver(UrlBasedViewResolver)에게 넘김
↓
UrlBasedViewResolver가 접두어 확인
"redirect:" → RedirectView 생성
"forward:" → InternalResourceView 생성
아무것도 없으면 → prefix/suffix 조합해서 JSP 경로 결정
| 구분 | forward | redirect |
| URL 변화 | 변하지 않음 | 변함 |
| 요청 횟수 | 1번 | 2번 |
| request 객체 | 유지 (공유됨) | 새로 생성 |
| 데이터 공유 | 가능 | 불가 (RedirectAttributes 사용) |
| context-root | 생략 가능 | 반드시 포함 |
| 새로고침 문제 | 중복 요청 발생 가능 | 마지막 GET 요청만 재실행 |
| 주 사용 상황 | 단순 화면 이동 | 등록/수정/삭제 후 페이지 이동 |
'프레임워크 > Spring' 카테고리의 다른 글
블로그의 정보
우와한개발자 님의 블로그
우와한개발자