Spring 4 Message Converters 의 처리 방법 분석. UTF-8 한글의 UTF-8 출력.

RESTful 한 응답 처리기를 만들기 위해서는 MessageConverter를 이용한다. 출력물을 적절한 json 형태로 만들기 위해서 컨버터를 사용하는 것이다.

mvc-config.xml 에 다음을 설정하면 스프링은 컨버터를 자동으로 등록한다.

1
<mvc:annotation-driven />

다음의 컨버터 중에서 위에서 부터 하나씩 처리가 가능한지 살피고 처리가 가능하면 처리 하고 브라우저로 내용을 flush 한다. 이 때 브라우저에게 지금부터 내가 보내는 내용은 어떠한 인코딩으로 작성되어 있다는 사실을 알리는데 그것이 header 값 중에 하나인 Content-Type:text/html 이다.

명시적인 message converter 를 설정에 등록하지 않으면 Spring 4는 기본적으로 7개의 컨버터를 등록하여 사용한다.

1
2
3
4
5
6
7
org.springframework.http.converter.ByteArrayHttpMessageConverter@3ade80f2
org.springframework.http.converter.StringHttpMessageConverter@49fc954e
org.springframework.http.converter.ResourceHttpMessageConverter@32be2576
org.springframework.http.converter.xml.SourceHttpMessageConverter@64993315
org.springframework.http.converter.support.AllEncompassingFormHttpMessageConverter@2a8ee664
org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter@775509e
org.springframework.http.converter.json.MappingJackson2HttpMessageConverter@44234093

controller 의 return type 이 String 이면 StringHttpMessageConverter 가 처리하게 되는데 이 Converter의 supported media type은 다음과 같다.

1
2
text/plain;charset=ISO-8859-1
*/*

한편 브라우저에서는 어떠한 요청을 하면서 다음의 응답을 받을 수 있다고 한다. 크롬 등의 브라우저에서 헤더를 보면 알 수 있다.

1
2
3
4
5
6
7
8
text/html
application/xhtml+xml
image/webp
application/xml;q=0.9
text/plain;charset=ISO-8859-1;q=0.8
application/json;charset=UTF-8;q=0.8
application/*+json;charset=UTF-8;q=0.8
*/*;q=0.8

따라서 Spring 은 text/html 가 가장 적당한 응답이라고 판단한다.  그런데 응답에 인코딩 정의가 안되어 있으니 StringHttpMessageConverter 의 기본 인코딩인 ISO-8859 로 데이타를 변조하면서 한글이 깨지게 된다.

명시적으로 컨버터를 등록해보자.

01
02
03
04
05
06
07
08
09
10
11
<mvc:annotation-driven>
 <mvc:message-converters>
<bean class="org.springframework.http.converter.StringHttpMessageConverter">
 <property name="supportedMediaTypes">
 <list>
 <value>text/html;charset=UTF-8</value>
 </list>
 </property>
 </bean>
 </mvc:message-converters>
 </mvc:annotation-driven>

스프링은 명시적인 메세지 컨버터를 맨 위에 추가한다.

01
02
03
04
05
06
07
08
09
10
org.springframework.http.converter.StringHttpMessageConverter@49fc954e
org.springframework.http.converter.ByteArrayHttpMessageConverter@3ade80f2
org.springframework.http.converter.StringHttpMessageConverter@49fc954e
org.springframework.http.converter.ResourceHttpMessageConverter@32be2576
org.springframework.http.converter.xml.SourceHttpMessageConverter@64993315
org.springframework.http.converter.support.AllEncompassingFormHttpMessageConverter@2a8ee664
org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter@775509e
org.springframework.http.converter.json.MappingJackson2HttpMessageConverter@44234093

규칙대로 한놈만 걸리면 그것으로 출력을 하고 마무리 한다고 했다.

우리는 명시적인 컨버터와 명시적으로 처리하겠다는 미디어 타입(text/html;charset=UTF-8)도 추가했다.

브라우저가 받아들일 수 있다는 미디어 타입과 비슷한 것을 골라서 스프링은 처리 가능한 미디어타입의 순서를 정리 한다. text/html 을 받을 수 있다고 브라우저가 알려줬으니 스프링은 text/html;charset=UTF-8 도 받을 수 있겠거니 판단한 것이고 아무래도 명시적인 캐릭터셋이 있으니 그것을 우선시 한다.

01
02
03
04
05
06
07
08
09
10
text/html;charset=UTF-8
text/html
application/xhtml+xml
image/webp
application/xml;q=0.9
application/json;charset=UTF-8;q=0.8
text/html;charset=UTF-8;q=0.8
text/plain;charset=ISO-8859-1;q=0.8
application/*+json;charset=UTF-8;q=0.8
*/*;q=0.8

결국 StringHttpMessageConverter 는 출력결과를 실제로는 http response의 context-header 를 text/html;charset=UTF-8 로 사용하고 브라우저는 서버사이드에서 UTF-8 로 출력하겠다고 준비된 한글을 UTF-8 로 스트리밍을 받으면서 한글이 깨지지 않게 된다.

댓글 남기기

이메일은 공개되지 않습니다. 필수 입력창은 * 로 표시되어 있습니다