Why Spring deprecate MediaType.APPLICATION_JSON_UTF8
에러 출현
스프링 테스트 코드를 짜기 위해 Junit 5 + Mockito를 사용해 개발하던 중 발생한 에러였습니다.
회사 코드인 관계로 코드를 올릴 수는 없어서 예제 코드로 대체합니다.
@Test
fun apiTest(){
mockMVC.perform(
post("api/test")
.contentType(MediaType.APPLICATION_JSON)
.content("Test")
)
}
위 테스트코드는 api/test로 post 요청을 보내는 테스트 코드입니다.
이 때 응답으로는 List<Foo>
를 받게 됩니다.
이 Foo 객체 내부에 선언된 프로퍼티의 값 중 한글이 있었습니다.
문제는 응답 바디에 포함된 한글이 깨지는 이슈가 있었습니다.
원인은 무엇이냐
MockMVCResponse를 잘 살펴보면 응답 헤더의 ContentType이 application/json
인 것을 확인할 수 있었습니다.
이것이 문제되는 이유는 charset=utf-8
이 포함되어있지 않기 때문인데요.
이러한 인코딩 처리가 헤더에 포함되지 않으면 한글이 깨질 수 밖에 없습니다.
request의 경우 application/json;charset=utf-8
이 헤더에 포함되기 때문에 요청은 한글이 잘 나오지만, response의 경우 그렇지 않았습니다.
이것이 문제의 원인이었습니다.
그건 그렇고 MediaType.APPLICATION_JSON_UTF8은 왜 depreacted?
그렇게 문제의 원인은 찾았으나 왜
발생했는지 이유를 몰라 끙끙대던 중 한 가지 의문이 들었습니다.
contentType을 설정할 때 왜 MediaType.APPLICATION_JSON_UTF8이 아닌 MediaType.APPLICATION_JSON을 보내는지 궁금해졌습니다.
MediaType.APPLICATION_JSON_UTF8가 depreacted된 이유는 스프링 2.2.0 업데이트와 관련이 있습니다.
이 deprecated가 사실은 이번 문제의 핵심이었습니다.
스프링 부트의 경우 2.2.0부터 application/json;charset=UTF-8
요청에 대해서 charset=utf-8
이 빠지게 되었습니다.
스프링 부트 2.2.0 부터는 utf-8 인코딩 처리를 별도로 해주지 않게 변경되었기 때문에 APPLICATION_JSON_UTF8
도 자연히 deprecated된 것이지요.
그래서 utf-8 인코딩에 대한 처리를 별도로 해줘야 했습니다.
한글이 깨지는 원인도 스프링 부트 2.2.0 부터 charset=utf-8
이 deprecated 되었기 때문이었습니다.
인코딩 처리를 하는 방법은 여러 방법이 있을 수 있는데 메시지 컨버터에 추가하는 방법도 있으며 (아래 레퍼런스 참조) 저희 팀의 경우 필터에 utf-8을 추가하여 이 문제를 해결하였습니다.
그럼 스프링은 왜 응답에 charset=utf-8을 없앴나?
이 원인은 크롬 브라우저와 같이 주요 브라우저들이 사양을 준수하고 charset=UTF-8
로 인코딩되는 특수한 문자들을 올바르게 해석해주므로 정확히는 스프링 5.2부터, 스프링 부트의 경우 2.2.0부터 응답에 이를 포함시키지 않게 되었습니다.
Reference
http://honeymon.io/tech/2019/10/23/spring-deprecated-media-type.html