본문 바로가기
Spring/스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술

HTTP 메시지 컨버터

by hk27 2022. 2. 2.
어떻게 JSON 데이터를 HTTP 메시지 바디에서 읽거나 쓸 수 있을까요?

 

안녕하세요. 

오늘은 어떻게 JSON 데이터를 HTTP 메시지 바디에서 읽거나 쓸 수 있는지 알아보겠습니다.

@RequestBody로 HTTP 요청 메시지 바디의 JSON 데이터를 객체로 받을 수 있고,

@ResponseBody로 객체를 HTTP 응답 메시지 바디에 데이터로 전송할 수 있습니다.

이것이 어떻게 가능할까요?

 

바로 HTTP 메시지 컨버터 덕분인데요.

@ResponseBody의 사용 원리를 봅시다.

스프링은 @ResponseBody 어노테이션이 있으면 HttpMessageConverter를 호출합니다. 

HttpMessageConverter에는 JsonConverter, StringConverter 등이 있고 데이터에 따라 적합한 컨버터가 사용됩니다. 

여기서 데이터의 형을 변환해서 웹 브라우저에 응답을 보냅니다. 

 

스프링 MVC가 HTTP 메시지 컨버터를 적용하는 경우는 아래와 같습니다.

- HTTP 요청: @RequestBody, HttpEntity, RequestEntity

- HTTP 응답: @ResponseBody, HttpEntity, ResponseEntity

 

HTTP 메시지 컨버터

스프링이 제공하는 HTTP 메시지 컨버터 인터페이스를 봅시다. 

public interface HttpMessageConverter<T> {
	boolean canRead(Class<?> clazz, @Nullable MediaType mediaType);
    
	boolean canWrite(Class<?> clazz, @Nullable MediaType mediaType);
    
    	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는 메시지 컨버터를 통해 메시지를 읽고 쓰는 메소드입니다.

 

스프링 부트가 제공하는 기본 메시지 컨버터는 아래와 같습니다. (일부 생략)

0 = ByteArrayHttpMessageConverter
1 = StringHttpMessageConverter
2 = MappingJackson2HttpMessageConverter

스프링 부트는 대상 클래스 타입과 미디어 타입을 확인해서 메시지 컨버터 사용 여부를 결정합니다. 만약 만족하지 않으면 마음 메시지 컨버터로 우선순위가 넘어갑니다.

0번인 ByteArray 메시지컨버터는 byte[] 데이터를 처리합니다. 

예를 들어서 @RequestBody byte[] data처럼 요청을 받으면 HTTP 요청 메시지의 데이터를 byte 배열로 받습니다.

1번인 String 메시지컨버터는 String 데이터를 처리합니다.

@Request String data, @ResponseBody return "ok" 처럼 요청을 받으면 String 문자로 데이터를 처리합니다.

2번인 MappingJackson 메시지 컨버터는 json 데이터를 처리하고 미디어 타입이 application/json일 때 사용됩니다.

@RequestBody HelloData data, @ResponseBody return helloData등 객체와 json을 변환할 때 사용됩니다. 

 

요청 매핑 핸들러

 그렇다면 HTTP 메시지 컨버터는 스프링 MVC의 어디에서 사용될까요?

위의 사진은 spring MVC 구조도입니다. 여기서 핸들러 어댑터 부분이 중요합니다.

어노테이션 기반의 컨트롤러인 @RequestMapping이 붙은 컨트롤러는 핸들러 어댑터 중 RequestMappingHandlerAdapter(요청 매핑 핸들러 어댑터)가 처리합니다. 

 

요청 매핑 핸들러 어댑터의 동작 방식은 아래와 같습니다.

1. 요청 매핑 핸들러 어댑터가 ArgumentResolver를 부릅니다. ArgumentResolver는 컨트롤러의 파라미터, 어노테이션 정보를 기반으로 전달 데이터를 생성합니다. 

2. 요청 매핑 핸들러 어댑터가 핸들러를 호출하고, 파라미터는 ArgumentResolver가 제공합니다. 

3. 컨트롤러가 작업을 수행한 뒤 ReturnValueHandler를 부릅니다. ReturnValueHandler는 응답 값을 변환하고 처리합니다. 

 

RequestMappingHandlerApater 클래스에 들어가면 기본으로 제공하는 ArgumentResolver가 30개가 넘는 것을 볼 수 있습니다. 

가능한 파라미터 목록은 공식 매뉴얼에서 확인할 수 있습니다.

https://docs.spring.io/spring-framework/docs/current/reference/html/web.html#mvc-annarguments

 

생각해보면 어노테이션 기반의 컨트롤러는 HttpServletRequest, HttpServletResponse, Model, @RequestParam, @ModelAttribute, HttpEntity 등등 매우 많은 파라미터를 사용할 수 있는데, 이것은 Argument Resolver 덕분입니다. 

 

ReturnValueHandler도 ArgumentResolver와 비슷하고, 응답 값을 변환하고 처리합니다.

 

오늘의 주제인 HTTP 메시지 컨버터는 ArgumentResolver와 ReturnValueHandler가 호출합니다.

ArgumentResolver와 ReturnResolver들이 HTTP 메시지 컨버터를 사용해서 필요한 객체를 만들고 응답 결과를 만듭니다. 

 

인프런  '스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술' 강의를 듣고 공부하며 정리한 자료입니다. 

잘못된 부분은 피드백 주시면 감사하겠습니다. 

글 읽어주셔서 감사합니다 :-)

 

참고 자료

스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술, 섹션 6. 스프링 MVC - 기본 기능 https://www.inflearn.com/course/스프링-mvc-1

 

 

 

댓글