Spring Boot 기본 ExceptionResolver 3종 완전 정리
Spring MVC에서 예외가 발생하면 DispatcherServlet은 내부적으로 HandlerExceptionResolverComposite를 통해
예외 처리 흐름을 제어합니다.
해당 Composite에는 기본적으로 다음의 Resolver들이 등록되며, 순서대로 예외 처리를 시도합니다.
등록 순서
- ExceptionHandlerExceptionResolver
- ResponseStatusExceptionResolver
- DefaultHandlerExceptionResolver
각 Resolver는 다음과 같은 상황에서 사용됩니다.
1. ExceptionHandlerExceptionResolver
정의
@ExceptionHandler 애노테이션이 붙은 메서드를 실행하여 예외를 처리하는 Resolver입니다.
Spring MVC에서 커스텀 예외 응답을 만들기 위해 가장 널리 쓰이는 방식입니다.
주요 동작
- 예외가 발생하면, 먼저 해당 컨트롤러 클래스 내에서 @ExceptionHandler가 붙은 메서드를 탐색합니다.
- 없다면 전역 예외 처리 클래스인 @ControllerAdvice에 정의된 핸들러에서 탐색합니다.
- 탐색 기준은 예외 타입(다형성 포함)입니다.
- 핸들러 메서드가 반환한 객체는 HttpMessageConverter를 통해 JSON/XML 응답으로 직렬화됩니다.
사용 예시
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(UserNotFoundException.class)
public ResponseEntity<?> handleUserNotFound(UserNotFoundException ex) {
return ResponseEntity.status(HttpStatus.NOT_FOUND)
.body(Map.of("error", "사용자를 찾을 수 없습니다"));
}
}
사용 시기
- 도메인 또는 비즈니스 예외에 대해 세밀하게 제어하고 싶을 때
- 공통적인 응답 포맷(JSON)을 유지하고 싶을 때
- 로깅, 알람 등 추가 동작이 필요한 경우
특징
- 커스터마이징 가능성 높음
- 다형성 매칭 지원 (ex: RuntimeException을 상위 타입으로 처리 가능)
- 컨트롤러 클래스마다 다르게 정의할 수도 있고, 전역으로도 적용 가능
2. ResponseStatusExceptionResolver
정의
예외 클래스에 붙은 @ResponseStatus 애노테이션 또는 코드에서 던진 ResponseStatusException을 해석하여 HTTP 응답을 생성하는 Resolver입니다.
주요 동작
- 예외 클래스에 @ResponseStatus(HttpStatus.XYZ)가 붙어 있으면 해당 상태 코드로 응답합니다.
- 또는 예외가 ResponseStatusException 타입이면, 해당 인스턴스에 포함된 HttpStatus와 메시지를 응답에 반영합니다.
- 응답 바디는 없거나 메시지만 간단히 포함됩니다.
사용 예시 1 – @ResponseStatus 이용
@ResponseStatus(HttpStatus.NOT_FOUND)
public class UserNotFoundException extends RuntimeException {
public UserNotFoundException(String message) {
super(message);
}
}
사용 예시 2 – ResponseStatusException 이용
@GetMapping("/users/{id}")
public User getUser(@PathVariable Long id) {
return userRepository.findById(id)
.orElseThrow(() -> new ResponseStatusException(
HttpStatus.NOT_FOUND, "사용자를 찾을 수 없습니다"
));
}
사용 시기
- 간단한 에러 응답이 필요한 경우
- 상태 코드만 명확히 지정하고 싶은 경우
- 별도의 예외 처리기 없이 빠르게 처리하고 싶을 때
특징
- @ExceptionHandler 없이도 예외에 상태 코드를 줄 수 있음
- 에러 응답 포맷 커스터마이징이 어려움 (별도 처리 없이 상태 코드 + 메시지 정도)
- ResponseStatusException은 컨트롤러, 서비스 어디서든 던질 수 있어 유연
3. DefaultHandlerExceptionResolver
정의
Spring이 자체적으로 정의한 표준 MVC 예외들을 HTTP 상태 코드로 매핑하는 기본 Resolver입니다.
주요 동작
- Spring MVC 내부에서 발생하는 예외들에 대해 적절한 HTTP 상태 코드를 설정합니다.
- 예: HttpRequestMethodNotSupportedException → 405 Method Not AllowedHttpMessageNotReadableException → 400 Bad Request
- MissingPathVariableException → 500 → 400 변환
사용 예시 (개발자가 명시하지 않아도 자동 작동)
@PostMapping("/users")
public void createUser(@RequestBody User user) {
// JSON 파싱 실패 → HttpMessageNotReadableException 발생
}
- 위와 같이 @RequestBody가 JSON 파싱에 실패할 경우 400 Bad Request가 자동 응답됩니다.
사용 시기
- 스프링 MVC가 자동으로 처리하는 상황
- 개발자가 명시적으로 개입하지 않아도 응답 상태를 바르게 설정해야 할 때
특징
- 직접 사용하지 않지만 기본 안전망 역할
- 응답 커스터마이징이 필요하면 @ExceptionHandler나 @ControllerAdvice로 오버라이드 가능
- 대부분의 애플리케이션에서 최후의 방어선 역할
전체 흐름 요약
[예외 발생]
↓
DispatcherServlet → HandlerExceptionResolverComposite
↓
① ExceptionHandlerExceptionResolver (가장 먼저 시도)
↓
② ResponseStatusExceptionResolver (상태 애노테이션 또는 ResponseStatusException)
↓
③ DefaultHandlerExceptionResolver (기본적인 Spring MVC 예외 처리)
결론 및 정리
Resolver | 설명 | 사용 대상 | 커스터마이징 |
ExceptionHandlerExceptionResolver | @ExceptionHandler를 탐색해 실행 | 커스텀 예외, 복잡한 응답 | 가장 강력 |
ResponseStatusExceptionResolver | @ResponseStatus 애노테이션 또는 ResponseStatusException 처리 | 단순 상태 응답 | 제한적 |
DefaultHandlerExceptionResolver | Spring 내부 예외 → HTTP 상태 코드 매핑 | 파라미터 누락, JSON 파싱 실패 등 | 거의 없음 |
이 세 가지 Resolver의 순서와 동작 원리를 이해하면,
Spring MVC에서 예외가 어떻게 감지되고 어떻게 응답으로 변환되는지를 정확히 파악할 수 있습니다.
실무에서는 대부분 ExceptionHandlerExceptionResolver를 활용한 전역 핸들링 방식을 기반으로,
필요에 따라 ResponseStatusException을 섞어 쓰는 방식이 주류입니다.
'Dev Framework > Spring' 카테고리의 다른 글
[Spring] ControllerAdvice + ExceptionHandler 전역 예외 처리 (0) | 2025.05.13 |
---|---|
[Spring][JPA] JPA QueryHint에 대해서 알아보자 (0) | 2025.05.01 |
[Spring][JPA] N+1 문제의 발생부터 해결까지 (0) | 2025.05.01 |
[Spring][JPA] 스프링 데이터 JPA Auditing 심화편 (1) | 2025.04.28 |
[Spring][JPA] 스프링 데이터 JPA Auditing 완전 정복 (0) | 2025.04.28 |