Spring Framework/Spring Boot

[Spring Boot] 4. View Resolver

hyomee2 2024. 9. 9. 19:24

핸들러 메소드가 요청을 처리하고 논리 뷰 이름을 반환하면

DispatcherServlet은 화면에서 데이터를 표시하도록 뷰 템플릿에 제어권을 넘긴다.

 

스프링 MVC에서는 뷰를 해석할 수 있는 ViewResolver 구현체 몇 가지가 있는데,

그 중 MVC 기본 설정에는 InternalResourceViewResolver를 기본으로 사용하고 있다.

 

InternalResourceViewResolver는 사용이 간단해서 편하지만,

RequestDispatcher가 forward 할 수 있는 내부 리소스(jsp/서블릿)만 해석이 가능하기 때문에

다른 뷰 템플릿(Thymeleaf )을 사용하는 경우에는 다른 viewResolver를 사용해야 한다.

 

 Thymeleaf와 같은 뷰 템플릿을 사용하는 경우에는 ThymeleafViewResolver를 사용한다. 

 

prefix를 뷰 이름의 앞 부분에 붙여 파일의 경로를 만들고, suffix를 끝 부분에 붙여서 파일의 확장자를 지정한다.


String 타입으로 반환

1. String으로 view name 반환(forward)

GET 방식의 /string 요청을 전달한다.

<!--/resources/templates/main.html-->

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>main</title>
</head>
<body>
    <h1>view resolver 테스트</h1>

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

 

발생하는 요청을 매핑할 Controllerhandler method이다.

문자열로 view 이름을 반환한다는 것은

반환 후 ViewResolver에게 resources/templates/를 prefix로,

.html을 suffix로 하여 resources/templates/result.html 파일을 응답 뷰로 설정하라는 의미이다.

package org.example.viewresolver;

@Controller
public class ResolverController {

    @GetMapping("/string")
    public String stringReturning(Model model) {
        // Model : View에서 표현 되어야 하는 동적인 데이터를 담는 용도로 사용하는 객체
        model.addAttribute("forwardMessage", "문자열로 뷰 이름 반환함...");

        return "result";
    }
}

 

응답할 뷰에서는 model에 추가된 forwardMessage를 화면에 출력하도록 한다.

<!--resources/templates/result.html-->

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

 

2. redirect

GET 방식의 /string-redirect 요청을 전달한다.

<!--/resources/templates/main.html-->

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>main</title>
</head>
<body>

    <!-- ... 위에서 작성한 내용 생략 -->
    
    <h3>문자열로 redirect하기</h3>
    <button onclick="location.href='string-redirect'">문자열로 redirect</button>

</body>
</html>

 

발생하는 요청을 매핑할 Controller의 핸들러 메소드이다. 

동일하게 String 반환 값을 사용하지만 접두사로 redirect:를 붙이면 forward 되지 않고 redirect 된다.

package com.ohgiraffers.viewresolver;

@Controller
public class ResolverController {

    @GetMapping("/string-redirect")
    public String stringRedirect() {
        // redirect: 을 붙인 뒤 redirect 할 주소 값을 작성한다.
        return "redirect:/";
    }
}

button을 클릭하면 / 경로로 redirect 되는 것을 확인할  수 있다.

3. RedirectAttributes

GET 방식의 /string-redirect-attr 요청을 전달한다.

<!--/resources/templates/main.html-->

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>main</title>
</head>
<body>

    <!--.. 앞에서 작성한 내용 생략-->

    <h3>문자열로 redirect & flash Attribute 하기</h3>
    <button onclick="location.href='string-redirect-attr'">문자열로 redirect & flash Attribute</button>

</body>
</html>

 

기본적으로 redirect를 하면 재요청이 발생하므로 request scope는 소멸된다.

하지만 Spring에서는 RedirectAttributes 타입을 통해 redirect 시 속성 값을 저장할 수 있도록 한다.

Redirect flash 영역에 담아서 redirect 할 수 있다.

자동으로 model에 추가되므로 requestScope에서 값을 꺼내면 된다.

Session에 임시로 값을 담고 소멸하는 방식이기 때문에 session에 동일한 키 값이 존재하면 안된다.

package org.example.viewresolver;

@Controller
public class ResolverController {

