View Resolver

컨테이너·2025년 11월 29일

Spring Boot

목록 보기
4/7
post-thumbnail

1. View Resolver 정리

컨트롤러의 핸들러 메서드가 실행되면:

  1. 요청을 처리하고
  2. “논리적인 뷰 이름(String)” 또는 “ModelAndView”를 반환한다.

그러면 DispatcherServlet이 이 뷰 이름을 보고

“어떤 템플릿 파일을 응답으로 보여줘야 하는지”를 ViewResolver에게 맡긴다.

image.png

스프링 MVC에는 여러 ViewResolver 구현체가 있는데,

우리가 주로 쓰는 건:

  • JSP 기준 기본: InternalResourceViewResolver 템플릿 명과 위치에 따른 뷰를 해석하는 역할을 한다.
    • prefix + 뷰이름 + suffix → 실제 파일 경로
    • 예: prefix /WEB-INF/views/, suffix .jsp, 뷰 이름 home/WEB-INF/views/home.jsp
  • 타임리프: ThymeleafViewResolver
    • 보통 prefix: classpath:/templates/ (또는 resources/templates/)
    • suffix는 .html 로 바꾸고
    • 뷰 이름은 resulttemplates/result.html 로 바꾼다.

핸들러 메서드에서 return "result"; 라고 하면

실제로는 templates/result.html을 찾아서 렌더링하게 되는 것.


1-1. String 타입으로 뷰 이름 반환

1-1-1. view name 반환 (forward)

요청 흐름:

  1. /string으로 GET 요청
  2. 컨트롤러에서 "result"라는 뷰 이름 반환
  3. ThymeleafViewResolvertemplates/result.html을 찾아서 forward

index.html:

<h3>문자열로 뷰 이름 반환하기</h3>
<button onclick="location.href='string'">문자열로 뷰 이름 반환</button>

컨트롤러:

@GetMapping("string")
public String stringReturning(Model model) {
    model.addAttribute("forwardMessage", "문자열로 뷰 이름 반환함...");
    return "result";
}

여기서 확인해야 할 것은 다음과 같다.

  • "result" = 논리적인 뷰 이름
  • 타임리프 ViewResolverprefix/suffix를 붙여서resources/templates/result.html(물리적인 뷰)을 찾아감
  • Model : view에서 표현되어야 하는 동적인 데이터를 담는 용도로 사용하는 객체.

뷰(result.html):

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>result</title>
</head>
<body>
    <h1 th:text="${ forwardMessage }"></h1>
</body>
</html>

Model에 넣은 forwardMessage가 타임리프에서 ${ forwardMessage }로 출력되는 구조.

forward 요약:

  • 같은 요청 안에서 서버 내부적으로 화면만 바꿔서 보여줌
  • 주소창 URL은 그대로 /string으로 유지됨

1-1-2. redirect

이번에는 같은 String 반환이지만 “redirect” 를 사용해보자. 핸들러 메소드에서 viewresolver의 기본전송방식은 forwad 이다. 경우에 따라서 redirect로 전송하도록 해야 하는데 그때 viewresolver객체에 "redirect:.. 를 붙여서 요청하면 redirect방식으로 이동시켜준다.

index.html:

<h3>문자열로 redirect 하기</h3>
<button onclick="location.href='string-redirect'">
    문자열로 뷰 이름 반환하여 리다이렉트
</button>

컨트롤러:

@GetMapping("string-redirect")
public String stringRedirect()  {
    return "redirect:/";
}

여기서 핵심은:

  • 뷰 이름 앞에 redirect: 를 붙이면 “뷰를 렌더링하라”가 아니라 “저 URL로 다시 요청 보내라”는 의미가 된다.
  • 즉, 클라이언트에게 302 응답과 Location 헤더를 보내서 브라우저가 /로 새로 요청하게 함

결과:

  • 버튼 클릭 → /string-redirect 요청
  • 서버 응답: redirect:/ → 클라이언트가 다시 /로 요청
  • 최종적으로 화면에 루트 페이지가 보이고, 주소창도 /로 바뀜

1-1-3. RedirectAttributes (flash attribute)

redirect는 “다른 요청”이기 때문에 기본적으로 request scope에 있던 데이터는 사라진다. 그래서 redirect 이후에도 한 번만 사용할 값을 넘기고 싶을 때 RedirectAttributes 객체의 addFlashAttribute()를 사용한다. 이는 잠시 세션에 저장했다가 redirect 후 세션에서 제거되게 할 수 있다.

  • 주의할 점 : session scope에 너무 많은 데이터를 저장하는 것은 서버 성능에 영향을 주며 세션에서 이름이 중복되는 것을 항상 주의해야한다.

index.html:

<h3>문자열로 뷰 이름 반환하면서 flashAttribute 추가 하기</h3>
<button onclick="location.href='string-redirect-attr'">
    문자열로 뷰 이름 반환하여 리다이렉트 & flashAttr 사용하기
</button>

컨트롤러:

@GetMapping("string-redirect-attr")
public String stringRedirectFlashAttribute(RedirectAttributes rttr) {

    rttr.addFlashAttribute("flashMessage1", "리다이렉트 attr 사용하여 redirect..");

    return "redirect:/";
}

설명:

  • addFlashAttribute("키", 값):
    • 일시적인 저장소(플래시 영역)에 값을 담음
    • redirect 이후 새로 들어온 요청의 requestScope에 자동으로 옮겨줌
    • 한 번 사용하면 사라지는 개념 (세션을 잠깐 빌리는 느낌) → 한 번만 사용가능하고 그 뒤로 넘길 수 없다(재사용 X)

