본문 바로가기
Hot Tech Reference/Spring Framework

spring 메시지 컨버터

by cusmaker 2014. 1. 27.
반응형

메시지 컨버터는 XML 이나 JSON 을 이용한 AJAX 기능이나 웹 서비스를 개발할 때 사용할 수 있다. HTTP 요청 프로퍼티를 모델 오브젝트의 프로퍼티에 개별적으로 바인딩하고 모델 오브젝트를 다시 뷰를 이용해 클라이언트로 보낼 콘텐트를 만드는 대신 HTTP 요청 메시지 본문과 HTTP 응답 메시지 본문을 통째로 메시지로 다루는 방식이다메시지 컨버터는 파라미터의 @RequestBody 와 메소드에 부여한 @ResponseBody 를 이용한다.

메시지 방식의 컨트롤러를 사용하는 방법은 두 가지로 구분한다. HTTP 요청 메소드에 따라서 GET과 POST 로 나누는 것이다. GET 의 경우는 요청정보가 URL 과 쿼리 스트링으로 제한되므로 @RequestBody 를 사용하는 대신 @RequestParam 이나 @ModelAttribute 로 요청 파라미터를 전달받는다. 반면에 POST 의 경우라면 HTTP 요청 본문이 제공되므로 @RequestBody 를 사용할 수 있다.

메시지 컨버터의 종류

사용할 메시지 컨버터는 AnnotationMethodHandlerAdapter 를 통해 등록한다. 일반적으로 하나 이상의 메시지 컨버터를 등록해 두고 요청 타입이나 오브젝트 타입에 따라 선택되게 한다. AnnotationMethodHandlerAdapter 에 등록되는 디폴트 메시지 컨버터는 다음과 같다.

ByteArrayHttpMessageConverter

지원하는 오브젝트 타입은 byte[] 이다. 미디어 타입은 모든 것을 다 지원한다. 따라서 @RequestBody 로 전달받을 때는 모든 종류의 HTTP 요청 메시지 본문을 byte 배열로 가져올 수 있다. 반대로 @ResponseBody 로 보낼 때는 콘텐트 타입이 application/octet-stream 으로 설정된다. 컨트롤러가 byte 배열에 담긴 바이너리 정보를 클라이언트에 전송할 필요가 있을 때 외에는 그다지 유용해 보이지 않는다. 바이너리 포맷을 가진 정보를 주고 받아야 하는 시스템이 있다면 활용할 수 있을 것이다.

StringHttpMessageConverter

지원하는 오브젝트는 스트링 타입이다. 미디어 타입은 모든 종류를 다 허용한다. 따라서 HTTP 요청의 본문을 그대로 스트링으로 가져올 수 있다. HTTP 가 기본적으로 텍스트 기반의 포맷이므로 가공하지 않은 본문을 직접 받아서 사용하고 싶은 경우라면 유용하게 쓸 수 있다.

XML 이나 JSON 같은 공개된 형식 외에 직접 정의한 문서 포멧이 있다면 적절한 파서를 붙여서 활용할 수 있도록 문자열로 받는 것이 편리하다. 물론 좀 더 나은 방법은 해당 문서 포멧을 지원하는 HttpMessageConverter 를 직접 개발해서 적용하는 것이다.

응답의 경우는 콘텐트 타입이 text/plain 으로 전달된다. 단순 문자열로 응답을 보내고 싶을 때는 @ResponseBody 와 함께 스트링 리턴값을 사용하면 된다.

FormHttpMessageConverter

미디터 타입이 application/x-www-form-urlencoded 로 정의된 폼 데이터를 주고 받을 때 사용할 수 있다. 오브젝트 타입은 다중 값을 갖는 맵 확장 인터페이스인 MultiValueMap<String, String> 을 지원한다. MultiValueMap 은 맵의 값이 List 타입인 맵으로, 하나의 이름을 가진 여러 개의 파라미터가 사용될 수 있는 HTTP 요청 파라미터를 처리하기에 적당하다. HTTP 요청의 폼 정보는 @ModelAttribute 를 이용해 바인딩하는 것이 훨씬 편리하고 유용하므로, FormHttpMessageConverter 를 @RequestBody 에 사용할 일은 별로 없을 것 같다.

응답의 경우에도 application/x-www-form-urlencoded 콘텐트 타입을 사용하는 경우는 드물지만 클라이언트가 application/x-www-form-urlencoded 타입의 폼 정보를 선호한다면 이용할 수 있을 것이다.

