Study/spring

[Java] Spring Boot 3 @RestControllerAdvice @ExceptionHandler 사용법

 

스프링에는 예외 처리를 위해 @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 실행 시 내부에서 에러가 발생했을 때 반환되는 값
API 실행 시 내부에서 에러가 발생했을 때 반환되는 값

API 실행 시 내부에서 에러가 발생하면 500 에러가 반환됩니다.

만약 에러가 발생한 원인이 외부에 있는 경우(ex. 입력 값이 잘못되었을 때, 요청을 잘못했을 때)에는 적절한 응답 코드와 응답 메시지를 반환하는 게 좋습니다.

 

요청 메소드(GET, POST)가 잘못되었거나 하는 경우에는 스프링에서 적절한 에러 코드를 반환해주기는 하지만, 에러에 대한 메시지를 전부 반환하기 때문에 비효율적입니다.

Request Method를 잘못 사용했을 때 반환되는 값
Request Method를 잘못 사용했을 때 반환되는 값

스프링에 의해 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 설정 후 반환 값
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 문서나 팀 내부에서 정의된 에러 응답 형식이 따로 있다면 이런 방식으로 반환하면 됩니다.