    // ... 앞에서 작성한 내용 생략

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

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

        return "redirect:/";
    }
}

 

응답 시 requestScope에 보존된 flashMessage1을 꺼내 alert 창에 띄울 수 있다.

<!--/resources/templates/main.html-->

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>main</title>
</head>
<body>
 
    <!--... 위에서 작성한 코드 생략-->
 
    <script>
        const flashMessage1 = `[[${flashMessage1}]]`;
        if(flashMessage1) alert(flashMessage1);
    </script>
</body>
</html>

실행해보면 redirect 했지만 메세지가 잘 보존됨을 alert 창을 통해 확인할 수 있다.


ModelAndView 타입으로 반환

ModelAndView 타입으로 반환하는 경우 modelview 정보를 한 번에 담아서 반환한다.String 타입으로 반환하는 것과 마찬가지로 forwardredirect를 모두 사용할 수 있으며, RedirectAttribute 사용도 가능하다.

1. view name 반환(forward)

GET 방식의 /modelandview 요청을 전달한다.

<!--/resources/templates/main.html-->

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>main</title>
</head>
<body>
    <!--... 위에서 작성한 내용 생략-->
    
    <h3>ModelAndView로 뷰 이름 반환하기</h3>
    <button onclick="location.href='modelandview'">ModelAndView로 뷰 이름 반환</button>
</body>
</html>

 

발생하는 요청을 매핑할 Controller의 핸들러 메소드이다.

핸들러 어댑터가 핸들러 메소드를 호출하고 반환받은 문자열을 ModelAndView로 만들어 dispatcherServlet에 반환한다.

이 때 문자열을 반환해도 되지만 ModelAndView를 미리 만들어 반환할 수도 있다.

package com.ohgiraffers.viewresolver;

@Controller
public class ResolverController {

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

        // Model 객체에 attribute 저장
        mv.addObject("forwardMessage", "ModelAndView를 이용한 모델과 뷰 반환");
        // View 객체에 논리적 뷰 이름 설정
        mv.setViewName("result");

        return mv;
    }
}

view resolver가 올바르게 동작하였음을 응답 화면을 통해 확인할 수 있다.

2. redirect

<!--/resources/templates/main.html-->

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>main</title>
</head>
<body>
   
    <!--... 위에서 작성한 내용은 생략-->
   
    <h3>ModelAndView로 redirect하기</h3>
    <button onclick="location.href='modelandview-redirect'">ModelAndView로 redirect</button>

</body>
</html>

 

발생하는 요청을 매핑할 Controller의  핸들러 메소드이다. 

ModelAndView 객체에서도 접두사로 redirect: 를 붙이면 forward 되지 않고 redirect 된다.

package com.ohgiraffers.viewresolver;

@Controller
public class ResolverController {

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

        mv.setViewName("redirect:/");

        return mv;
    }
}

button 클릭 시 / 경로로 redirect 된다.

 

3. RedirectAttributes

GET 방식의 /modelandview-redirect-attr 요청을 전달한다.

<!--resources/templates/main.html-->

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>main</title>
</head>
<body>
  
    <h3>ModelAndView로 redirect & flashAttibute 추가하기</h3>
    <button onclick="location.href='modelandview-redirect-attr'">ModelAndView로 redirect & flashAttibute</button>

</body>
</html>

 

발생하는 요청을 매핑할 Controller의 핸들러 메소드이다.

ModelAndView 사용 시에도 동일하게 RedirectAttributes 타입을 통해 redirect 시 속성 값을 지정할 수 있다.

package com.ohgiraffers.viewresolver;

@Controller
public class ResolverController {

    // ... 위에서 작성한 내용 생략

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

        rttr.addFlashAttribute("flashMessage2", "리다이렉트 attr 사용하여 redirect...");
        mv.setViewName("redirect:/");

        return mv;
    }
}

 

응답 시 requestScope에 보존된 flashMessage2을 꺼내 alert 창에 띄운다.

<!--resources/templates/main.html-->

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>main</title>
</head>
<body>

    <!--앞에서 작성된 부분 생략-->

    <script>
        const flashMessage2 = `[[${ flashMessage2 }]]`;
        if(flashMessage2) alert(flashMessage2);
    </script>

</body>
</html>