API 예외처리 - 스프링부트가 제공하는 ExceptionHandler

현시기얌·2021년 8월 17일
0

Api 예외처리

목록 보기
3/6

스프링 부트가 기본으로 제공하는 ExceptionHandler

스프링 부트가 기본으로 제공하는 ExceptionHandler는 다음과 같다.

HandlerExceptionResolverComposite에 다음 순서로 등록
1. ExceptionHandlerExceptionResolver
2. ResponseStatusExceptionResolver
3. DefaultHandlerExceptionResolver --> 우선순위가 제일 낮다.

ExceptionHandlerExceptionResolver

@ExceptionHandler을 처리한다. API 예외 처리는 대부분 이 기능으로 해결한다.

ResponseStatusExceptionResolver

HTTP 상태 코드를 지정해준다.
ex) @ResponseStatus(value = HttpStatus.NOT_FOUND)

DefaultHandlerExceptionResolver

스프링 내부 기본 예외를 처리한다.

ResponseStatusExceptionResolver

ResponseStatusExceptionHandler는 예외에 따라서 HTTP 상태 코드를 지정해주는 역할을 한다.

다음 두 가지 경우를 처리한다.
1. @ResponseStatus가 달려있는 예외
2. ResponseStatusException 예외

사용자 정의 BadRequestException

@ResponseStatus(code = HttpStatus.BAD_REQUEST, reason = "잘못된 요청 오류")
public class BadRequestException extends RuntimeException{
}

API Controller

 @GetMapping("/api/response-status-ex1")
 public String responseStatusEx1() {
     throw new BadRequestException();
 }

결과

@ResponseStatus 어노테이션을 이용해 HTTP상태 코드를 지정해 줬기 때문에 500에러가 아닌 400에러가 발생한다.

우리가 만든 BadRequestException 예외가 컨트롤러 밖으로 넘어가면 ResponseStatusExceptionResolver 예외가 해당 어노테이션을 확인해서 오류 코드를 httpStatus.BAD_REQUEST(400)으로 변경하고, 메세지도 담는다.

ResponseStatusExceptionResolver 코드를 확인해보면 결국 response.sendError(statusCode,resolvedReason)를 호출하는 것을 확인할 수 있다.
sendError(400)을 호출했기 때문에 WAS에서 다시 오류 페이지 /error를 내부 요청한다.

메세지 사용

 server:
  error:
    include-message: always

위와 같이 include-message를 always로 설정하면 메세지까지 출력 가능하다.

메세지 처리 또한 가능하다.

messages.properties

error.bad=잘못된 요청 오류입니다. 메세지 사용

BadRequestException

@ResponseStatus(code = HttpStatus.BAD_REQUEST, reason = "error.bad")
public class BadRequestException extends RuntimeException{
}

결과

ResponseStatusException

@ResponseStatus는 개발자가 직접 변경할 수 없는 예외에는 적용할 수 없다. (어노테이션을 직접 넣어야 하는데, 내가 코드를 수정할 수 없는 라이브러리의 예외 코드 같은 곳에는 적용할 수 없다. ex) BindException, MethodArgumentNotValidException...)
추가로 어노테이션을 사용하기 때문에 조건에 따라 동적으로 변경하는 것도 어렵다.
이때는 ResponseStatusException 예외를 사용하면 된다.

API Controller

   @GetMapping("/api/response-status-ex2")
   public String responseStatusEx2() {
       throw new ResponseStatusException(HttpStatus.NOT_FOUND, "error.bad", new IllegalArgumentException());
   }

결과

profile
현시깁니다

0개의 댓글