Spring - RequestBody & ResponseBody

웹 서비스와 RESTful한 방식이 시스템을 구성하는 주요 요소로 자리 잡으면서 웹 시스템간에 XML이나 JSON 등의 형식으로 데이터를 주고 받는 경우가 증가했습니다.

이에 따라 스프링 MVC도 **클라이언트에서 전송한 XML 데이터나 JSON 또는 기타 데이터를 컨트롤러에서 DOM 객체나 자바 객체로 변환해서 받을 수있는 기능(수신)**을 제공하고 있으며, 비슷하게 **자바 객체를 XML이나 JSON 또는 기타 형식으로 변환해서 전송할 수 있는 기능(송신)**을 제공하고 있습니다.

@RequestBody 어노테이션과 @ResponseBody 어노테이션은 각각 HTTP 요청의 body 부분을 자바 객체로 변환하고 자바 객체를 HTTP 응답 body로 변환하는데 사용됩니다.

@RequestBody

Spring MVC 컨트롤러에서 HTTP 요청의 body 부분을 자바 객체로 mapping할 때 @RequestBody 어노테이션을 사용합니다. @RequestBody 어노테이션의 기능은 다음과 같습니다.

  • @ReuqestBody를 사용하지 않는 경우 : query parameter, form data를 객체에 mapping한다.
  • @ReuqestBody를 사용하는 경우 : body에 있는 data를 HttpMessageConverter를 이용해 선언한 객체에 mapping한다.

@ResponseBody

@ResponseBody는 @RequestBody와 비슷한 방식으로 동작합니다. @ResponseBody가 메소드 레벨에서 부여되면 메소드가 리턴하는 오브젝트는 ContentNegotiatingViewResolver를 이용해 뷰를 통해 결과를 만들어내는 것이 아닌, message converter를 통해 바로 HTTP 응답의 메시지 본문으로 변환됩니다.

ContentNegotiatingViewResolver는 등록되어 있는 ViewResolver중에서 controller 메소드의 리턴값을 통해 등록된 ViewResolver 중에서 적합한 형태로 처리해서 반환하는 반면, @ResponseBody는 @RequestBody가 선택한 형식으로 결과값을 변환하여 반환한다고 보면 됩니다.

@RestController는 @Controller와 @ResponseBody를 동시에 사용하는 것과 같습니다. @Controller를 사용하는 경우에만 @ResponseBody를 추가하면 됩니다.

HttpMessageConverter를 이용한 변환 처리

AnnotationMethodHandlerAdapter에는 HttpMessageConverter 타입의 메시지 변환기인 message converter가 여러 개 등록되어 있습니다. @RequestBody가 붙은 파라미터가 있으면 HTTP 요청의 미디어 타입과 파라미터의 타입을 먼저 확인하고, message converter 중에서 해당 미디어 타입과 파라미터 타입을 처리할 수 있다면, HTTP 요청의 body 부분을 통째로 변환해서 지정된 메소드 파라미터로 전달해줍니다.

HttpMessageConverter의 종류

AnnotationMethodHandlerAdapter 클래스는 @RequestBody 어노테이션이 적용된 파라미터나 @ResponseBody 어노테이션이 적용된 메서드에 대해 HttpMessageConverter를 사용해서 변환을 처리합니다. 주요 HttpMessageConverter 구현 클래스는 다음과 같습니다.

  • ByteArrayHttpMessageConverter : HTTP 메시지와 byte 배열 사이의 변환을 처리한다. 컨텐츠 타입은 application/octet-stream이다.
  • StringHttpMessageConverter : HTTP 메시지와 String 사이의 변환을 처리한다. 컨텐츠 타입은 text/plain;charset=ISO-8859-1이다.
  • SourceHttpMessageConverter : HTTP 메시지와 javax.xml.transform.Source 사이 변환을 처리한다. 컨텐츠 타입은 application/xml 또는 text/xml이다.
  • FormHttpMessageConverter : HTML 폼 데이터를 MultiValueMap으로 전달받을 때 사용된다. 지원하는 컨텐츠 타입은 application-x-www-form-urlencorded이다.
  • MappingJacksonHttpMessageConverter : Jackson 라이브러리를 이용해서 JSON HTTP 메시지와 객체 사이의 변환을 처리한다. 컨텐츠 타입은 applicaion/json이다.
  • MarshallingHttpMessageConverter : 스프링의 Marshaller와 unMarshaller를 이용해서 XML HTTP 메시지와 객체 사이의 변환을 처리한다. 컨텐츠 타입은 application/xml 또는 text/xml이다.

Content-Type과 Accept header 기반의 변환 처리

AnnotationMethodHandlerAdapter가 HttpMessageConverter를 이용해서 request의 body 데이터를 @RequestBody 어노테이션이 적용된 자바 객체로 변환할 때에는, HTTP 요청 header의 Content-Type에 명시된 미디어 타입(MIME)을 지원하는 HttpMessageConverter 구현체를 선택합니다.
예를 들어, 요청 미디어 타입이 application/json이고 @RequestBody 어노테이션이 적용된 경우 MappingJacksonHttpMessageConverter가 선택됩니다.

비슷하게 @ResponseBody 어노테이션을 이용해서 리턴한 객체를 HTTP 응답 객체로 변환할 때에는 HTTP 요청 header의 Accept에 명시된 미디어 타입(MIME)을 지원하는 HttpMessageConveter 구현체를 선택합니다.
예를 들어, Accept에 명시된 값이 application/json이고 @ResponseBody 어노테이션이 적용된 메서드의 리턴 타입이 자바 객체인 경우 MappingJacksonHttpMessageConverter가 선택됩니다.

참고

Http Message Converters with the Spring Framework