가장 먼저 알아야 할 점은 우리는 뷰 페이지에서 파라미터 값을 받아온다는 것입니다.

 

파라미터 값을 어떻게 가져올지에 대한 고민에 대한 결과물이 아래와 같은 방식이라고 생각합니다.

 

애노테이션을 알기 전에 작동 방식에 대해 알면 이해가 좀 더 편하지 않을까 싶어 간단히 정리했습니다.

 

  • HttpServletRequest
    • HttpServlet에 대한 요청 정보를 제공하도록 ServletRequest를 확장한 인터페이스를 사용한다.
    • HttpServletRequest은 서블릿 컨테이너가 생성하며 서블릿의 service() 메소드의 매개변수로 보낸다.
    • service()는 Http Method에 따라 Get 방식 혹은 Post 방식으로 위임하여 처리한다.
    • 즉, HttpServletRequest는 HttpServlet의 요청을 받아서 꺼내서 쓸 수 있다는 것이다.
    • 스프링에서는 HttpServletRequest를 직접 사용하지 않고 다양한 애노테이션을 사용해서 데이터를 가져온다.
  • @RequestParam
    • @RequestParam("이름") [데이터타입] [변수명] : 이름과 변수명이 같다면 이름은 생략할 수 있다.
    • request.getParameter("이름")과 같은 코드라고 생각하면 편하다.
    • 참고로 @RequestParam도 생략할 수 있지만 명확성을 위해서 지우지 않는 게 좋다고 생각한다.
    • 이 방식은 해당 파라미터를 모두 직접 작성해야 한다.
    • 파라미터가 많아서 생기는 문제를 해결하기 위해 요청 파라미터를 하나의 객체에 값을 넣어서 사용한다.
    • 그 방식으로 우리는 Model이라는 인터페이스를 사용한다.
  • Model & ModelAndView
    • Model 
      • 해당하는 파라미터 값을 Model 객체에 담아서 사용한다.
      • 즉, Model은 데이터만을 전달하기 위한 객체이다.
      • model.addAttribute("[속성명]",데이터) 방식으로 모델 객체에 데이터를 담아서 사용한다.
      • 속성명이 view로 전달된다.
      • 마지막으로 view 이름을 String으로 return하는 방법을 사용한다.
    • ModelAndView
      • 데이터와 뷰의 이름을 함께 전달하는 객체이다.
      • model.addObject(데이터) : 데이터를 모델 객체에 담는다.
      • model.setviewName("뷰페이지명") : View를 세팅한다.
      • String 객체 대신에 ModelAndView를 return 한다.
    • 최근에는 ModelAndView를 잘 사용하지 않는다.
    • 이 과정을 쉽게 하기 위해서 @ModelAttribute가 나왔기 때문이다.
  • @ModelAttribute
    • @ModelAttribute("이름") [객체명] [변수명] : model.addAttribute("이름", 데이터) 형태로 전달된다.
      • 이름과 변수명이 같다면 이름을 생략할 수 있다.
      • 이름을 생략하면 model.addAttribute("[객체명]", 데이터) 형태로 전달된다.
    • 해당 객체에 요청 파라미터의 값을 모두 넣어서 사용한다.
    • 이해를 돕자면 @ModelAttribute는 아래와 같은 과정으로 진행된다.
      1. @ModelAttribute 뒤에 있는 객체를 생성한다.
      2. 요청 파라미터의 이름으로 해당 객체의 프로퍼티를 찾는다.
      3. 해당 프로퍼티의 setter를 호출해서 파라미터의 값을 입력한다.
    • 추가적으로 @RequestParam과 달리 검증 작업을 내부적으로 한다.
    • 그래서 보통 Errors 객체나 BindingResult 객체를 @ModelAttribute가 붙은 파라미터 바로 뒤에 선언해서 검증 처리를 실시한다.
//Model과 @RequestParam 사용

@PostMapping("/edit")
public String updateItem(@RequestParam("itemname") String itemname,
                         @RequestParam("quantity" int quantity,
                         Model model) {
  
  Item item = new Item(itemname, quantity);
  
  itemService.updateItem(item);
  
  model.addAttribute("item", item);
  
  return "[해당 뷰 페이지 위치]";
}

===================================================================================

//@ModelAttribute 사용

@PostMapping("/edit")
public String updateItem(@Valid @ModelAttribute("item") ItemDto form,
                         BindingResult bindingresult) {
 
  itemService.updateItem(itemId, form);
  return "[해당 뷰 페이지 위치]";
}

------------------------------------------------------------------------------------
//View 페이지
<form th:action th:object="${item}" method="post">

//[@ModelAttribute("item")]와 [th:object="${item}"]로 일치해야 값을 사용할 수 있다.

===================================================================================

@PostMapping("/edit")
public String updateItem(@Valid @ModelAttribute ItemDto form
                         BindingResult bindingresult) {
 
  itemService.updateItem(itemId, form);
  return "[해당 뷰 페이지 위치]";
}

----------------------------------------------------------------------------------
//View 페이지
<form th:action th:object="${itemDto}" method="post">

//[@ModelAttribute ItemDto]와 [th:object="${itemDto}"]로 일치해야 값을 사용할 수 있다.

정리

@RequestParam을 사용하면 각각의 정보를 개별로 받아온 데이터를 직접 사용할 수도 있고,

 

사용할 객체에 담은 다음 Model 객체에 다시 담아서 정보를 전달한다.


@ModelAttribute("item") ItemDto form = model.addAttribute("item", new ItemDto());
-> html에서 객체 이름을 'item'으로 받아온다. [th:object="${item}"]

@ModelAttribute ItemDto form = model.addAttribute("ItemDto", new ItemDto());
-> html에서 객체 이름을 'ItemDto'으로 받아온다. [th:object="${itemDto}"]