Spring MVC - Model, ModelAndView, ModelMap

지니·2023년 8월 20일
0

spring

목록 보기
8/13

Model, ModelAndView, ModelMap의 차이점 그리고 @ModelAttribute에 대해서 알아보자

1. Model, ModelAndView, ModelMap란?

  • 스프링 프레임워크에서는 컨트롤러(Controller)에서 뷰(View)로 데이터를 전달하는 여러 가지 방법이 있다.
    이러한 방법들 중에서 스프링 MVC에서 사용되는 Model, ModelMap, ModelAndView의 사용에 대해 좀 더 상세하게 설명하겠다.

Model

  • Model은 뷰를 렌더링하는 데 사용되는 속성을 제공할 수 있는 가장 기본적인 개념이다. (스프링 MVC에서 컨트롤러와 뷰 사이의 데이터를 전달하는 역할을 하는 인터페이스이다.)

  • 뷰에 사용할 수 있는 데이터를 제공하려면, controller에서 데이터를 Model 객체에 추가하면 된다. 그러면 이 Model 객체는 뷰로 전달되어 뷰에서 사용될 수 있다.

  • Model에 데이터를 추가하는 방법은 addAttribute 메서드를 사용하면 된다. 예를 들어, model.addAttribute("message", "Hello, World!");와 같이 사용할 수 있다.

  • 또한, 속성이 있는 맵을 Model 인스턴스와 병합할 수 있다.

예를 들어, 다음과 같이 사용할 수 있다.

@GetMapping("/showViewPage")
public String passParametersWithModel(Model model) {

    Map<String, String> map = new HashMap<>();
    map.put("spring", "mvc");

    model.addAttribute("message", "Baeldung");
    model.mergeAttributes(map);
    return "view/viewPage";

}

ModelAndView

  • ModelAndView는 값을 뷰로 전달하는 인터페이스이다. 이 인터페이스를 사용하면, 스프링 MVC에 필요한 모든 정보를 한 번에 반환할 수 있다.

  • ModelAndView 객체를 생성하고, 이 객체에 데이터와 뷰 이름을 설정한 후 컨트롤러에서 반환하면, 스프링 MVC는 이 ModelAndView 객체를 사용하여 뷰를 렌더링한다.

  • ModelAndView는 ModelView를 한 번에 처리할 수 있으므로, 편리하게 사용할 수 있다.

예를 들어, 다음과 같이 사용할 수 있다.

@GetMapping("/goToViewPage")
public ModelAndView passParametersWithModelAndView() {

    ModelAndView modelAndView = new ModelAndView("view/viewPage");
    modelAndView.addObject("message", "Baeldung");
    return modelAndView;

}

ModelMap

  • ModelMapModel 인터페이스를 구현한 클래스로, Map과 유사한 API를 제공한다.

  • Model 인터페이스와 마찬가지로, ModelMap도 뷰를 렌더링하는 데 사용되는 값을 전달하는 데 사용된다. 그리고 Model과 마찬가지로, ModelMap에 데이터를 추가하려면 addAttribute 메서드를 사용하면 된다.

  • ModelMap의 장점은 값을 컬렉션으로 전달하고, 이러한 값들을 마치 맵(키와 값을 가짐) 내에 있는 것처럼 처리할 수 있다는 것이다.

예를 들어, 다음과 같이 사용할 수 있다.

@GetMapping("/printViewPage")
public String passParametersWithModelMap(ModelMap map) {

    map.addAttribute("welcomeMessage", "welcome");
    map.addAttribute("message", "Baeldung");
    return "view/viewPage";

}

2. 컨트롤러에서는 이 셋중에 어떤것을 선택해서 사용해야 할까?

  • 이들 모두 뷰에 데이터를 전달하는 방법이지만, 사용 방법과 적용 상황에 따라 적절한 것을 선택하면 된다.

  • 예를 들어, 단순히 데이터를 전달하는 경우에는 Model이나 ModelMap을 사용할 수 있고, 뷰 이름과 함께 데이터를 전달하려면 ModelAndView를 사용할 수 있다.

  • 만약 HTTP 요청 파라미터를 객체에 바인딩하거나 특정 메소드의 반환값을 모델에 추가하고싶다면 그때는 @ModelAttribute를 사용하면 된다.


