우와한 개발자

[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 요청만 재실행
주 사용 상황 단순 화면 이동 등록/수정/삭제 후 페이지 이동

블로그의 정보

우와한개발자 님의 블로그

우와한개발자

활동하기