Spring Boot는 @ExceptionHandler와 @ControllerAdvice 어노테이션을 통해 전역적인 예외 처리 기능을 제공하며, 이를 통해 코드의 중복을 줄이고 효율적인 예외 관리를 가능하게 합니다.
@ExceptionHandler는 컨트롤러 클래스 안에 정의되어 해당 컨트롤러에서 발생하는 예외를 처리하는 데 사용됩니다. 이를 사용하면 try-catch 블록 없이 예외를 처리할 수 있습니다.
@RestController
public class UserController {
@GetMapping("/user/{id}")
public String getUser(@PathVariable int id) {
if (id == 0) {
throw new UserNotFoundException("User not found with ID: " + id);
}
return "User found";
}
@ExceptionHandler(UserNotFoundException.class)
public ResponseEntity<ErrorResponse> handleUserNotFound(UserNotFoundException e) {
ErrorResponse error = new ErrorResponse(
HttpStatus.NOT_FOUND.value(),
"User not found",
e.getMessage()
);
return new ResponseEntity<>(error, HttpStatus.NOT_FOUND);
}
}
예외 발생
UserController의 getUser에서 UserNotFoundException이 발생합니다.
사용자 ID로 사용자를 조회했는데 해당 사용자가 없는 경우입니다.
예외 캐치:
@ExceptionHandler가 UserNotFoundException을 캐치합니다.
handleUserNotFound 메서드가 호출됩니다.
응답 생성:
ErrorResponse 객체가 생성되고, 예외 정보가 담깁니다.
ResponseEntity를 통해 ErrorResponse와 HTTP 상태 코드 404가 클라이언트에게 반환됩니다.
이 방식은 각 컨트롤러마다 예외 처리 코드를 작성해야 하는 단점이 있습니다.
@ControllerAdvice를 사용하면 모든 컨트롤러에서 발생하는 예외를 한 곳에서 처리할 수 있습니다.
@ControllerAdvice
public class GlobalExceptionHandler {
private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);
@ExceptionHandler(UserNotFoundException.class)
public ResponseEntity<ErrorResponse> handleUserNotFound(UserNotFoundException e) {
logger.error("User not found exception occurred: ", e);
ErrorResponse error = new ErrorResponse(
HttpStatus.NOT_FOUND.value(),
"User not found",
e.getMessage()
);
return new ResponseEntity<>(error, HttpStatus.NOT_FOUND);
}
}
예외 발생
어떤 컨트롤러에서든 UserNotFoundException이 발생합니다.
예외 캐치
@ControllerAdvice가 예외를 캐치합니다.
예외의 타입에 따라 적절한 @ExceptionHandler 메서드가 호출됩니다.
응답 생성
ErrorResponse 객체가 생성되고, 예외 정보가 담깁니다.
ResponseEntity를 통해 ErrorResponse와 적절한 HTTP 상태 코드가 클라이언트에게 반환됩니다.
| 구분 | @ExceptionHandler (컨트롤러에 붙이는 경우) | @ControllerAdvice (전역 예외 처리) |
|---|---|---|
| 범위 | 특정 컨트롤러 내에서만 동작 | 모든 컨트롤러에서 동작 |
| 사용 목적 | 특정 API에서만 발생하는 예외 처리 | 애플리케이션 전반에서 발생하는 예외 처리 |
| 코드 중복 | 여러 컨트롤러에서 동일한 예외를 처리하려면 중복 코드 발생 | 중복 코드 없이 일관된 예외 처리 가능 |
| 유지보수성 | 특정 컨트롤러에 종속적이므로 유지보수가 어려움 | 중앙화된 예외 처리로 유지보수가 쉬움 |