[LG CNS AM Inspire Camp 1기] SpringBoot (4) - [LAB - 3] View는 어떻게 찾나요?

정성엽·2025년 2월 4일
1

LG CNS AM Inspire 1기

목록 보기
38/53

INTRO

이번에는 Spring MVC 패턴을 적용하면서 궁금했던 HTML을 불러오는 부분을 정리해보려고 한다.


1. String 반환과 View Resolver

미니 프로젝트를 진행하면서 궁금했던 또 다른 부분은 바로 컨트롤러 코드에 있었다.

우선 코드를 살펴보자

Sample Code

@Controller
public class UserController {
    @Autowired()
    private UserService userService;

    @GetMapping("/")
    public ModelAndView userSelect() {
        ModelAndView modelAndView = new ModelAndView("/user/userList");
        List<UserProfileDto> list = userService.getAllUsers();
        return modelAndView.addObject("list", list);
    }

    @GetMapping("/userAdd.do")
    public String goToUserAdd() {
        return "/user/userAdd";
    }

    @PostMapping("/user/add")
    public String addUser(UserProfileDto userProfileDto, RedirectAttributes redirectAttributes) {
        Boolean isSuccess = userService.addUser(userProfileDto);
        if (isSuccess) {
  redirectAttributes.addFlashAttribute("success", "사용자가 성공적으로 등록되었습니다.\n(메인으로 돌아가기)");
            return "redirect:/userAdd.do";
        } else {
redirectAttributes.addFlashAttribute("fail", "사용자 등록에 실패했습니다.\n[DB Error]");
            return "redirect:/userAdd.do";
        }
    }

    @GetMapping("/userUpdate.do")
    public ModelAndView openUserDetail(@RequestParam("userId") Long userId) {
        ModelAndView modelAndView = new ModelAndView("/user/userUpdate");
        UserProfileDto userProfileDto = userService.selectUserDetail(userId);
modelAndView.addObject("userProfileDto", userProfileDto);
        return modelAndView;
    }
    ...
}

위에서 작성된 UserController의 코드를 살펴보면, ModelAndView 를 반환하는 메서드와 String 을 반환하는 메서드가 존재한다.

ModelAndView는 View Template을 생성하는 시점에 매핑되는 HTML 파일의 경로를 파라미터로 전달한다.

이러한 방식으로 적절한 HTML을 반환하고 있음을 직관적으로 이해할 수 있다.

하지만, String으로 단순한 문자열을 반환하는 경우에는 어떻게 적절한 View Template을 찾아서 반환할 수 있는 걸까?

그 해답은 바로 ViewResolver에 있다.

💡 ViewResolver의 동작 방식

Spring MVC에서 String을 반환하면 다음과 같은 과정이 일어난다.

Controller에서 String 반환하는 경우

  • 컨트롤러에서 String 반환
  • ViewResolver가 해당 문자열을 받아서 실제 뷰 경로로 변환
  • 접두사(prefix) 추가
    - EX) "/WEB-INF/views/"
  • 접미사(suffix) 추가
    - EX) ".html"
  • 최종 경로의 뷰 파일을 찾아서 렌더링

즉, String으로 반환하면 접두사와 접미사를 추가하여 뷰 경로를 찾아내고 이를 렌더링하는 방식으로 동작한다!

💡 @Controller vs @RestController

여기서 중요한 점은 이러한 ViewResolver의 동작이 @Controller@RestController 에서 다르다는 것이다.

두가지 어노테이션을 정리하면 다음과 같다.

@Controller

  • ViewResolver를 통해 뷰를 찾아 렌더링
  • 문자열 반환 시 뷰 이름으로 인식
  • 주로 웹 페이지를 반환할 때 사용

@RestController

  • ViewResolver를 사용하지 않음
  • 문자열 반환 시 그 문자열 자체를 반환
  • 주로 데이터(JSON/XML)를 반환할 때 사용

이러한 차이점 때문에 같은 코드라도 다른 결과를 볼 수 있다.

Sample Code

// @Controller의 경우
return "/user/userAdd";  // userAdd.html 파일을 찾아 렌더링

// @RestController의 경우
return "/user/userAdd";  // 문자열 "/user/userAdd"를 그대로 반환

따라서, 데이터를 주고받는 목적이라면 @RestController를 사용하고 아니라면 @Controller를 사용하면 된다.

@Controller를 사용하면 String으로 리턴되는 경우 ViewResolver가 경로로 인식하여 적절한 템플릿 HTML을 찾아서 렌더링한다!


OUTRO

사실 이 미니 프로젝트를 진행하면서 정리하려고 목표했던 내용은 더 있다.

예를들어, 필자는 장바구니 같은 기능을 구현했는데 기존에 사용하던 방식(Html -> Controllor로 요청 -> 적절한 View Template 반환)을 사용하면 + 버튼을 눌러서 아이템을 추가할 때마다 리렌더링이 발생한다.

이런 문제를 DOM 요소를 직접 컨트롤하는 스크립트 코드를 추가해서 해결할 수 있었다.

하지만, 지금 정리하면서 생각해보니 SpringBoot 정리와는 조금 멀어지는 것 같아서 생략하려고 한다! 👊

Mini Project GitHub - 운동 루틴 관리 프로그램

profile
코린이

0개의 댓글

관련 채용 정보