본문 바로가기
JAVA/Spring

[Spring] @RequestParam vs @ModelAttribute vs @RequestBody

by 민트맛녹차 2022. 8. 1.

@RequestParam, @ModelAttribute, @RequestBody 는 Spring에서 클라이언트 측에서 보낸 요청값을 객체나 변수로 바인딩 하기위해 사용되는 어노테이션들이다.

 

@RequestParam

@RequestParam은 Servlet request parameters를 method argument로 bind한다.  이때, Servlet request parameter는 query parameter 나 form data를 뜻한다. 

@RequestParam을 사용한 method argument는 기본적으로 required이지만, required=false를 선언하거나 argument를 Optional로 선언함으로써 선택적으로 사용할 수 있다.

타겟이 되는 method parameter가 String이 아니라면 Type Conversion이 자동으로 적용된다.  간단한 type들은 기본적으로 지원되지만 커스텀하기를 원한다면 Converter나 Formatter를 사용해야 한다.

@RequestParam은 생략가능하다. 기본적으로 argument가 simple value type이거나 다른 argument resolver에 의해 해결되지 않는다면 @RequestParam이 있는 것으로 다뤄진다.

 

@ModelAttribute

method argument에 @ModelAttribute를 사용하면 model의 attribute에 접근할 수 있다. Servlet request parameter의 이름과 method argument의 이름이 일치한다면 데이터 바인딩을 해준다.

다음과 같은 방법으로 인스턴스를 소싱한다.

  • @ModelAttribute method를 통해 추가된 model을 통해서
  • @SessionAttribute 에 model attribuet가 있다면 Http Session 을 통해서
  • model attribuet name이 requst valeu name과 일치하는 Converter를 통해서 
  • 기본 생성자를 통해서
  • Servlet request parameter와 일치하는 인자를 가지는 primary 생성자를 통해서(인자를 많이 가지는 생성자가 primary 생성자인듯 하다)
  • 추가로, 생성자로 주입하지 못한 변수들은 Setter를 통해 값을 할당한다.

참고로, @ModelAttribute method는 Controller에 존재하는 HandlerMethod에서 공통으로 참조해야하는 Model정보가 있다면 해당 Model정보의 초기화 목적으로 사용한다.

 

model attribute 인스턴스가 생성된 후 데이터 바인딩이 적용된다. WebDataBinder 클래스가 Servlet request parameter 이름을 바인딩 할 Object 필드와 매칭시킨다. 필요한 경우 Type Conversion이 적용된 후 필드가 채워진다.

데이터 바인딩 중 BindException 같은 에러가 날 수 있는데 BindingResult arguement를 @ModelAttribute 바로 옆에 넣어 에러를 체크할 수 있다.

데이터 바인딩 후, javax.validation.Valid 어노테이션이나 스프링의 @Validated 어노테이션을 추가하여 자동으로 유효성 검사를 할 수 있다.

@ModelAttribute는 생략이 가능하다.  기본적으로 argument가 simple value type이거나 다른 argument resolver에 의해 다뤄지지 않는다면 @ModelAttribute이 있는 것으로 다뤄진다.

 

@RequestBody

@RequestBody는 HttpMessageConverter를 통해  request body를 읽어 Object로 역직렬화한다.

 javax.validation.Valid 어노테이션이나 스프링의 @Validated 어노테이션을 추가하여 자동으로 유효성 검사를 할 수 있다. 기본적으로 validation error는 MethodArgumentNotValidException을 일으켜 400 응답을 하게 한다. Errors 나 Binding Result를 사용해  validation error를 조작할 수 있다.

스프링에서 Json의 역직렬화를 담당하는 것은 MappingJackson2HttpMessageConverter 이다. @RequestBody로 데이터를 받는다면, Jackson의 ObjectMapper의 내부 메서드를 사용해 변환하기 때문에 기본 생성자와 Getter는 필요하지만 Setter는 필요 없다.

 

요약

@RequestParam

  • Servlet request parameter를 1개 바인딩

 

@ModelAttribute 

  • Servlet request parameter를 Object로 바인딩
  • WebDataBinder 클래스 사용

 

@RequestBody

  • Request Body를 Object로 역직렬화
  • HttpMessageConverter 클래스 사용

 

 

 

셋의 차이를 비교하려다 argument resolver, Converter, Formatter, HttpMessageConverter 등 모르는 지식만 더 늘어났다. 이 부분은 나중에 정리하도록 하겠다.

 

 

참조
https://docs.spring.io/spring-framework/docs/current/reference/html/web.html#mvc-ann-requestparam
https://docs.spring.io/spring-framework/docs/current/reference/html/web.html#mvc-ann-modelattrib-method-args
https://docs.spring.io/spring-framework/docs/current/reference/html/web.html#mvc-ann-requestbody
https://parkadd.tistory.com/70
https://ncucu.me/52

 

 

댓글