Spring - 뷰 리졸버를 이용한 뷰 연결하기

제훈·2024년 8월 13일

Spring

목록 보기
10/18

뷰 리졸버를 이용한 뷰 연결하기

Spring MVC 패턴의 요청 처리 과정이다.

  1. 요청이 들어온다.
  2. 우선 필터를 거쳐서 디스페처 서블릿으로
  3. 핸들러 매핑에서 매핑 후
  4. controller 가기 전 인터셉터 거친 뒤(preHandle) 도착
  5. 비즈니스 로직 처리
  6. 다시 컨트롤러에서 디스페처 서블릿으로 갈 때 인터셉터 (postHandle)
  7. 뷰 리졸버에서 뷰 찾기
  8. 응답

이렇게 있을 때 7번의 뷰 리졸버를 이용한 뷰 연결하는 것을 Controller와 연관지어서 알아보자.

컨트롤러에서는 ModelAndView를 반환하는데 그것을 알맞은 View로 전달하기 위해 DispatcherServlet에 의해 뷰 리졸버가 호출된다.

즉, 뷰 리졸버는 ModelAndView 객체를 View 영역으로 전달하기 위해 알맞은 View 정보를 설정하는 역할을 한다.

forwarding 과 redirect 를 활용해서 알아볼 것이다.


반환한 String이 뷰 리졸버로 간다고 가정하고 하는 것이다.

기본 세팅

mainController

@Controller
public class MainController {

     * 설명.
     *  뷰 리졸버 인터페이스를 구현한 ThymeleafViewResolver가 현재 처리하게 된다.
     *  접두사(prefix) : resources/templates/
     *  접미사(suffix) : .html
     *  핸들러 메소드가 반환하는 String 값 앞 뒤에 접두사 및 접미사를 붙여 view 를 찾게 된다.
     */

    @RequestMapping(value={"/", "/main"})
    public String main() {
        return "main";
    }
}

main.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1 align="center">뷰 리졸버를 이용한 뷰 연결하기 (feat.forwarding VS redirect)</h1>

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

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

    <!-- script 를 써서 javascript 문법 사용 가능-->
    <script>
        console.log('test');
        const message1 = `[[${message1}]]`;
        console.log(message1);
    </script>

    <h3>문자열로 뷰어를 반환하면서 flashAttribute 추가하기</h3>
    <button onclick="location.href='string-redirect-attr'">문자열로 뷰 이름 반환하여 리다이렉트</button>
    <script>
        const flashMessage1 = `[[${flashMessage1}]]`;
        console.log(flashMessage1);
    </script>

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

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

    <script>
        const message2 = `[[${param.message2}]]`;
        console.log(message2);
    </script>

    <h3>ModelAndView로 redirect 하면서 flashAttribute 추가</h3>
    <button onclick="location.href='modelandview-redirect-attr'">ModelAndView로 뷰 이름 반환하여 리다이렉트 & flash attr 사용하기</button>
    <script>
        const flashMessage2 = `[[${flashMessage2}]]`;
        // console.log(flashMessage2);
        if (flashMessage2) {
            alert(flashMessage2); // flash 한 번만 쓰는 용도여서 flash가 아니라면 새로고침할 때마다 계속 이 메시지가 뜬다.
        }
    </script>
</body>
</html>

result.html

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

<h1 align="center" th:text="${forwardMessage}"></h1> 부분은 문자열로 뷰 이름 반환할 때만 사용한다.


화면 사진


String을 반환해주는 ResolverController

1. 문자열로 뷰 이름 반환하기

일단은 문자열로 뷰 이름을 반환해주는 첫 번째 예시를 해보자.

@Controller
public class ResolverController {
    /* 설명. 서블릿 때와 마찬가지로 포워딩을 통해 값을 전달할 수 있다. */
    @GetMapping("string")
    public String stringReturning(Model model) {
        model.addAttribute("forwardMessage", "문자열로 뷰 이름 반환");

        return "result";
    }
}

실행 결과 화면

