HTTP 메시지 컨버터(HTTP Message Converter)

2022. 3. 27. 18:21
반응형

스프링에서 메시지 바디(Message Body)에 데이터를 넣어서 서버로 HTTP 요청을 하거나 반대로 서버로부터 HTTP 응답을 받아서 메시지 바디(Message Body)에 있는 데이터를 불러올 때 @RequestBody와 @ResponseBody 애노테이션을 거의 대부분의 스프링 사용자들은 사용할 것이다.

 

@RequestBody와 @ResponseBody는 애노테이션 하나만으로 아주 유연하게 처리할 수 있는 장점이 있다. 이것은 다 HTTP 메시지 컨버터 덕분이 아닌가 싶다. @ResponseBody를 사용하면 어떤식으로 동작하게 되는지 간단히 알아보자.

 

@ResponseBody의 사용 원리

  1. HTTP Message Body에 문자 내용을 직접 반환한다.
  2. 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가지가 있는데, 스프링이 순서대로 해당 메시지 컨버터가 클래스와 미디어 타입을 지원하는지 여부를 체크하며, 만족하지 않는다면 다음으로 넘어간다.

  1. ByteArrayHttpMessageConverter : byte[] 데이터를 처리한다.
  2. StringHttpMessageConverter : String 데이터를 처리한다.
  3. MappingJackson2HttpMessageConverter : JSON 형태의 데이터를 처리한다.

HTTP 요청 데이터 읽기

HTTP 요청이 오게되면 어떤 방식으로 메시지 컨버터가 동작할까? HTTP 요청이 오고, 컨트롤러에서 @RequestBody와 HttpEntity를 사용하고 있다고 전제하에 설명하겠다. HTTP 요청이 오면 메시지 컨버터가 메시지를 읽을 수 있는지 확인하기 위해 canRead() 메서드를 호출하여 @RequestBody의 대상 클래스 타입을 지원하는지 여부와 HTTP 요청 헤더에 적혀있는 Content-Type 미디어 타입을 지원하는지 여부를 체크한다. 만약에 이 조건을 만족하지 않는다면 다음 우선순위의 메시지 컨버터가 같은 방식으로 동작하게 될 것이고, 조건을 만족한다면 read() 메서드를 호출하여 객체를 생성하고 반환하게 된다.

  1. HTTP 요청이 들어온다.(컨트롤러에서 @RequestBody와 HttpEntity 파라미터 사용)
  2. 메시지 컨버터가 메시지를 읽을 수 있는지 확인하기 위해서 canRead() 메서드를 호출한다.
    1. @RequestBody의 대상 클래스 타입을 지원하는지 여부를 체크한다.
    2. HTTP 요청 헤더의 Content-Type 미디어 타입을 지원하는지 체크한다.
  3. 조건을 만족한다면 read() 메서드를 호출하여 객체를 생성하고 반환한다.
  @RequestMapping
  void requestBody(@RequestBody HelloData data) {}
content-type: application/json

HTTP 응답 데이터 생성

HTTP 요청이 오고 응답을 하게 되면 어떤 방식으로 메시지 컨버터가 동작할까? 컨트롤러에서 @ResponseBody와 HttpEntity를 사용하고 있다고 전제하에 설명하겠다. 메시지 컨버터가 메시지를 쓸 수 있는지 확인하기 위해 canWrite()를 호출하여 return 대상 클래스 타입을 지원하는지 여부와 HTTP 응답 헤더에 적혀있는 Accept 미디어 타입을 지원하는지 여부를 체크한다. 만약 이 조건을 만족하지 않는다면 다음 우선순위의 메시지 컨버터가 같은 방식으로 동작하게 될 것이고, 조건을 만족한다면 write() 메서드를 호출하여 HTTP 응답 메시지 바디에 데이터를 생성하여 응답하게 된다.

  1. HTTP 응답으로 메시지 바디에 데이터를 실어 보낸다.(컨트롤러에서 @ResponseBody와 HttpEntity 반환값 사용)
  2. 메시지 컨버터가 응답할 메시지를 쓸 수 있는지 확인하기 위해서 canWrite() 메서드를 호출한다.
    1. return 대상 클래스 타입을 지원하는지 여부를 체크한다.
    2. Http 응답 헤더의 Accept 미디어 타입을 지원하는지 체크한다.
  3. 조건을 만족한다면 write() 메서드를 호출하여 HTTP 응답 메시지 바디에 데이터를 쓴다.
@ResponseBody
public ResponseEntity<HelloData> responseBody(){}
accept: application/json
반응형

BELATED ARTICLES

more