spring boot는 다음과 같은 기본적인 에러페이지를 제공하고 있습니다.
기본적으로 Exception이 발생하고 별다른 처리를 하지 않으면 기본으로 등록된 다음과같은 error.html 또는 error.jsp 파일에 맵핑되어 에러 페이지가 보여지게 됩니다.
RESTful API 요청을 만들어 보냈다면 스프링은 다음 그림과 같은 화이트라벨 에러 페이지를 보여줍니다.
또한, error.html을 수정하여 원하는 정보를 담은 에러페이지를 만들 수도 있습니다.

스프링에서 핸들링되지 않은 예외들은 보통 500에러로 응답하게 됩니다.
그러나 @ResponseStatus 어노테이션을 통해 사용자가 원하는 에러(상태코드와 메세지)로 만들수 있습니다.
그리고 이 에러는 다른곳에서 처리되지 않는 이상 해당 상태코드와 메세지로 응답합니다.
@ResponseStatus(value=HttpStatus.NOT_FOUND, reason="No such Order") // 404
public class OrderNotFoundException extends RuntimeException {
// ...
}
@ExceptionHandler 어노테이션을 통해 해당 컨트롤러에서 발생하는 에러를 공통으로 처리할 수 있습니다.
하지만 범위가 해당 컨트롤러만 해당됩니다.
따라서 컨트롤러 마다 @ExceptionHandler를 작성해야 하기에 코드의 중복이 발생합니다.
@Controller
public class ExceptionHandlingController {
// @RequestHandler methods
...
// Exception handling methods
@ExceptionHandler({SQLException.class,DataAccessException.class})
public String databaseError() {
return "databaseError";
}
@ExceptionHandler(Exception.class)
public ModelAndView handleError(HttpServletRequest req, Exception ex) {
logger.error("Request: " + req.getRequestURL() + " raised " + ex);
ModelAndView mav = new ModelAndView();
return mav;
}
}
Controller Advice는 ExceptionHandler를 전체 컨트롤러에 적용하는 것입니다. 마치 인터셉터 처럼 동작한다고 이해하면 될 것입니다.
또한, @ControllerAdvice와 @RestControllerAdvice는 Bean으로 등록되어 관리됩니다.
여러 ControllerAdvice가 있을 때 @Order어노테이션으로 순서를 지정하지 않는다면 Spring은 ControllerAdvice를 임의의 순서로 호출합니다. 즉, 사용자가 예상하지 못한 예외 처리가 발생할 수 있습니다.
basePackages
만약 여러 ControllerAdvice를 세분화하고 싶다면 basePackages 속성을 이용할 수 있습니다.
작성된 패키지와 하위 패키지에서 발생하는 예외는 해당 ControllerAdvice에서 처리하도록 지정할 수 있습니다.
assignableTypes
assignableTypes 속성을 이용하면 클래스 단위로도 ControllerAdvice를 적용할 수 있습니다.
@ControllerAdvice(basePackages = {"com.example.demo"})
// @ControllerAdvice(assignableTypes ={SimpleController.class})
class GlobalDefaultExceptionHandler {
@ResponseStatus(HttpStatus.CONFLICT) // 409
@ExceptionHandler(DataIntegrityViolationException.class)
public void handleConflict() {
// Nothing to do
}
}
HandlerExceptionResolver 는 MVC 시스템에서 발생하는 모든 예외를 차단
하고 처리하는 데 사용됩니다.
public interface HandlerExceptionResolver {
ModelAndView resolveException(HttpServletRequest request,
HttpServletResponse response, Object handler, Exception ex);
}
HandlerExceptionResolver는 내부에 3가지 ExceptionResolver들을 사용하고, 우선순위는 다음과 같습니다.
1번부터 예외처리가 체인화 되어 진행됩니다.
내부적으로 스프링은 이 작업을 수행할 전용 빈(HandlerExceptionResolverComposite)을 만듭니다.
@ExceptionHandler를 이용하여 예외처리를 진행합니다.
ExceptionResolver 중 우선순위가 가장높고 위에서 살펴본 방식이 이 방식입니다.
@ResponseStatus 를 이용한 예외처리를 진행합니다.
표준 스프링 예외를 변환하여 HTTP 상태 코드로 변환합니다.(Spring MVC 내부)
/error.html 에 해당합니다.
결론적으로 위와 같은 우선순위로 에러처리가 동작하게 됩니다.
사용자는 이 우선순위에 따라 예외 처리를 만들어서 사용할 수 있습니다.
실무에서는 @ExceptionHandler 와 @ControllerAdvice를 이용한 방식을 가장 많이 사용한다고 합니다.
https://spring.io/blog/2013/11/01/exception-handling-in-spring-mvc
https://tecoble.techcourse.co.kr/post/2023-05-03-ExceptionHandler-ControllerAdvice/
https://parkmuhyeun.github.io/woowacourse/2023-04-19-Exception-Handler/