제목이 길어져서 생략했지만 2.1.2.RELEASE 부터 적용되는 이야기이다.
스프링부터 2.1.2.RELEASE 에서 의존하는 스프링 프레임워크 버전은 5.1.4.RELEASE 이다.
spring-web:5.1.4.RELEASE 에 들어있는 StringHttpMessageConverter 클래스의 코드가 아래와 같이 변경된 것을 알 수 있었다.
getContentTypeCharset 메서드가 해주는 역할은 미디어타입에 따라 캐릭터셋을 돌려주는데,
크게 3가지 부분에서 사용이 된다.
- readInternal: 메세지를 읽을 때
- getContentLength: 컨텐츠의 길이를 계산할 때
- writeInternal: 메세지를 쓸 때
문제는 getContentTypeCharset의 로직의 분기가 추가됨에 따라 JSON 컨텐츠타입의 경우 charset이 특별히 지정되어 있지 않으면 기본적으로 UTF-8를 인코딩 타입을 사용하게 된다. 혹시나 defaultCharset 을 사용하여 인코딩을 바꾸는 경우 이전 동작이 정상적으로 동작하지 않을 가능성이 생긴 것이다.
이 문제를 발견하게 된 것은 요청은 EUC-KR로 인코딩된 JSON으로 보내고, 응답은 UTF-8로 인코딩된 JSON을 받는 특이한 API 때문이었다.
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity entity = new HttpEntity<>(content, headers);
RestTemplate restTemplate = new RestTemplate();
restTemplate.getMessageConverters().add(0, new StringHttpMessageConverter(Charset.forName("EUC-KR"));
restTemplate.exchange(apiUrl, HttpMethod.POST, entity, Response.class);
이 경우에는 제일 마지막 else를 거쳐야 getDefaultCharset()을 통해 구해온 캐릭터셋을 반환한다.
하지만 spring-web이 5.1.4.RELEASE 부터는 상관없이 UTF-8을 돌려주게 된다는 사실.
해결책은
커밋 로그에도 나와 있지만, MappingJackson2HttpMessageConverter 이나 GsonHttpMessageConverter도 로직이 동일하다.
따라서 우선순위가 가장 높은 ContentType에 캐릭터셋을 명시하는 것이 가장 확실하다.
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.valueOf("application/json;charset=EUC-KR");
HttpEntity entity = new HttpEntity<>(content, headers);
RestTemplate restTemplate = new RestTemplate();
restTemplate.exchange(apiUrl, HttpMethod.POST, entity, Response.class);
다른 해결책은?
나만 문제가 아니였는지 StringHttpMessageConverter 의 수정사항은 다시 Rollback이 되었다.
Rossen Stoyanchev가 일을 저질러 놓고 Sebastien Deleuze가 해결해놓았다.
하지만 아직 2019-05-28일 커밋된 수정사항은 릴리즈되지 않은 것 같다.
이후 언젠가 롤백이 된 버전으로 Jump를 하는 것이 다른 해결책이다.
'Programing > Framework' 카테고리의 다른 글
[Spring] RestClientException 예외 정리 (0) | 2019.07.24 |
---|---|
[SpringBoot] ConversionService에 대한 오해 (0) | 2019.06.25 |
[spring boot] Type-safe Configuration Properties 쓸 때 주의점 (0) | 2019.06.11 |
[Spring] AOP로 로깅 코드 덜어내기 (0) | 2019.05.29 |
[Spring] 스프링 부트에서 SOAP 클라이언트 사용하기 (0) | 2019.05.02 |