ControllerAdvice - kotlin

Sung Jun Jin·2021년 11월 21일
0

스프링 애플리케이션에서 Controller 내에서 글로벌하게 발생하는 예외를 ControllerAdvice를 사용해 핸들링 할 수 있다.

우선 ControllerAdvice란?

특정 패키지나 컨트롤러, 나아가서 컨트롤러 단에서 글로벌하게 발생하는 예외를 공통적으로 처리할 수 있는 어노테이션이다.

우선 실습을 위해 컨트롤러를 생성해보자.

@RestController
@RequestMapping("/api/exception")
class ExceptionApiController {

    @GetMapping("/test")
    fun controllerAdvice() {
        val list = mutableListOf<String>()
        val temp = list[0]
    }
}

일부로 예외를 내도록 빈 리스트에서 0번째 인덱스를 가져오게 해보자. IndexOutOfBoundsException exception이 발생함을 예측할 수 있다.

로컬에서 서버를 구동시킨 다음에 Postman으로 방금 작성한 api를 호출해보자.

역시나 기본 500, Internal Server Error가 발생한다. 로그를 확인해보면 전형적으로 핸들링 처리가 되지 않은 인덱스 에러가 발생함을 확인할 수 있다.

이제 ControllerAdvice 어노테이션을 사용해 발생한 위 예외를 핸들링해보자.

advice 패키지를 생성해 GlobalControllerAdvice 클래스를 생성한다

@RestControllerAdvice
class GlobalControllerAdvice {
    @ExceptionHandler(value = [IndexOutOfBoundsException::class])
    fun indexOutOfBoundException(e: IndexOutOfBoundsException): String {
        return "Index Error 발생"
    }
}
  • @RestControllerAdvice 어노테이션을 달아주면 해당 클래스는 ControllerAdvice의 역할을 하게 된다.
  • 클래스 내의 함수를 작성하고 @ExceptionHandler 어노테이션을 사용한다 value 안에는 따로 핸들링하고 싶은 ExceptionArray로 받는다. 여기서는 IndexOutOfBoundsException만 필요하므로 위 같이 작성해준다.
  • 두 종류 이상의 Exception을 처리하고 싶다면 @ExceptionHandler를 아래와 같이 작성할 수 있다.
    @ExceptionHandler(value = [IndexOutOfBoundsException::class, RuntimeException::class])

서버를 다시 재가동 시킨 후 똑같이 api를 호출해보자.

IndexOutOfBoundsException가 따로 핸들링 되었다. 하지만 200 응답을 내주는건 조금 이상하니까 따로 500용 ResponseEntity를 반환해서 처리해주자.

@RestControllerAdvice
class GlobalControllerAdvice {
    @ExceptionHandler(value = [IndexOutOfBoundsException::class])
    fun indexOutOfBoundException(e: IndexOutOfBoundsException): ResponseEntity<String>{
        return ResponseEntity.internalServerError().body("Index Error 발생")
    }
}

그리고 다시 호출해보면 아래와 같이 500 response code와 함께 핸들링한 메세지로 응답이 오는 부분을 확인할 수 있다.

위 처럼 글로벌하게 정의해 애플리케이션의 컨트롤러에서 발생하는 모든 예외를 처리할수도 있지만 특정 패키지나, 컨트롤러에 한해서만 에러핸들링 처리가 가능하다.

@ResControllerAdvice 어노테이션에서 basePackageClasses를 활용해주면 된다.

예시) PutApiController 내부에서만 에러 핸들링을 제한해보기

@RestControllerAdvice(basePackageClasses = [PutApiController::class])
class PutApiControllerAdvice
profile
주니어 개발쟈🤦‍♂️

0개의 댓글