티스토리 뷰
의역/오역이 있을 수 있고 잘못된 부분이 존재할 수 있습니다
요약
1. @RequestBody는 HttpMessageConverter가 HTTP Request Body 내의 데이터를 객체로 변환(역직렬화)하도록 시키는 애노테이션이다.
2. @Valid를 붙이면 검증을 할 수 있고, 실패 시 MethodArgumentNotValidException을 던진다.
3. application/json 타입의 경우 MappingJackson2HttpMessageConverter가 데이터를 객체로 역직렬화 해준다.
4. MappingJackson2HttpMessageConverter는 ObjectMapper를 사용하는데, 프로퍼티를 이용하기 때문에 getter / setter 둘 중 하나만 있으면 된다
@RequestBody
- Annotation indicating a method parameter should be bound to the body of the web request.
(메서드 파라미터가 web request(HTTP Request)의 body 에 있는 데이터를 통해 bind 될 것을 나타내는 애노테이션)
(굉장히 정직한 이름이다;;)
- The body of the request is passed through an HttpMessageConverter to resolve the method argument depending on the content type of the request.
(http body는 HttpMessageConverter에게 전달되어 처리된다.)
- Optionally, automatic validation can be applied by annotating the argument with @Valid.
(@Valid 애노테이션과 함께 사용하면 자동으로 검증이 적용된다)
@PostMapping("/accounts")
public void handle(@RequestBody Account account) {
// ...
}
- You can use the @RequestBody annotation to have the request body read and deserialized into an Object through an HttpMessageConverter.
(request Body를 읽고 역직렬화를 통해 데이터를 객체로 만드는 과정을 HttpMessageConverter가 해준다)
- By default, validation errors cause a MethodArgumentNotValidException, which is turned into a 400 (BAD_REQUEST) response.
(@Valid를 사용할 경우, 검증 실패 시 MethodArgumentNotValidException을 발생시킨다.)
- Alternatively, you can handle validation errors locally within the controller through an Errors or BindingResult argument
(예외를 바로 던지지 않고 컨트롤러에서 처리하고 싶다면 BindingResult를 뒤에 바로 붙여주면 된다)
@PostMapping("/accounts")
public void handle(@Valid @RequestBody Account account, BindingResult result) {
// ...
}
# HttpMessageConverter
- The spring-web module contains the HttpMessageConverter contract for reading and writing the body of HTTP requests and responses through InputStream and OutputStream.
(spring-web 모듈은 HttpMessageConverter를 기본적으로 포함하고 있다.
-> InputStream에서 HTTP request의 body를 읽는 역할 & OutputStream에서 HTTP response의 body에 데이터를 쓰는 역할을 담당한다)
- HttpMessageConverter instances are used on the client side (for example, in the RestTemplate) and on the server side (for example, in Spring MVC REST controllers).
(클라이언트 사이드에서는 RestTemplate, 서버 사이드에서는 RestController 구현 할 때 주로 사용된다.)
- Concrete implementations for the main media (MIME) types are provided in the framework and are, by default, registered with the RestTemplate on the client side and with RequestMappingHandlerAdapter on the server side (see Configuring Message Converters).
(HttpMessageConverter(인터페이스)의 구현체는 MIME 타입에 의해 정해진다
-> RequestMappingHandlerAdapter가 이를 판단하고 적절한 HttpMessageConverter를 사용할 수 있게 해준다)
<MIME 3대장>
text/* -> StringHttpMessageConverter
application/x-www-form-urlencoded -> FormHttpMessageConverter
application/json -> MappingJackson2HttpMessageConverter
# MappingJackson2HttpMessageConverter
- Implementation of org.springframework.http.converter.HttpMessageConverter that can read and write JSON using Jackson 2.x's ObjectMapper.
(Jackson 라이브러리의 ObjectMapper를 사용해서 JSON을 읽거나 쓰도록 만들어주는 HttpMessageConverter 구현체)
- This converter can be used to bind to typed beans, or untyped HashMap instances.
(typed beans(??) 또는 untyped HashMap 인스턴스를 바인딩 하는데 사용)
<결론>
메서드 파라미터에 @RequestBody가 붙어있다
-> HTTP Request Body 내부에 데이터가 담겨있음을 의미
-> RequestMappingHandlerAdapter가 데이터의 MIME 타입을 확인하고 적절한 HttpMessageConverter 구현체 선정
(application/json의 경우 MappingJackson2HttpMessageConverter 사용)
-> 해당 Converter가 Request Body 내부의 데이터를 객체(Object)로 변환!
(MappingJackson2HttpMessageConverter의 경우 내부적으로 ObjectMapper를 이용해 변환)
* RequestBody의 DTO는 setter 없이 getter만 있으면 getter를 이용해 값을 바인딩할 수 있다
** 어떻게 가능할까? 후속 포스팅 ==> https://sedangdang.tistory.com/307
+ HTTP Request 구조
* Start Line (시작 줄)
- HTTP 메서드 (GET, PUT, POST, DELETE, HEAD, OPTIONS 등....)
- 요청 타깃 (주로 URL, 프로토콜, 포트, 도메인의 절대 경로)
- HTTP Version
* Body (본문)
- 필수 요소 X (GET, HEAD, DELETE, OPTIONS와 같이 리소스를 가져오는 요청은 보통 본문이 필요하지 않다)
- POST와 같이 서버에 데이터를 전송하고자 할 때 주로 사용
- 단일 리소스 바디 (Content-Type, Content-Length로 정의)
- 다중 리소스 바디 (Multipart form 데이터)
(* 참고 ) https://developer.mozilla.org/ko/docs/Web/HTTP/Messages#http_%EC%9A%94%EC%B2%AD
진짜로 파면 팔수록 더 어렵다;;
<참고>
'웹 > Spring' 카테고리의 다른 글
ObjectMapper는 어떻게 setter 없이도 동작할까? (0) | 2022.12.01 |
---|---|
@ModelAttribute 공식 문서를 읽어보자 (0) | 2022.11.23 |
@WebMvcTest 에서 Spring Security 적용, 401/403 에러 해결하기 - csrf (4) | 2022.11.22 |
스프링 + Thymeleaf로 게시글 비밀번호 기능 구현하기 (0) | 2022.10.29 |
DTO는 대체 어디서 변환하는 것이 좋을까? (2) | 2022.10.27 |