@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
'JAVA > Spring' 카테고리의 다른 글
[Spring Security] JWT + OAuth2.0 적용해보기 - (2) (0) | 2023.02.02 |
---|---|
[Spring Security] JWT + OAuth2.0 적용해보기 - (1) (0) | 2022.12.01 |
댓글