[Spring] RestTemplate 한글 깨짐(StringHttpMessageConverter)

wlsh44·2022년 9월 27일

spring

목록 보기
1/2

spring 2.6.3 기준으로 작성된 글입니다.

이번 포스팅에서는 spring의 RestTemplate로 한글이 담긴 문자열을 포함한 Post형식의 Request를 보낼 때 한글이 깨지는 현상의 해결 방법에 대해 작성해보려고 합니다.

문제 상황

우선 문제 상황에 대해 살펴보겠습니다.

안녕! hi!이라는 한글과 영어가 포함된 간단한 문자열을 보내는 테스트 코드를 작성해보겠습니다.

@SpringBootTest
public class Test {

    @Autowired RestTemplate restTemplate;

    @org.junit.jupiter.api.Test
    void test() {
        HttpHeaders httpHeaders = new HttpHeaders();
        String str = "안녕! hi!";
        HttpEntity<String> entity = new HttpEntity<>(str, httpHeaders);


        restTemplate.exchange("http://localhost:8080/hi", HttpMethod.POST, entity, String.class);
    }
}
@WebServlet(urlPatterns = "/hi")
public class IndexController extends HttpServlet {

    @Override
    public void service(HttpServletRequest request, HttpServletResponse response) throws IOException {
        ServletInputStream inputStream = request.getInputStream();
        System.out.println(StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8));
    }
}

위의 사진처럼 안녕을 제대로 출력하지 못하는 것을 볼 수 있습니다.

이는 문제의 원인은 RestTemplateString을 인코딩할 때 사용하는 StringHttpMessageConverter에 있습니다.

RestTemplate의 생성자에 들어가 보시면 기본적으로 StringHttpMessageConverter라는 객체를 messageConverters에 추가함을 알 수 있습니다.

그런데 이때 StringHttpMessageConverterDefault CharsetISO-8859-1이고 이를 이용해 한글을 인코딩하기 때문에 한글이 깨지는 현상이 발생하게 됩니다.

해결 방법

제가 찾아본 해결 방법으로는 크게 두 가지가 있는데 모두 알아보겠습니다.

Custom StringHttpMessageConverter 추가

첫 번째로는 RestTemplateCustom StringHttpMessageConverter를 추가하는 방법입니다.

위의 사진을 보시면 StringHttpMessageConverterdefaultCharset을 인자로 받는 생성자가 존재합니다.

따라서 UTF-8을 넣어 객체를 만들고, 이를 RestTemplatemessageConverters 리스트 안에 추가해줍니다.

    @Bean
    public RestTemplate restTemplate() {
        RestTemplate restTemplate = new RestTemplate();

        restTemplate.getMessageConverters()
                .add(0, new StringHttpMessageConverter(StandardCharsets.UTF_8));
        return restTemplate;
    }

이때 리스트의 첫 번째 위치로 추가시키는 이유는 기존에 존재하는 StringHttpMessageConverter 때문입니다.

만약 맨 뒤에 추가하게 되면 기존의 default로 생성된 StringHttpMessageConverterISO-8859-1로 인코딩하게 되어 같은 결과가 나타납니다.

StringHttpMessageConverter Bean 이용

두 번째로는 기존에 존재하는 StringHttpMessageConverter를 추가해주는 방법이 있습니다.
사실 Springboot에는 첫 번째 방법처럼 객체를 새로 만들지 않아도 StringHttpMessageConverter가 빈으로 등록되어 있습니다.

그 부분은 HttpMessageConvertersAutoConfiguration에서 확인할 수 있습니다.

이때 server.sevlet.encoding에 대한 properties를 binding 해줌을 볼 수 있습니다.

따라서 application.properties에 다음과 같은 property를 추가하고 RestTemplate에 추가시켜줍니다.

server.servlet.encoding.charset=UTF-8

server.servlet.encoding에 대한 여러 설정에 대해 대해 알고 싶으시다면 이곳에서 확인해주세요.

    @Bean
    public RestTemplate restTemplate(StringHttpMessageConverter stringHttpMessageConverter) {
        RestTemplate restTemplate = new RestTemplate();

        restTemplate.getMessageConverters().add(0, stringHttpMessageConverter);
        return restTemplate;
    }

또는 새로운 messageConverters 리스트를 만들어서 setter를 통해 추가해줄 수도 있습니다.

    @Bean
    public RestTemplate restTemplate(StringHttpMessageConverter stringHttpMessageConverter) {
        RestTemplate restTemplate = new RestTemplate();

        List<HttpMessageConverter<?>> messageConverters = List.of(stringHttpMessageConverter);
        restTemplate.setMessageConverters(messageConverters);
        return restTemplate;
    }

다만 이 경우 기존의 messageConverters를 아예 지워버리기 때문에 다른 messageConverter를 필요에 따라 추가해주셔야 합니다.

이후 다시 테스트를 해보면 잘 자동함을 볼 수 있습니다.

업로드중..

참조

https://cornswrold.tistory.com/402

https://stackoverflow.com/questions/29392422/how-can-i-tell-resttemplate-to-post-with-utf-8-encoding

profile
정리정리

0개의 댓글