개발/Spring

[Spring] 응답 대신 Exception - RestTemplate_DefaultResponseErrorHandler.handleError

kku-lab 2024. 9. 11. 10:57
at org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:94)

Datadog를 확인하던 중 에러 Log를 발견했다.


try{
   RestTemplate restTemplate = new RestTemplate();
   ...
   ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.POST, request, String.class);
}catch(HttpStatusCodeException e){
   ...
}

 

RestTemplate를 사용해여 외부 API와 통신을 하던 중 발생한 에러였고, 'response'에 json 응답으로 에러가 왔어야 한다.


{
   "ststusCode": 500
   ...
}

 

내가 생각한 응답 코드는 이 형태였지만, 완전한 정답은 아니였다.

RestTemplate의 'response'는 4xx, 5xx의 응답 코드를 받으면 Exception을 발생시킨다는 사실을 몰랐다.

 

무조건 응답이 올 줄 알았기 때문에 if문을 사용하고 있었다.

즉, catch 부분에 로그 기록만 남겼었고, 에러가 발생한 데이터를 처리하지 못했다.

다행히 관리자 부분에 데이터 처리 여부를 확인하는 기능이 있었고, 그 기능을 사용하여 처리를 하였다.


그렇다면 4xx, 5xx 의 응답 코드가 발생했을 때 처리 방법은 catch문에 대처 코드를 추가하거나,

DefaultResponseErrorHandler 클래스가 아닌 CustomErrorHandler를 사용하는 것이다.

 

public class RestTemplateErrorHandler implements ResponseErrorHandler {
    @Override
    public boolean hasError(ClientHttpResponse response) throws IOException {
        //에러를 항상 false로 반환 -> 에러가 없다고 판단하게 한다.
        return false;
    }

    @Override
    public void handleError(ClientHttpResponse response) throws IOException {
       //아무 동작이 없다 -> 에러 발생 시에도 별도 처리가 없다.
    }
}

try{
   RestTemplate restTemplate = new RestTemplate();
   ...
   //코드추가//
   restTemplate.setErrorHandler(new RestTemplateErrorHandler());
 
   ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.POST, request, String.class);
}catch(HttpStatusCodeException e){
   ...
}

 

이 방식은 RestTemplate의 기본 에러 핸들러를 재정의 한 방법이다.

hasError() 메소드가 항상 false를 반환하고,

handleError() 메소드가 아무 동작도 하지 않기 때문에 실제로 에러 처리가 이루어지지 않는다.

4xx, 5xx 의 응답 코드를 감지해도 Exception을 발생시키지 않고, 정상적인 응답처럼 처리할 수 있게 되었다.