루트 페이지 템플릿에서:

<script>
    const flashMessage1 = '[[${ flashMessage1 }]]';
    console.log(flashMessage1);
    if(flashMessage1) {
       alert(flashMessage1);
    }
</script>
  • redirect 이후에도 flashMessage1이 한 번은 유지되기 때문에 alert로 메시지를 보여줄 수 있다.
  • 다음 요청부터는 더 이상 남아 있지 않음

정리:

  • forward → 같은 요청 안에서 화면만 바꿈 (request 데이터 유지)
  • redirect → 완전 새로운 요청 (request 데이터 초기화됨)
  • RedirectAttributes.addFlashAttribute → redirect에도 “한 번만 쓸 데이터”를 전달하는 방법

1-2. ModelAndView 타입으로 반환

지금까지는:

  • 뷰 이름은 String으로 return
  • 모델 데이터는 Model 파라미터로 채우는 방식

ModelAndView 타입 방식 :

  • 모델 + 뷰 이름을 합쳐서 ModelAndView라는 객체로 한 번에 반환하는 방식이다.

둘의 기능 차이보다는 “작성 스타일” 차이에 가깝고, forward/redirect/RedirectAttributes 사용 방식은 거의 동일하다. 그냥 스프링에서 이런거 제공한다 까지만 알아도 된다.


1-2-1. view name 반환 (forward)

index.html:

<h3>ModelAndView로 뷰 이름 지정해서 forward로 반환하기</h3>
<button onclick="location.href='modelandview'">
    ModelAndView로 뷰 이름 지정해서 반환받기
</button>

컨트롤러:

@GetMapping("modelandview")
public ModelAndView modelAndViewReturning(ModelAndView mv) {

    mv.addObject("forwardMessage", "ModelAndView를 이용한 모델과 뷰 반환");
    mv.setViewName("result");

    return mv;
}

설명:

  • ModelAndView mv를 파라미터로 받아와서
    • addObject("키", 값)으로 모델 데이터 추가: 모델 객체에 attribute를 저장한다.
    • setViewName("result")로 논리적 뷰 이름 지정을 해준다.
  • 반환하면 DispatcherServlet이 이걸 그대로 사용:
    • 모델 → 타임리프에 전달
    • 뷰 이름 "result" → result.html 렌더링

실제 결과는 String + Model 방식과 동일하게 result.html이 뜨고

forwardMessage가 출력된다.


1-2-2. redirect

index.html:

<h3>ModelAndView로 redirect 하기</h3>
<button onclick="location.href='modelandview-redirect'">
    ModelAndView로 뷰 이름 반환하여 리다이렉트
</button>

컨트롤러:

@GetMapping("modelandview-redirect")
public ModelAndView modelAndViewRedirect(ModelAndView mv)  {

    mv.setViewName("redirect:/");

    return mv;
}

설명:

  • 똑같이 setViewName("redirect:/")로 설정하면 redirect 동작
  • 내부적으로는 String 반환 방식과 같은 규칙을 사용
  • 결과: /로 다시 요청 보내는 리다이렉트

1-2-3. RedirectAttributes + ModelAndView

index.html:

<h3>ModelAndView로 뷰 이름 반환하면서 flashAttribute 추가 하기</h3>
<button onclick="location.href='modelandview-redirect-attr'">
    ModelAndView로 뷰 이름 반환하여 리다이렉트
</button>

컨트롤러:

@GetMapping("modelandview-redirect-attr")
public ModelAndView modelAndViewRedirect(ModelAndView mv, RedirectAttributes rttr) {

    rttr.addFlashAttribute("flashMessage2", "ModelAndview를 이용한 redirect attr");
    mv.setViewName("redirect:/");

    return mv;
}

템플릿에서:

<script>
    const flashMessage2 = '[[${ flashMessage2 }]]';
    console.log(flashMessage2);
    if(flashMessage2) {
       alert(flashMessage2);
    }
</script>

설명:

  • RedirectAttributes 사용법은 String 반환 방식과 동일
  • ModelAndView를 쓰느냐, String을 쓰느냐만 다름
  • redirect 후에도 한 번만 사용할 값(flashMessage2)을 화면에서 확인할 수 있음

정리

  1. ViewResolver
    • 컨트롤러 → “논리 뷰 이름” 반환
    • ViewResolver가 prefix/suffix를 붙여 실제 템플릿 파일을 찾는 역할
    • 타임리프: templates/ + 뷰이름 + .html
  2. String vs ModelAndView
    • String
      • 뷰 이름만 반환
      • 모델은 Model 파라미터에 넣어서 전달
    • ModelAndView
      • 뷰 이름 + 모델을 한 객체에 담아서 반환
    • 기능상 큰 차이는 없고, 코드 스타일 차이
  3. forward vs redirect
    • forward: "result" 처럼 그냥 뷰 이름
    • redirect: "redirect:/경로" 또는 mv.setViewName("redirect:/경로")
  4. RedirectAttributes
    • redirect 시에도 값을 한 번만 전달하고 싶을 때
    • addFlashAttribute("키", 값) 사용
    • redirect 후 새 요청의 requestScope에서 그 값을 꺼낼 수 있음
    • alert 메시지, 성공/실패 알림 등 “한 번 보여주고 끝낼 값”에 적합
profile
백엔드

0개의 댓글