3. @ModelAttribute

  • 이 어노테이션은 HTTP 요청 파라미터를 자바 객체에 바인딩하는 역할을 한다.

  • 예를 들어, 폼 데이터를 객체로 받아오는 경우에 사용된다. 또한, @ModelAttribute 어노테이션은 메소드 레벨에서도 사용될 수 있으며, 이 경우 해당 메소드의 반환값이 모델에 자동으로 추가된다.

1. 메서드 인자에 적용

  • @ModelAttribute가 붙은 메소드 인자는 HTTP 요청 파라미터를 해당 객체에 바인딩하는 역할을 한다. 이는 주로 폼 데이터를 객체로 받아오는 경우에 사용된다.

예를 들어, 사용자로부터 받은 사용자 정보를 User 객체에 바인딩하려면 다음과 같이 사용할 수 있다.

@PostMapping("/user")
public String submit(@ModelAttribute User user) {
    // user 객체는 요청 파라미터를 바인딩 받은 상태
    // 여기서 비즈니스 로직 수행
    return "userView";
}

2. 메서드 자체에 적용

  • @ModelAttribute가 붙은 메소드는 뷰가 렌더링되기 전에 항상 먼저 실행되며, 이 메소드의 반환값이 모델에 추가된다. 이를 통해 여러 뷰에서 공통으로 사용되는 참조 데이터를 제공하는 데 유용하다.

예를 들어, 모든 뷰에서 사용 가능한 설정 정보를 제공하려면 다음과 같이 사용할 수 있다.

@ModelAttribute("settings")
public Settings getSettings() {
    return settingsService.getSettings();
}
  • 이 경우, getSettings() 메서드가 반환하는 Settings 객체는 "settings"라는 이름으로 모델에 자동으로 추가되며, 뷰에서는 이 "settings" 속성을 사용하여 설정 정보에 접근할 수 있다.

  • 이렇게 @ModelAttribute는 스프링 MVC에서 매우 유용하게 사용되는 어노테이션이다. 사용 방법은 상황에 따라 달라질 수 있으므로, 필요에 따라 적절하게 사용하면 된다.

3. @ModelAttribute - 메서드 자체적용 상세설명

  • @ModelAttribute 어노테이션이 붙은 메서드가 반환하는 것은 뷰가 아닌 데이터이다. 이 메서드가 반환하는 데이터는 자동으로 모델에 추가되며, 이 모델은 뷰를 렌더링하는 데 사용된다.

  • 스프링 MVC에서는 컨트롤러 메서드가 반환하는 값이 기본적으로 뷰 이름으로 해석되지만, @ModelAttribute 어노테이션이 붙은 메서드는 이 규칙에서 예외이다. @ModelAttribute 어노테이션이 붙은 메서드는 뷰 이름을 반환하는 것이 아니라, 뷰에서 사용할 수 있는 데이터를 반환한다.

  • @ModelAttribute 어노테이션이 붙은 메서드는 해당 컨트롤러의 모든 @RequestMapping 메서드가 호출되기 전에 자동으로 호출된다. 따라서 이 메서드가 반환하는 데이터는 해당 컨트롤러의 모든 뷰에서 사용할 수 있다.

예를 들어, 다음과 같은 컨트롤러가 있다고 가정해 보자

@Controller
public class MyController {

    @ModelAttribute("settings")
    public Settings getSettings() {
        return settingsService.getSettings();
    }

    @GetMapping("/view1")
    public String view1() {
        return "view1";
    }

    @GetMapping("/view2")
    public String view2() {
        return "view2";
    }
}
  • 이 경우에는, "/view1" 또는 "/view2" URL에 대한 요청이 있을 때마다 getSettings() 메소드가 먼저 호출되고, 이 메소드가 반환하는 Settings 객체는 "settings"라는 이름으로 모델에 추가된다.

  • 그런 다음, 이 모델은 "view1" 또는 "view2" 뷰를 렌더링하는 데 사용된다. 따라서 "view1" 또는 "view2" 뷰에서는 "settings" 속성을 사용하여 설정 정보에 접근할 수 있다.


