HTTP 메시지 컨버터(HTTP Message Converter)
스프링에서 메시지 바디(Message Body)에 데이터를 넣어서 서버로 HTTP 요청을 하거나 반대로 서버로부터 HTTP 응답을 받아서 메시지 바디(Message Body)에 있는 데이터를 불러올 때 @RequestBody와 @ResponseBody 애노테이션을 거의 대부분의 스프링 사용자들은 사용할 것이다.
@RequestBody와 @ResponseBody는 애노테이션 하나만으로 아주 유연하게 처리할 수 있는 장점이 있다. 이것은 다 HTTP 메시지 컨버터 덕분이 아닌가 싶다. @ResponseBody를 사용하면 어떤식으로 동작하게 되는지 간단히 알아보자.
@ResponseBody의 사용 원리
- HTTP Message Body에 문자 내용을 직접 반환한다.
- HttpMessageConverter가 동작하여 데이터가 어떤 형식인지, 읽을수 있는지 등을 판단한다.
HttpMessageConverter의 인터페이스
package org.springframework.http.converter;
public interface HttpMessageConverter<T> {
boolean canRead(Class<?> clazz, @Nullable MediaType mediaType);
boolean canWrite(Class<?> clazz, @Nullable MediaType mediaType);
List<MediaType> getSupportedMediaTypes();
default List<MediaType> getSupportedMediaTypes(Class<?> clazz) {
return (canRead(clazz, null) || canWrite(clazz, null) ?
getSupportedMediaTypes() : Collections.emptyList());
}
T read(Class<? extends T> clazz, HttpInputMessage inputMessage)
throws IOException, HttpMessageNotReadableException;
void write(T t, @Nullable MediaType contentType, HttpOutputMessage outputMessage)
throws IOException, HttpMessageNotWritableException;
}
- canRead(), canWrite() : 메시지 컨버터가 해당 클래스와 미디어 타입을 지원하는지 체크한다.
- read(), write() : 메시지 컨버터를 통해서 메시지를 읽고 쓰는 기능이다.
HttpMessageConverter 구현체
HttpMessageConverter를 구현한 클래스는 대표적으로 3가지가 있는데, 스프링이 순서대로 해당 메시지 컨버터가 클래스와 미디어 타입을 지원하는지 여부를 체크하며, 만족하지 않는다면 다음으로 넘어간다.
- ByteArrayHttpMessageConverter : byte[] 데이터를 처리한다.
- StringHttpMessageConverter : String 데이터를 처리한다.
- MappingJackson2HttpMessageConverter : JSON 형태의 데이터를 처리한다.
HTTP 요청 데이터 읽기
HTTP 요청이 오게되면 어떤 방식으로 메시지 컨버터가 동작할까? HTTP 요청이 오고, 컨트롤러에서 @RequestBody와 HttpEntity를 사용하고 있다고 전제하에 설명하겠다. HTTP 요청이 오면 메시지 컨버터가 메시지를 읽을 수 있는지 확인하기 위해 canRead() 메서드를 호출하여 @RequestBody의 대상 클래스 타입을 지원하는지 여부와 HTTP 요청 헤더에 적혀있는 Content-Type 미디어 타입을 지원하는지 여부를 체크한다. 만약에 이 조건을 만족하지 않는다면 다음 우선순위의 메시지 컨버터가 같은 방식으로 동작하게 될 것이고, 조건을 만족한다면 read() 메서드를 호출하여 객체를 생성하고 반환하게 된다.
- HTTP 요청이 들어온다.(컨트롤러에서 @RequestBody와 HttpEntity 파라미터 사용)
- 메시지 컨버터가 메시지를 읽을 수 있는지 확인하기 위해서 canRead() 메서드를 호출한다.
- @RequestBody의 대상 클래스 타입을 지원하는지 여부를 체크한다.
- HTTP 요청 헤더의 Content-Type 미디어 타입을 지원하는지 체크한다.
- 조건을 만족한다면 read() 메서드를 호출하여 객체를 생성하고 반환한다.
@RequestMapping
void requestBody(@RequestBody HelloData data) {}
content-type: application/json
HTTP 응답 데이터 생성
HTTP 요청이 오고 응답을 하게 되면 어떤 방식으로 메시지 컨버터가 동작할까? 컨트롤러에서 @ResponseBody와 HttpEntity를 사용하고 있다고 전제하에 설명하겠다. 메시지 컨버터가 메시지를 쓸 수 있는지 확인하기 위해 canWrite()를 호출하여 return 대상 클래스 타입을 지원하는지 여부와 HTTP 응답 헤더에 적혀있는 Accept 미디어 타입을 지원하는지 여부를 체크한다. 만약 이 조건을 만족하지 않는다면 다음 우선순위의 메시지 컨버터가 같은 방식으로 동작하게 될 것이고, 조건을 만족한다면 write() 메서드를 호출하여 HTTP 응답 메시지 바디에 데이터를 생성하여 응답하게 된다.
- HTTP 응답으로 메시지 바디에 데이터를 실어 보낸다.(컨트롤러에서 @ResponseBody와 HttpEntity 반환값 사용)
- 메시지 컨버터가 응답할 메시지를 쓸 수 있는지 확인하기 위해서 canWrite() 메서드를 호출한다.
- return 대상 클래스 타입을 지원하는지 여부를 체크한다.
- Http 응답 헤더의 Accept 미디어 타입을 지원하는지 체크한다.
- 조건을 만족한다면 write() 메서드를 호출하여 HTTP 응답 메시지 바디에 데이터를 쓴다.
@ResponseBody
public ResponseEntity<HelloData> responseBody(){}
accept: application/json
'Spring Framework > Spring Web MVC' 카테고리의 다른 글
Spring MVC - FrontController(Dispatcher Servlet) (0) | 2022.04.09 |
---|---|
Spring MVC - API 예외처리(Exception) (0) | 2022.04.05 |
Spring MVC - 로그인 처리(쿠키, 세션) (0) | 2022.04.02 |
Spring MVC - Bean Validation (0) | 2022.03.29 |
Spring MVC - Validation(검증) (0) | 2022.03.28 |