요즘은 백앤드와 프론트앤드를 완전히 나눠서 개발하기 때문에 백앤드에서 ModelAndView 를 사용할 일은 거의 없다. 즉, 백앤드에서는 Api개발에 그외 성능 개선이나 인프라 적인 요소에 집중하게 된다. 하지만 일부 간단한 프로젝트에서는 아직도 백앤드에서 풀스택으로 개발하는 경우가 많으며 그때는 ModelAndView 가 많이 사용된다.
이 경우 Controller 에 @RestController를 지정해야 할까 @Controller 를 지정해야 할까? 정석은 api형태의 컨트롤러와 view형태의 컨트롤러를 클래스로 분리해서 각각 @RestController 와 @Controller 를 지정하는 것인데 view형태의 컨트롤러를 사용한다는 것은 이미 소규모 프로젝트라는 말이고 굳이 컨트롤러를 나눠서 작성할 필요까진 없는 경우가 대부분이다.
이때는 기본적으로 @RestController 만 지정해도 모두 처리가 가능한데 리턴타입이 ModelAndView 일 경우 view로 이동하고 그 외 타입일 경우 json 문자열로 직렬화를 시도한다.
그런데 @RestController 를 지정할 경우 @ModelAttribute 를 사용할 때 주의가 필요하다. 알다시피 @ModelAttribute은 VO, Map 등으로 파라미터를 타입형태로 받을 때 사용되고 기본적으로 파라미터로 넘어온 값을 response에도 포함하기 때문에 파라미터로 넘어온 값을 계속 가지고 이동해야 하는 게시판 리스트에 많이 사용된다.
사용방법은 기본적으로 아래와 같다.
@GetMapping("list")
public String getList(
@ModelAttribute(value="pageModel") PageModel pageModel
, Model model
){
model.addAttribute("list", ...);
model.addAttribute("count", ...);
return "list";
}
이렇게 되면 Thymeleaf 를 사용하는 기준 list.html 로 이동할 것이고 response 에는 위에서 추가한 list, count 외에 pageModel 이 자동으로 포함될 것이다.
그런데 위에서 말했듯이 @RestController를 사용할 경우 리턴타입이 ModelAndView 일 때만 view 로 이동하기 때문에 view로 이동을 원한다면 ModelAndView 를 리턴하도록 아래와 같이 변경해야 한다.
@GetMapping("list")
public ModelAndView getList(
@ModelAttribute(value="pageModel") PageModel pageModel
){
ModelAndView modelAndView = new ModelAndView("list");
modelAndView.addObject("pageModel", pageModel);
modelAndView.addObject("list", ...);
modelAndView.addObject("count", ...);
return modelAndView;
}
보편적인 방식으로 처리가 되지 않아 방식을 바꾸긴 했지만 클라이언트에서 넘겨주는 파라미터가 아닌 Model model 를 없앨 수 있어서 오히려 더 직관적인 소스가 되었다.