4. @ControllerAdvice와 @ModelAttribute는 관계가 있을까?

  • @ControllerAdvice 어노테이션과 @ModelAttribute 어노테이션을 함께 사용하면, 모든 컨트롤러에서 공통으로 사용되는 모델 속성을 정의할 수 있다.

  • @ControllerAdvice 어노테이션이 붙은 클래스는 모든 컨트롤러에 대해서 공통적으로 적용되는 코드를 정의하는 데 사용된다.

  • @ControllerAdvice를 적용한 클래스 내부에서 @ModelAttribute 어노테이션을 사용하면, 해당 속성이 모든 컨트롤러와 뷰에서 적용되어 사용할수가 있다.

예를 들어, 다음과 같은 @ControllerAdvice 클래스를 정의할 수 있다.

@ControllerAdvice
public class GlobalControllerAdvice {

    @ModelAttribute("settings")
    public Settings getSettings() {
        return settingsService.getSettings();
    }
}
  • 이 경우, getSettings() 메소드가 반환하는 Settings 객체는 "settings"라는 이름으로 모델에 추가되며, 이 모델은 모든 컨트롤러의 모든 뷰에서 사용할 수 있다.

  • 따라서 @ControllerAdvice@ModelAttribute를 함께 사용하면, 애플리케이션 전체에서 공통으로 사용되는 모델 속성을 한 곳에서 관리할 수 있다. 이는 코드의 중복을 줄이고 유지 관리를 용이하게 하는 데 도움이 된다.


5. @ModelAttribute, @ControllerAdvice + @ModelAttribute의 차이점

  • @ModelAttribute를 일반 컨트롤러 클래스 안에 선언하는 경우와 @ControllerAdvice 클래스 안에 선언하는 경우의 주요 차이점은 적용 범위이다.

일반 컨트롤러 클래스에서의 @ModelAttribute 사용

  • 일반적인 컨트롤러 클래스에서 @ModelAttribute 어노테이션이 붙은 메소드는 해당 컨트롤러의 @RequestMapping 메소드가 호출되기 전에 먼저 호출된다.

  • 따라서 이 메소드가 반환하는 객체는 해당 컨트롤러의 모든 뷰에서 사용할 수 있다. 그러나 이 객체는 해당 컨트롤러에서만 사용할 수 있으며, 다른 컨트롤러에서는 사용할 수 없다.

  • 이 방법의 장점은 각 컨트롤러에서 필요한 모델 속성을 직접 관리할 수 있다는 것이다.

  • 단점은 같은 모델 속성이 여러 컨트롤러에서 필요한 경우 코드의 중복이 발생할 수 있다는 것이다.

@ControllerAdvice 클래스에서의 @ModelAttribute 사용

  • @ControllerAdvice 클래스에서 @ModelAttribute 어노테이션이 붙은 메소드는 모든 컨트롤러의 @RequestMapping 메소드가 호출되기 전에 먼저 호출된다. 따라서 이 메소드가 반환하는 객체는 모든 컨트롤러의 모든 뷰에서 사용할 수 있다.

  • 이 방법의 장점은 애플리케이션 전체에서 공통으로 사용되는 모델 속성을 한 곳에서 관리할 수 있다는 것이다. 이는 코드의 중복을 줄이고 유지 관리를 용이하게 한다.

  • 단점은 모든 컨트롤러와 뷰에서 이 모델 속성이 사용 가능하므로, 필요하지 않은 경우에도 이 메소드가 호출되고 모델 속성이 생성될 수 있다는 것이다.

  • 따라서 어떤 방법을 사용할지는 애플리케이션의 요구 사항과 개발 팀의 선호에 따라 달라질 수 있다.

공통으로 사용되는 모델 속성이 많은 경우에는 @ControllerAdvice를 사용하는 것이 좋을 수 있다.
반면, 각 컨트롤러에서 고유한 모델 속성을 관리해야 하는 경우에는 일반 컨트롤러 클래스에서 @ModelAttribute를 사용하는 것이 적합할 수 있다.

profile
탐구하는 Backend 개발자

1개의 댓글

comment-user-thumbnail
2024년 6월 20일

잘 읽었습니다!!

답글 달기

관련 채용 정보