SourceHttpMessageConverter

미디어 타입은 application/xml, application/*+xml, text/xml 세 가지를 지원한다. 오브젝트 타입은 javax.xml.transform.Source 타입인 DOMSource, SAXSource, StreamSource 세 가지를 지원한다. XML 문서를 Source 타입의 오브젝트로 전환하고 싶을 때 유용하게 쓸 수 있다. 최근에는 OXM 기술의 발달로 XML 을 바로 자바오브젝트로 변환하는 경우가 많기 때문에 그다지 많이 쓰이지는 낳겠지만, DOM 이나 SAX 방식의 XML 문서 접근을 선호한다면 이용할 만하다.

기본적으로 네 가지 종류의 HttpMessageConverter 가 디폴트로 등록되지만, 이 보다는 디폴트로 등록되지 않는 다음 세 가지 HttpMessageConverter 가 실제로 더 유요하다. 이중에서 필요한 메시지 컨버터가 있다면 직접 AnnotationMethodHandlerAdapter 빈의 messageConverters 프로퍼티에 등록하고 사용해야 한다.

Jaxb2RootElementHttpMessageConverter

JAXB2의 @XmlRootElement 와 @XmlType 이 붙은 클래스를 이용해서 XML 과 오브젝트 사이의 메시지 변환을 지원한다. 기본적으로 SourceHttpMessageConverter 와 동일한 XML 미디어 타입을 지원한다. 오브젝트는 두 가지 에노테이션 중 하나가 적용됐다면 어떤 타입이든 사용할 수 있다.

JAXB2의 스키마 컴파일러를 통해 생성된 바인딩용 클래스를 이용해서 손쉽게 XML 과 오브젝트 사이의 변환 기능을 이용할 수 있다. JAXB2에 숙련된 개발자라면 이를 이용해 편리하게 XML 문서 기반의 컨트롤러를 만들 수 있다.

MarshallingHttpMessageConverter

스프링의 OXM 추상화의 Marshaller 와 Unmarshaller 를 이용해서 XML 문서와 자바 오브젝트 사이의 변환을 지원해주는 컨버터다. MarshallingHttpMessageConverter 를 빈으로 등록할 때 프로퍼티에 marshaller 와 unmarshaller 를 설정해줘야 한다. 미디어 타입은 다른 XML 기반 메시지 컨버터와 동일하며, 지원 오브젝트는 unmarshaller 의 supports() 메소드를 호출해서 판단한다. OXM 기술을 자유롭게 선택해서 XML 문서 기반의 컨트롤러를 작성하려고 한다면 편리하게 이용할 수 있다. 단, Marshaller 의 개수만큼 MarshallingHttpMessageConverter 를 등록해줘야 하는 것이 조금 번거로울 수 있다.

MappingJacksonHttpMessageConverter

Jackson ObjectMapper 를 이용해서 자바 오브젝트와 JSON 문서를 자동변환해주는 메시지 컨버터다. 지원 미디어 타입은 application/json 이다. 자바 오브젝트 타입에 제한은 없지만 프로퍼티를 가진 자바빈 스트일이거나 HashMap 을 이용해야 정확한 변환 결과를 얻을 수 있다.

Jackson 프로젝트의 ObjectMapper 가 대부분의 자바 타입을 무난히 JSON 으로 변환해주지만 날짜나 숫자 등에서 포맷을 적용하는 등의 부가적인 변환 기능이 필요하다면 ObjectMapper 를 확장해서 적용할 수 있다. 스프링 소스가 제공하는 MVC-AJAX 예제 프로젝트(https://src.springsource.org/svn/spring-samples/mvc-ajax/trunk) 를 보면, 스프링의 컨버전 서비스를 JSON 변환에 적용하도록 ObjectMapper 를 확장한 예를 찾아 볼 수 있다.

위의 세 가지 메시지 컨버터를 사용하려면 다음과 같이 AnnotationMethodHandlerAdapter 빈을 등록하고 messageConverters 프로퍼티에 등록해줘야 한다. 여타 전략과 마찬가지로 전략 프로퍼티를 직접 등록하면 디폴트 전략은 자동으로 추가되지 않는다는 점을 주의하자.

1
2
3
4
5
6
7
8
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
    <property name="messageConverters">
        <list>
            <bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter" />
            <bean class="org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter" />
        </list>
    </property>
</bean>

출처 : http://springsource.tistory.com/89