[Spring] RestTemplate 요청 에러 (HttpStatusCodeException)의 인코딩이 깨짐 문제

식빵·2022년 7월 28일
1

Spring Lab

목록 보기
14/34
post-thumbnail

😱 문제 발생

getForEntity 나 getForObject 등을 사용하면 특이하고 HttpStatusCodeException 예외로 받았을 때 한글 깨짐현상이 일어났다.



👏 해결 과정

RestTemplate 자체에서 상태 코드 200을 못 받은 getForXXX 메소드 자체에서 에러가 던져진다. 그리고 이때 어떤 예외를 던지고, 예외 자체에 API 에 호출에서 받은 결과에 대한 responseBody, Header, StatusCode 등의 데이터를 넣어주는 역할을 하는 클래스가 존재한다. 그게 바로 DefaultErrorHandler 클래스이다.

즉 RestTemplate 은 생성시에 setErrorHandler() 메소드로 직접 등록하지 않으면 기본적으로 DefaultErrorHandler 핸들러를 사용하는 것이다.

중요한 것은 HttpStatusCodeException 예외에 넣을 Body 의 내용에 대한 Charset 을 어떤 것을 사용할지를 결정하는 메소드가 있는데, 그게 바로 DefaultErrorHandler 내부있는 getCharset 메소드다.

이 메소드를 Override하면 되는 것이다.
아래 처럼하면 해결이 된다.

RestTemplate rest = new RestTemplate();
rest.setErrorHandler(new DefaultErrorHandler() {
	
    @Override
    protected Charset getCharset(ClientHttpResponse response) {
    	return StandardCharsets.UTF_8;
    }
});

사실 이외에도 조금 어렵게 가는 방법도 있기는 하다.
restTemplate.getForXXX, restTemplate.postForXXX 메소드가 아니라
restTemplate.exchange 메소드를 사용하면 직접적으로 요청 Header 를 세팅할 수 있다.
이때 이 Header 에 Charset 을 UTF-8 로 지정하면 되는 것이다.
아래처럼 말이다.

// 헤더 생성
HttpHeaders headers = new HttpHeaders();
		
// application/json;charset=UTF-8  을 위해 특화되어 있다.
headers.setContentType(MediaType.APPLICATION_JSON_UTF8);

// **** Accept 헤더 값에서 Charset이 설정되게 한다!!!!!!!
headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON_UTF8));


// 요청 URL 생성
UriComponents build = getDefaultComponentBuilder()
  .path(requestApiUri)
  .queryParams(queryParam)
  .build().encode();

HttpEntity requestEntity = new HttpEntity(headers);

try {
	RestTemplate rest = new RestTemplate;
  
	ResponseEntity<JsonNode> response 
             = rest.exchange(build.toUri(), 
  					method, 
                    requestEntity, 
                    JsonNode.class);
                    
catch (HttpStatusCodeException e) {
	 ResponseEntity.status(e.getRawStatusCode())
    				.headers(e.getResponseHeaders())
                    .body(e.getResponseBodyAsString()); // **** 한글이 안깨진다!
}



✨ 참고 링크

profile
백엔드를 계속 배우고 있는 개발자입니다 😊

0개의 댓글