ihoneymon / blog-comments

honeymon.io 댓글관리
0 stars 0 forks source link

/tech/2019/10/23/spring-deprecated-media-type #5

Open utterances-bot opened 4 years ago

utterances-bot commented 4 years ago

[spring] Deprecate MediaType.APPLICATION_JSON_UTF8 in favor of APPLICATION_JSON - I'm honeymon(JiHeon Kim).

참고: Deprecate MediaType.APPLICATION_JSON_UTF8 in favor of APPLICATION_JSON · Issue #22788 · spring-projects/spring-framework

http://honeymon.io/tech/2019/10/23/spring-deprecated-media-type.html

mayaul commented 4 years ago

2개의 속성으 ㄹ가지고 있음 -> 2개의 속성을가지고 있음 오타 수정해주세요 :)

kimmunsu commented 4 years ago

형은 역시 구세주...

jwee0330 commented 4 years ago

많은 도움이 되었습니다! 감사합니다

ppyong commented 3 years ago

안녕하세요! 문의 드릴게 있어서 댓글 달아요. mockMvc에서 응답에 한글이 깨져서 보다가 들어왔는데요.

해결법 3가지 중 2개가 RestTemplate인데요. 혹시 mockMvc를 사용해서 요청 시 내부적으로는 RestTemplate를 사용해서 이렇게 설정하는건가요?

추가로 "응답값을 문자열(String) 대신 객체로 변환하여 처리" 의미를 알 수 있을까요? 컨트롤러에서는 객체로 반환인데 내부에서 응답을 적절한 JSON 응답으로 만드는걸텐데요. 이걸 어떻게 객체로 변환하여 처리하란건지 이해가 안가서요 ㅠㅠ;

ihoneymon commented 3 years ago

@ppyong 님이 물어보시는 내용이

둘 중에 어떤 경우를 말하는 것인지 궁금합니다.

첫번째 경우는, MockHttpServletResponse 에서 mockMvc 에서 사용하는 PrintingResultHandler 가 사용하는 MockHttpServletResponse 에서 캐릭터인코딩값을 가져오는 코드가 개선이 되어야 합니다.

protected void printResponse(MockHttpServletResponse response) throws Exception {
    String body = (response.getCharacterEncoding() != null ?
            response.getContentAsString() : MISSING_CHARACTER_ENCODING);

    this.printer.printValue("Status", response.getStatus());
    this.printer.printValue("Error message", response.getErrorMessage());
    this.printer.printValue("Headers", getResponseHeaders(response));
    this.printer.printValue("Content type", response.getContentType());
    this.printer.printValue("Body", body);
    this.printer.printValue("Forwarded URL", response.getForwardedUrl());
    this.printer.printValue("Redirected URL", response.getRedirectedUrl());
    printCookies(response.getCookies());
}

MockHttpServletResponse.getCharacterEncoding() 에서 캐릭터셋을 결정하는 코드가 여전히 Content-Type 에서 charset 값을 가져오고 있어서 기본캐릭터셋인 ISO-8859-1 를 가지고 있습니다.

private void updateContentTypeHeader() {
    if (this.contentType != null) {
        String value = this.contentType;
        if (this.charset && !this.contentType.toLowerCase().contains(CHARSET_PREFIX)) {
            value = value + ';' + CHARSET_PREFIX + this.characterEncoding;
        }
        doAddHeaderValue(HttpHeaders.CONTENT_TYPE, value, true);
    }
}

mockMvc 의 출력물은 크게 신경쓰지 않으셔도 됩니다. 혹은 https://github.com/HomoEfficio/dev-tips/blob/master/Spring%20Test%20MockMvc의%20한글%20깨짐%20처리.md 를 참조하셔서 MockMvcBuilder 에서 필터를 추가하시면 됩니다.

ihoneymon commented 3 years ago

이 글에서 중요한 것은, API 측(서버)에서 스프링 부트 2.2.0 이상을 사용하면 요청헤더에 Content-Type: applicatoin/json; charset=UTF-8 으로 요청해서 charset=UTF-8 헤더가 소거되어 응답하기 때문에 클라이언트(사용자측)에서 Content-Type 에 있는 charset 을 선택하면서

String response = restTemplate.getObject("{requestUrl}", String.class);

으로 받게되는 경우 responseISO_8859_1 캐릭터셋을 사용하여 한글이 깨져보일 수 있다는 것을 주의하면 됩니다.

ihoneymon commented 2 years ago

다음과 같이 .addFilter(new CharacterEncodingFilter(StandardCharsets.UTF_8.name(), true))를 추가할 수 있음

        return MockMvcBuilders.standaloneSetup(controllers)
//                .defaultResponseCharacterEncoding(StandardCharsets.UTF_8)
                .setControllerAdvice(
                        new GlobalRestControllerExceptionHandler(),
                        new ApiResponseWrappingAdvisor())
                .setConversionService(conversionService)
                .setMessageConverters(new MappingJackson2HttpMessageConverter(JsonUtils.getMapper()))
                .addFilter(new CharacterEncodingFilter(StandardCharsets.UTF_8.name(), true)); // UTF-8

그러나 이렇게 할 경우 테스트에서 Content-Type 은 변경되지 않습니다.

오랜만에 MockMvc 코드를 열어보다가 다음과 같이 선언하면 되지 않을까 하는 생각을 했습니다. AbstractMockMvcBuilder#defaultResponseCharacterEncoding

return MockMvcBuilders.standaloneSetup(controllers)
                .defaultResponseCharacterEncoding(StandardCharsets.UTF_8)
                .setControllerAdvice(
                        new GlobalRestControllerExceptionHandler(),
                        new ApiResponseWrappingAdvisor())
                .setConversionService(conversionService)
                .setMessageConverters(new MappingJackson2HttpMessageConverter(JsonUtils.getMapper()));

요렇게 하면 아주 깔끔하게 처리됩니다. spring-test 5.3.10 에 추가됐군요.