[Spring MVC] 스프링 HTTP 에러 처리

기본 예외처리

 

 자바의 경우, 예외가 발생했을 때 그 예외를 별도로 처리해주지 않는다면 해당 메소드를 호출한 상위 스택에 예외를 던지고, main에 이르러서까지 예외가 처리되지 않는다면 정보를 출력하면서 main 쓰레드가 종료된다.

비슷하게 웹 애플리케이션의 경우 사용자 요청별로 별도의 쓰레드가 할당되어 서블릿 컨테이너 안에서 실행되는데, 애플리케이션에서 발생한 에러를 서블릿 안에서 처리하지 못하고 바깥으로 전달되면 톰캣과 같은 WAS(Web Application Server)까지 예외가 전달된다.

그러면 WAS는 서버에서 처리할 수 없는 오류가 발생한 것으로 생각해서 HTTP 500 error를 발생시킨다.

 

 

 

커스텀 서블릿 오류 화면 설정

 

application.properties

 설정 이전에 에러시 Whitelabel 화면을 띄워주지 않도록 에러페이지 동작 로직을 막자.

 

아래와 같이 WebServerFactoryCustomizer<ConfigurableWebServerFactory>의 customize를 구현하고 컴포넌트로 등록해주면 스프링이 WAS에서 오류가 발생했을때 등록해둔 uri로 이동시킨다.

 

아래의 경우 error-page/400, error-page/500을 받는 컨트롤러를 생성하여 뷰를 리턴해주면 예외가 발생했을 때 개발자가 지정한 화면으로 이동하도록 할 수 있다.

 

 

@Component
public class WebServerCustomizer implements WebServerFactoryCustomizer<ConfigurableWebServerFactory> {

    //오류 페이지 커스텀
    @Override
    public void customize(ConfigurableWebServerFactory factory) {

        //404 에러가 발생하면 error-page/400을 호출
        ErrorPage errorPage404 = new ErrorPage(HttpStatus.NOT_FOUND, "/error-page/400");
        ErrorPage errorPage500 = new ErrorPage(HttpStatus.INTERNAL_SERVER_ERROR, "/error-page/500");
        ErrorPage errorPageEx = new ErrorPage(RuntimeException.class , "/error-page/500");

        //에러 페이지 등록하기
        factory.addErrorPages(errorPage404, errorPage500, errorPageEx);
    }
}

 

 컨트롤러에서 예외가 발생했을때 서블릿 안에서 오류가 처리되지 못했을 때, 서블릿은 오류 페이지를 찾고, WAS는 해당 예외를 처리하는 오류 페이지가 존재하는지 확인한다. WAS가 이 로직을 처리하기 때문에 웹 서버는 해당 로직을 알 수 없다.

WAS가 오류 페이지를 찾았다면, 다시 디스패처 서블릿쪽으로 보내서 컨트롤러가 페이지를 뷰에 띄워주게 된다. 즉, 필터부터 컨트롤러까지의 요청 흐름이 한번 더 반복된다. 또한 WAS는 오류 정보를 request의 attrubute에 추가해서 넘겨주기 때문에, 오류 페이지에서 이 정보를 사용할 수도 있다.

 

 

 

 

스프링 오류페이지 처리

 

 지금까지는 커스텀 페이지를 만들고 예외 종류에 따라서 ErrorPage를 추가하고, 에러처리용 컨트롤러도 만들어야 했다. 하지만 스프링 부트를 이용하면 이런 과정을 모두 기본적으로 제공해준다.

 

- 스프링은 /error이하의 경로로 기본 오류 페이지를 설정한다.

- 또한 예외처리용 컨트롤러도 자동으로 제공한다.

스프링이 기본적으로 제공하는 BasicErrorController

따라서 개발자는 스프링이 제공하는 컨트롤러(BasicErrorController)를 이용해서 오류 페이지를 표시할 뷰 파일만 등록해주면 된다.

 

BasicErrorController는 /resources/templates/error 아래에 존재하는 html문서들을 에러가 발생할 경우 자동으로 등록한다. html의 이름에 따라서 404 error가 발생하면 404.html, 403 error가 발생했는데 403.html이 존재하지 않는 경우 4xx.html 이런 우선순위(구체적->추상적)로 작동한다.