순조롭게 프로젝트를 진행하던 중, postman 에서 응답을 받는데 한글이 아닌 ???를 받았다. 이게 뭔가… 일단 encoding 문제인 것 같아 차근차근 문제를 해결해보기로 한다. 이 문제를 해결하기 위해 여러 방법들을 찾아보았고 그 순서에 따라 글을 작성했다.
postman 페이지 자체에서 문제가 있나 ? 싶어 command + , 명령어를 통해 incoding 설정을 찾아보려 했으나 따로 그런것은 없었다. 즉, 서버에서 오가면서 charset을 어떤 것으로 설정하느냐의 문제였고, 위 오류를 제외하고 다른 요청 응답에서는 한글이 잘만 출력되는 것을 확인했다.
즉, postman 자체에는 문제가 없다.
그렇다면,, 현재 Spring을 통해 개발하고 있는 intelliJ에 문제가 생긴 것은 아닌가 ? 라는 생각과 함께
command + , 명령어로 intelliJ 설정에 들어갔다. 마찬가지로 딱히 그런 설정은 없었다. 그래서 헤더에 application/json;charset=UTF-8
을 넣어준다면 정상적으로 출력되지 않을까? 하여 controller에 @GetMapping(value = "/categories", produces = "application/json;charset=UTF-8")
이렇게 입력하여 인코딩에서 문제가 생기지 않도록 설정했지만,, 결과는 ???로 동일했다..
그렇다면,, 어떻게 해야하나 싶을때, WebMvcConfigurer
를 구현하는 어떤 설정자를 만들어 컨트롤러에서 전송하는 모든 응답 데이터의 인코딩이 UTF-8로 인코딩된다는 사실을 알게되었다. 바로 도전해본다.
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Override
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
configurer.defaultContentType(MediaType.APPLICATION_JSON, MediaType.TEXT_PLAIN)
.mediaType("json", MediaType.APPLICATION_JSON)
.mediaType("text", MediaType.TEXT_PLAIN)
.parameterName("mediaType")
.favorPathExtension(true);
}
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(new StringHttpMessageConverter(StandardCharsets.UTF_8));
converters.add(new MappingJackson2HttpMessageConverter());
}
}
WebMvcConfig를 만들어서 모든 요청이 UTF-8로 인코딩되는 코드이다. 하지만,, 이렇게 설정해도 값이 변하지 않는다는 것을 깨달았다.. 대체.. 뭘 어떻게..
찾았다.. 생각보다 이유는 간단했다. 나는 정적인 파일들을 임의로 DB에 저장하기 위해 application.properties 에 한글로 모든 파일명을 저장해놓았고, 이를 불러오면서 split을 통해 String[] 에 담아 각 파일명을 이용했다. 혹시라는 생각에 나는 이 Spring[] 을 출력해보았고 그 결과는 ???인 것을 확인했다..
결국,, 파일 encoding 문제였다.
나는 문제를 찾았으니 푸는건 금방이라고 생각했지만,, 정말 크나큰 오산이였다. application.properties 파일을 utf-8로 인코딩하기 위해
@PropertySource(value = "classpath:application.properties", encoding = "UTF-8")
위 코드를 사용하였고, 이는 파일을 지정한 형식으로 encoding 하여 가져올 수 있다는 뜻이다. 하지만 이게 왠걸.. 이래도 물음표 살인마는 굳건했다.
SpringBoot 에서 properties를 읽을 수 있는 PropertySourceLoader
를 구현하고 있는 PropertiesPropertySourceLoader
클래스를 알아보았다.
PropertiesPropertySourceLoader
클래스 내부에서는 OriginTrackedPropertiesLoader
의 load()
메서드를 호출한다.
위에서 볼 수 있듯이 OriginTrackedPropertiesLoader
내부에서 사용하는 CharacterReader
클래스는 인코딩을 StandardCharsets.ISO_8859_1로 하고 있다… yml 의 기본 인코딩은 StandardCharsets.UTF_8 이지만, properties는 ISO_8859_1이기 때문에 그동안 많은 짓을 해도.. 변경되지 않고 물음표 살인마와 마주쳤던 것이다..
이제 이를 해결하기 위해 우리는 단 한가지의 설정을 해주면 된다(ㅠㅠ).
위의 Transparent native-to-ascii conversion 을 체크해준다면 properties 인코딩 설정을 변경할 수 있게 된다. 이제는 우리가 기존에 짰던 코드에서 인코딩을 UTF-8 로 변경하고자 했던 노력들이 성공할 수 있게 된다.
이로써 값은 완벽하게.. 한글로 나오기 시작했다. 시간은 오래걸렸지만, 인코딩에 대해 깊게 생각해볼 수 있는 시간이였던 것 같다.