forwarding은 잘 되는 것을 볼 수 있다.

그럼 Redirect도 잘 될까??


2. 문자열로 redirect

Controller에 추가

    @GetMapping("string-redirect")
    public String stringRedirect(Model model) {
        model.addAttribute("message1", "문자열로 뷰 이름 반환하여 리다이렉트"); // 이건 안 되는 것을 보여주려고 만들었다.
        // 위의 상태로 해서 개발자 도구를 킨 채로 버튼을 눌러도 변화가 없다..

        return "redirect:/";
    }

서블릿 때와 마찬가지로 리다이렉트를 하지만, 파라미터를 활용하지 않고서는 전달할 수 없다.

(스프링은 해법을 제시하니 그것 또한 알아볼 것이다.)


3. 문자열로 뷰어를 반환하면서 flashAttribute 추가하기

RedirectAttribute 라는 객체에 attribute를 담으면 리다이렉트 시에도 값이 전달된다.

한 번 해보자.

Controller에 추가

    @GetMapping("string-redirect-attr")
    public String stringRedirectFlashAttribute(RedirectAttributes redirectAttributes) {
        redirectAttributes.addFlashAttribute("flashMessage1", "리다이렉트 attr 사용해 redirect");

        return "redirect:/";
    }

실행 결과 화면

개발자 도구에서 확인할 수 있다.


ModelAndView로 반환하기

4. ModelAndView를 이용한 forward

그럼 위에서 말한대로 원래는 Controller는 String이 아닌 ModelAndView 형태로 반환해주니 그렇게 해보려고 한다.

그러면서 이제 result.html은

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

이렇게 바꿔줘야 한다.

바꿔준 뒤 활용해보자.

Controller에 추가

    @GetMapping("modelandview")
    public ModelAndView modelAndViewTest(ModelAndView mv) {
        mv.addObject("message2", "ModelAndView를 이용한 forward");
        mv.setViewName("result");

        return mv;
    }

실행 결과 화면

단순 forward 반환 시에는 Model 만 활용했을 때와 별 차이가 없다. (반환형이 ModelAndView로 바뀐 정도)


5. ModelAndView를 이용한 redirect

Controller에 추가

    @GetMapping("modelandview-redirect")
    public ModelAndView modelAndViewRedirectTest(ModelAndView mv) {
        mv.addObject("message2", "ModelAndView를 이용한 redirect");
        mv.setViewName("redirect:/"); // `redirect:/?message2=ModelAndView를+이용한+forward`

        return mv;
    }

redirect 시에는 ModelAndView에 addObject로 담긴 key와 value 는 parameter로 리다이렉트 된다. (쿼리스트링 형태)


실행 결과 화면


6. ModelAndView로 redirect 하면서 flashAttribute 추가

Controller에 추가

    @GetMapping("modelandview-redirect-attr")
    public ModelAndView modelAndViewRedirectFlashAttribute(ModelAndView mv, RedirectAttributes redirectAttributes) {
        redirectAttributes.addFlashAttribute("flashMessage2", "ModelAndView를 이용한 redirect attribute");
        mv.setViewName("redirect:/");

        return mv;
    }

실행 결과 화면

왜 이건 팝업으로 뜰까?

그 이유는 바로 main.html에서 alert를 활용했기 때문이다.

        if (flashMessage2) {
            alert(flashMessage2); 
        }

flash는 한 번만 쓰는 용도여서 flash가 아니라면 새로고침할 때마다 계속 이 메시지가 뜨는데, 이것을 적용하지 않으면 어떤 이벤트가 발생했을 때 새로고침을 하면 해당 이벤트에 대한 팝업이 계속 뜨는 것이다.

나도 포인트가 적립됐다든지 이벤트로 직접 구현해보질 않아서 발생했을 때 flashMessage로 하지 않았을 때 포인트가 적립됐다고 하는 만큼 누적되는건지 궁금하긴 하다.. 알아보고 정리하도록 하겠다.

profile
백엔드 개발자 꿈나무

0개의 댓글