클라이언트에서 서버로 요청 데이터를 전달할 때는 주로 다음과 같은 방법을 통해 전달한다.
반대로 서버에서 클라이언트에 응답 데이터를 전달할 때는 다음과 같다.
HTTP API를 제공하는 경우에는 HTTP Message Body에 JSON, XML, TEXT 형식으로 데이터를 직접 담아서 요청 및 응답을 처리한다.
Spring에서는 컨트롤러에서 HttpEntity 객체나 @RequestBody, @ResponseBody 어노테이션을 사용하면 데이터를 직접 매핑할 필요 없이 자동으로 요청 및 응답 데이터를 적절한 데이터 형식으로 변환해준다.
그렇다면 스프링은 내부에서 어떠한 원리로 요청 및 응답 데이터를 적절하게 매핑해주는 것일지 의문이다.
이는 HTTP 메시지 컨버터
라는 기능을 통해서 제공해준다.
HTTP 메시지 컨버터는 데이터의 클래스 타입과 미디어 타입을 체크하여 알맞은 형식의 데이터로 변환해준다.
스프링 부트는 다양한 타입의 메시지 컨버터를 지원하며 이들은 우선순위를 가진다.
대표적인 메시지 컨버터는 다음과 같다.
만약, JSON 형식의 객체 데이터 {"name":"hello", "age":20}를 전송하면 MappingJackson2HttpMessageConverter가 적절한 데이터로 변환해준다.
MappingJackson2HttpMessageConverter는 클래스 타입으로 객체 or HashMap을 지원하고, 미디어 타입으로 application/json을 지원해주기 때문이다.
그렇다면 HTTP 메시지 컨버터는 스프링 MVC의 동작 과정 중 어디서 적용되는 것일까?
HTTP 메시지 컨버터는 ArgumentResolver와 ReturnValueHandler가 사용한다.
스프링 MVC는 요청이 발생하면 핸들러 매핑, 핸들러 어댑터를 통해 요청을 처리할 수 있는 컨트롤러를 찾아준다.
그런데 우리는 요청을 @RequestParam, @ModelAttribute, @RequestBody, HttpEntity 등 다양한 타입의 인자값으로 받을 수 있었다.
컨트롤러에서 데이터를 사용하기 위해서는 다양한 타입의 인자값을 누군가가 적절한 데이터로 매핑시켜줘야 할 것이다.
이를 해결해주는 친구가 바로 ArgumentResolver
이다. 반대로 ReturnValueHandler
는 응답에서 다양한 타입의 인자값을 처리해준다. 각각 오브젝트들은 요청, 응답 데이터를 적절한 데이터로 변환해주는 역할을 수행한다.
이때 다양한 타입의 데이터들 중 HttpEntity 객체나 @RequestBody, @ResponseBody 어노테이션을 가지는 데이터라면 HTTP 메시지 컨버터를 사용하여 데이터를 매핑시켜주는 것이다.