Spring web exception hierarchy
spring 6.0 이후 기준
스프링 web 예외는 크게 2가지의 최상위 예외 클래스를 구현함
core 모듈 예외
- 최상위 예외 클래스 : NestedRuntimeException
web 모듈 예외
- 최상위 예외 클래스 : ErrorResponseException
- 예외 스펙 : ErrorResponse
ErrorResponse
spring web에서 HTTP error 응답을 나타내는 인터페이스
status, headers, ProblemDetail 객체를 필드로 가짐
ProblemDetail 필드
- type, title, status, detail, instance, properties(추가 정보)
RFC 7807의 Problem Detail
RFC 7807은 Problem Detail을 정의하는 문서임(권장 사항 문서)
Problem Detail은 API 클라이언트에게 HTTP API에서 발생하는 문제 발생 상황을 표현하는 방법임(common error format)
JSON으로 직렬화할 때 application/problem+json
미디어 타입을 사용함
HTTP/1.1 403 Forbidden
Content-Type: application/problem+json
Content-Language: en
{
"type": "https://example.com/probs/out-of-credit",
"title": "You do not have enough credit.",
"detail": "Your current balance is 30, but that costs 50.",
"instance": "/account/12345/msgs/abc",
"balance": 30,
"accounts": ["/account/12345",
"/account/67890"]
}
type
- 문제 유형(problem type)을 식별하는 URI
- 문제에 대한 추가 정보를 제공하는 웹 페이지(자세한 설명, 해결 방법, 관련 문서 링크 제공)를 가리킬 수 있음
title
- 문제 유형에 대한 간략한 설명(human-readable)
detail
- 문제 발생에 대한 상세 설명(human-readable)
status
- 문제 발생에 대해 origin 서버가 발행한 HTTP 상태 코드
instance
- 문제의 특정 발생을 식별하는 URI
- 문제가 발생한 특정 리소스를 가리킴
- 위의 instance는 특정 계정의 특정 데이터 항목에 대한 문제를 식별함
balance, accounts : 추가 정보
ErrorResponseException
최상위 예외 클래스로 ErrorResponse를 구현함
spring web의 모든 예외는 ErrorResponseException을 상속받음
Exception resolution process
public class DispatcherServlet extends FrameworkServlet {
@Nullable
private List<HandlerExceptionResolver> handlerExceptionResolvers;
}
- handler 예외 발생
- DispatcherServlet -> handlerExceptionResolvers 순회하며 예외 처리 시도
- 해당 resolver가 null을 반환하면 다음 resolver에게 예외 처리 위임
- resolver가 예외 처리를 하면 해당 resolver가 반환한 ModelAndView를 반환 -> 다음 resolver는 실행되지 않음
- 모든 resolver가 예외 처리 실패하면 servlet container에게 예외를 던짐
Spring web exception resolver
HandlerExceptionResolver
handler 예외를 처리하는 최상위 인터페이스
예외 발생 시점
- handler mapping
- handler execution
public interface HandlerExceptionResolver {
ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex);
}
handler : 실행된 handler 또는 null(핸들러 매핑이 실패한 경우)
ModelAndView
- ModelAndView 반환 : 예외 처리 후 view를 렌더링
- null 반환 : 다음 resolver에게 예외 처리 위임
- 모든 resolver가 예외 처리를 실패하면 servlet container에게 예외를 던짐 -> 500 에러 발생
DefaultHandlerExceptionResolver
HandlerExceptionResolver의 기본 구현체
표준 spring mvc 예외들을 해결하고 그에 맞는 http status code로 변환함
지원하는 표준 spring mvc 예외들
- HttpRequestMethodNotSupportedException
- HttpMediaTypeNotSupportedException
- HttpMediaTypeNotAcceptableException
- MissingPathVariableException
- MissingServletRequestParameterException
- MissingServletRequestPartException
- ServletRequestBindingException
- ConversionNotSupportedException
- TypeMismatchException
- HttpMessageNotReadableException
- HttpMessageNotWritableException
- MethodArgumentNotValidException
- MethodValidationException
- HandlerMethodValidationException
- NoHandlerFoundException
- NoResourceFoundException
- AsyncRequestTimeoutException
SimpleMappingExceptionResolver
예외 클래스와 뷰 이름을 매핑하는 구현체
ExceptionHandlerExceptionResolver
@ExceptionHandler
- 특정 유형의 예외 처리를 하는 메서드를 정의하는 어노테이션
- @ControllerAdvice, @RestControllerAdvice, 일반 빈에 정의
- 일반 빈에 정의한 경우 해당 빈 내부에서 발생하는 예외만 처리 가능
- ModelAndView 또는 ResponseEntity 반환
@ControllerAdvice, @RestControllerAdvice
- 전역 예외 핸들러(애플리케이션의 모든 컨트롤러에서 발생하는 해당 유형의 예외 처리)
- @ExceptionHandler 메서드를 포함하는 클래스를 정의하는 어노테이션
- ExceptionHandlerExceptionResolver를 통해 DispatcherServlet에 등록되어 해당 빈 내부의 @ExceptionHandler 메서드가 예외 처리를 할 수 있음
- @ControllerAdvice : ModelAndView 반환
- @RestControllerAdvice : ResponseEntity 반환
ExceptionHandlerExceptionResolver
- @ExceptionHandler 메서드를 찾아 예외 처리를 수행함
ResponseEntityExceptionHandler
HandlerExceptionResolver를 구현하지 않고 ResponseEntity를 반환하는 예외 처리 추상 클래스
기본적으로 표준 spring mvc 예외 처리를 지원함
ResponseEntityExceptionHandler의 구현체는 오버라이딩을 통해 표준 spring mvc 예외 처리 및 커스텀 예외 처리를 확장할 수 있음
핵심 메서드
- createProblemDetail() : ProblemDetail 생성
- handleExceptionInternal() : ProblemDetail을 body로 담은 ResponseEntity 생성
BasicErrorController
spring boot에서 기본 제공하는 에러 처리 컨트롤러(/error 경로의 요청을 처리)
애플리케이션에서 처리되지 않은 예외가 발생했을 때 동작함