1. 정리
1. 예외 발생 시 전체 흐름 (필터 , 인터셉터 예외 재요청 방지 설정 시)
1) WAS(/error-ex, dispatchType=REQUEST) -> 필터 -> 서블릿 -> 인터셉터 -> 컨트롤러
2) WAS(여기까지 전파) <- 필터 <- 서블릿 <- 인터셉터 <- 컨트롤러(예외발생)
3) WAS 오류 페이지 확인
4. WAS(/error-page/500, dispatchType=ERROR) -> 필터(x) -> 서블릿 -> 인터셉터(x) -> 컨트롤러(/error-page/500) -> View2. 예외 처리 페이지 설정
- 스프링 제공 페이지 사용 (추천)
- 직접 설정 방식 사용
2. 서블릿 지원 예외
서블릿은 다음 2가지 방식으로 예외 처리를 지원한다.
1) Exception(예외)
2) response.sendError(HTTP 상태 코드, 오류 메시지)
3. 서블릿 예외 흐름
1. Exception(예외)
1) 흐름 : WAS(여기까지 전파) <- 필터 <- 서블릿 <- 인터셉터 <- 컨트롤러(예외발생)
2) RuntimeException와 같은 예외를 잡지 못할 경우 WAS까지 전파되며 서버 내부에서 처리할 수 없는 오류가 발생한 것으로 생각해서 500에러를 발생시킨다.2. response.sendError(HTTP 상태 코드, 오류 메시지) 사용
@GetMapping("/error-500") public void error500(HttpServletResponse response) throws IOException { response.sendError(500); }1) 흐름 : WAS(sendError 호출 기록 확인) <- 필터 <- 서블릿 <- 인터셉터 <- 컨트롤러
2) 응답을 내보내기 전에 서블릿 컨테이너는 sendError()을 호출 했는지를 확인하며, 호출 시 설정 된 오류 코드에 맞춘 에러 페이지를 보여준다.3. 예외처리 오류페이지 작동 흐름
1) WAS(여기까지 전파) <- 필터 <- 서블릿 <- 인터셉터 <- 컨트롤러(예외발생)
2) WAS/error-page/500다시 요청 -> 필터 -> 서블릿 -> 인터셉터 -> 컨트롤러(/error-page/
500) -> View
3) 해당 과정은 클라이언트에서는 모르며, 서버 내부에서 재요청이 일어나는 과정인거다.
4. 서블릿 오류 페이지
1. 오류 페이지 재요청 시
1) 오류 정보 추가
예외 , 예외 타입 , 오류 메세지 등의 오류 정보를 HttpServletRequest에 포함해서 전달한다.
2) 요청이 내부 요청(에러)인지, 정상 요청인지 확인 - dispatcherTypes
2-1) 필터와 인터셉터의 두번 호출을 막기 위해서 요청을 확인 할 수 있는 dispatcherTypes을 제공한다.
2-2) request.getDispatcherType()
2-3) 내부 요청 시, dispatchType=ERROR
2-4) 정상 요청 시, dispatcherType=REQUEST
2-5) 다른 추가 정보 (forward , INCLUDE ..)1. 스프링 자동 설정
1) custom 설정을 안할 경우 new ErrorPage()를 자동으로 등록하며 경로는 "/error"로 등록된다.
2) 에러 재요청에 대한 컨트롤러는 BasicErrorController를 통해 이루어진다.
3) BasicErrorController 뷰 선택 우선 순의3-1) 1 순위 : 뷰 템플릿 영역에서 /error/400 -> /error/4xx 순
3-2) 2 순위 : 정적 템플릿 영역에서 /error/400 -> /error/4xx 순
3-3) 3 순위 : resources/templates/error.html
3-4) 뷰 템플릿이 정적 리소스보다 우선순위가 높고, 404, 500처럼 구체적인 것이 5xx처럼 덜 구체적인 것 보다 우선순위가
높다. (5xx, 4xx 라고 하면 500대, 400대 오류를 처리해준다.)4) 컨트롤러에서 =오류 정보를 model에 포함할지 여부
4-1) server.error.include-exception=true : 예외 포함 여부
4-2) server.error.include-message=on_param : message 포함 여부
4-3) server.error.include-stacktrace=on_param : trace 포함 여부
4-4) server.error.include-binding-errors=on_param : errors 포함 여부
4-5) never(사용 안함) , always(항상 사용) , on_param(파라미터 있을 때 사용)
실무에서는 이것들을 노출하면 안된다!2. custom 설정
@Component public class WebServerCustomizer implements WebServerFactoryCustomizer<ConfigurableWebServerFactory> { @Override public void customize(ConfigurableWebServerFactory factory) { ErrorPage errorPage404 = new ErrorPage(HttpStatus.NOT_FOUND, "/errorpage/404"); ErrorPage errorPage500 = new ErrorPage(HttpStatus.INTERNAL_SERVER_ERROR, "/error-page/500"); ErrorPage errorPageEx = new ErrorPage(RuntimeException.class, "/errorpage/500"); factory.addErrorPages(errorPage404, errorPage500, errorPageEx); } }1) 스프링 애플리케이션이 시작될 때 컴포넌트 스캔을 통해 빈으로 등록되고, 이를 통해 에러 페이지 설정을 스프링 부트의 내장 WAS (예: 톰캣, 젯티 등)에서 처리하도록 구성합니다.
2) RuntimeException.class 등록에 경우 해당 예외에 대한 자식 예외들도 /errorpage/500 페이지로 처리한다.3. 추가 설정
application.properties
server.error.whitelabel.enabled=true : 오류 못 찾을 시 스프링 화이트 페이지 사용