[MSA] FeignException 핸들링하기

Nicky·2024년 10월 7일
0

Trouble Shooting 

목록 보기
3/4
post-thumbnail

문제 상황

부모 서비스에서 FeignClient로 요청을 호출 시 예외가 처리되지 않는 문제가 생겼다.

현재 다음과 같이 공통된 형태의 예외 응답을 만들어서 쓰고 있어서

응답을 받고..

FeignClientAdapter

@FeignClientAdapter
@RequiredArgsConstructor
public class QueueManageClientAdapter {

    private final QueueManageClient queueManageClient;
    private final FeignClientResponseValidator responseValidator;

    public CommonResponse getWaitingQueueInfo(UUID userId) {
        CommonResponse response = queueManageClient.getWaitingQueueInfo(userId);
        responseValidator.validate(response);
        return response;
    }

}

validator로 예외상황을 처리할 생각이었는데 원하는대로 동작하지 않았다.

FeignClientResponseValidator

@Component
public class FeignClientResponseValidator {
    public void validate(CommonResponse<?> response) {
        HttpStatus statusCode = response.getStatus();
        if (!statusCode.is2xxSuccessful()) {
            ClientErrorCase errorCase = fromMessage(response.getMessage());
            throw new ApplicationException(errorCase);
        }
    }
}

이유는 즉, Feign 클라이언트가 기본적으로 HTTP 요청이 실패할 경우 FeignException 예외를 발생시키기 때문이었는데, 이를 핸들링하려면 ErrorDecoder를 커스텀으로 사용해야 한다고 한다. 하지만 이것은 만들어둔 예외 응답을 새로 만들어야 해서 비효율적이라고 생각이 들었다.

해결 과정

따라서 기존에 만들어둔 예외 응답을 그대로 사용하는 방법을 찾던 중, GlobalExceptionHandler에서 FeignException를 핸들링하는 방법을 찾았다.

GlobalExceptionHandler

@ControllerAdvice
@RequiredArgsConstructor
public class GlobalExceptionHandler {

    private final ObjectMapper objectMapper;

    @ExceptionHandler(FeignException.class)
    public ResponseEntity feignExceptionHandler(FeignException feignException) throws JsonProcessingException {
        String responseJson = feignException.contentUTF8();
        Map<String, String> responseMap = objectMapper.readValue(responseJson, Map.class);
        return ResponseEntity
                .status(feignException.status())
                .body(responseMap);
    }

}

이번엔 원하는 대로 예외 응답을 받는 것을 확인할 수 있다!

별도의 검증 로직이 필요 없어져 오히려 이전 보다 코드가 간결해진 모습이다.

FeignClientAdapter

@FeignClientAdapter
@RequiredArgsConstructor
public class QueueManageClientAdapter {

    private final QueueManageClient queueManageClient;

    public CommonResponse getWaitingQueueInfo(UUID userId) {
        return queueManageClient.getWaitingQueueInfo(userId);
    }

}
profile
배우고 기록하는 공간

0개의 댓글