스프링에는 예외 처리를 위해 @ExceptionHandler와 @ControllerAdvice, @RestControllerAdvice 어노테이션이 존재합니다.
이 어노테이션을 사용하는 이유와 예제를 소개해드리겠습니다.
ExceptionHandler를 사용하는 이유
스프링 부트에서 REST API를 요청했을 때 에러가 발생하면 일반적으로 다음과 같은 응답값이 반환됩니다.
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class ExceptionHandlerController {
@GetMapping("/exception/null")
public String nullPointerException() {
throw new NullPointerException("Null Pointer Exception");
}
}
API 실행 시 내부에서 에러가 발생하면 500 에러가 반환됩니다.
만약 에러가 발생한 원인이 외부에 있는 경우(ex. 입력 값이 잘못되었을 때, 요청을 잘못했을 때)에는 적절한 응답 코드와 응답 메시지를 반환하는 게 좋습니다.
요청 메소드(GET, POST)가 잘못되었거나 하는 경우에는 스프링에서 적절한 에러 코드를 반환해주기는 하지만, 에러에 대한 메시지를 전부 반환하기 때문에 비효율적입니다.
스프링에 의해 4xx 에러가 반환되지만, 응답 Body에 에러에 대한 stacktrace가 포함되어 있습니다.
@ControllerAdvice와 @ExceptionHandler는 이런 상황에서 불필요한 값을 제외하고 필요한 값만 반환되게 할 수 있습니다.
사용 예제
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(NullPointerException.class)
public ResponseEntity<?> nullPointerException(NullPointerException e) {
return ResponseEntity
.badRequest()
.body(e.getMessage());
}
}
NullPointerException이 발생했을 때 400 에러(Bad Request)와 메시지를 반환하는 코드입니다.
ExceptionHandler를 설정한 다음 예외가 발생하면 다음과 같이 반환됩니다.
예외 발생 시 ExceptionHandler에 의해 설정된 에러 코드와 메시지가 반환되었습니다.
@RestControllerAdvice에 의해 응답값이 Body로 반환되었습니다.
만약 @ControllerAdvice를 사용했다면 설정된 페이지로 이동하게 됩니다.
에러 형식 지정 방법
에러 반환 형식이 따로 정해져 있다면 형식에 맞게 반환하도록 설정하면 됩니다.
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import lombok.AllArgsConstructor;
import lombok.Getter;
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(NullPointerException.class)
public ResponseEntity<Response> nullPointerException(NullPointerException e) {
return ResponseEntity
.badRequest()
.body(new Response("NPE", e.getMessage()));
}
@Getter
@AllArgsConstructor
public static class Response {
private String code;
private String message;
}
}
에러 발생 시 code와 message를 반환하는 코드입니다.
이 상태로 예외가 발생하면 다음과 같이 반환됩니다.
API 문서나 팀 내부에서 정의된 에러 응답 형식이 따로 있다면 이런 방식으로 반환하면 됩니다.