Spring

Spring - Exception

코드파고 2022. 10. 9. 18:36

Spring은 서블릿 위에서 작동한다. Servlet 단계에서의 예외부터 이해해보자!

 

서블릿의 예외 처리 방법 두 종류

1️⃣ Exception
2️⃣ response.sendError(HTTP Status Code, Error Message)

 

Exception

자바가 직접 실행

main() 메서드를 넘어서 예외가 던져지면, 예외 정보를 남기고 해당 쓰레드는 종료

웹 어플리케이션

사용자 요청별로 쓰레드 할당되며 서블릿 컨테이너 안에서 실행된다.

try-catch로 예외를 잡아서 처리하면 문제가 없지만 서블릿 밖으로 나가게 되면 500으로 처리된다

 

response.sendError(HTTP 상태 코드, 오류 메시지)

서블릿 컨테이너에게 오류 메시지를 직접 전달 가능

WAS👈필터 👈 서블릿 👈인터셉터 👈 컨트롤러(예외발생)

다시 HTTP 요청을 하듯 타고들어간다

WAS👉필터 👉서블릿 👉인터셉터 👉컨트롤러(에러 페이지)👉뷰

여기에 오류 정보도 추가적으로 전달 가능

이 때, 서블릿은 DispatcherType을 통해 내부 요청인지를 판단하여 필터,인터셉터의 중복 호출을 방지한다

[DispatcherType의 종류]
REQUEST(클라이언트 요청),
ERROR(오류 요청),
FORWARD(다른 서블릿이나 JSP 호출),
INCLUDE(다른 서블릿이나  JSP 결과 포함),
ASYNC(서블릿 비동기 호출)

스프링이 제공하는 ErrorPage를 직접 등록해 주자

public class WebServerCustomizer implements WebServerFactoryCustomizer<ConfigurableWebServerFactory> {
    @Override
    public void customize(ConfigurableWebServerFactory factory) {
        ErrorPage errorPage404 = new ErrorPage(HttpStatus.NOT_FOUND, "/error-page/404"); // 스프링 부트가 제공하는 에러페이지
        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);
    }
}

 

 

스프링 부트의 오류 페이지 지원

WebServerCustomizer 사용해서 등록하고.. 이런 과정을 자동화해준다

ErrorPage를 자동 등록하여 /error 경로로 기본 오류 페이지를 설정한다

이미 컨트롤러가 생성되어 있기 때문에 템플릿을 사용하면 된다.

 

뷰 선택 우선순위

뷰 템플릿 👉 정적 리소스 👉 적용 대상이 없을 때(/error)

 

BasicErrorController

BasicErrorController가 제공하는 기본 정보를 model에 담아 View에 전달한다.

server.error.include-exception=true
server.error.include-message=always
server.error.include-stacktrace=always
server.error.include-binding-errors=always

.다양한 예외 정보 출력하기💥 - 그러나 보안상 취약점이 생길 수 있으니 막아두는 편이 좋다.

서비스에 대한 정보들이 출력될 수 있으므로 되도록 서버에 로그로 남겨서 로그로 확인하도록 하자.

?message=&errors=&trace=와 같이 파라미터를 추가해서 정보를 조회할 수도 있다.

 

에러 공통 처리 컨트롤러의 기능을 바꾸고 싶다면

1️⃣ErrorController 인터페이스를 상속받아 구현

2️⃣BasicErrorController를 상속받아서 기능을 추가하자