Spring - BasicErrorController

이재용·2025년 1월 1일
0
  1. 예외가 WAS(=서블릿)까지 전달되거나 response.sendError()가 호출되면,
  2. WAS는 오류 페이지 정보를 확인한다. (ErrorMvcAutoConfiguration 클래스가 오류 페이지를 자동으로 등록하는 역할을 한다.)오류정보 -> new ErrorPage(RuntimeException.class, "/error-page/500") 스프링 부트는 ErrorPage를 자동으로 등록한다.
  3. 이때 /error라는 경로로 기본 오류 페이지를 설정한다.
  4. 서블릿 밖으로 예외가 발생하거나, response.sendError(...)가 호출되면 모든 오류는 /error를 호출하게 된다.
  5. 스프링 부트가 자동 등록한 BasicErrorController는 이 경로를 기본으로 받는다.
    예시
    RuntimeException 예외가 WAS까지 전달되면, WAS는 오류 페이지 정보를 확인한다. 확인해보니 RuntimeException 의 오류 페이지로 /error-page/500 이 지정되어 있다. WAS는 오류 페이지를 출력하기 위해 /error-page/500 를 다시 요청한다.
    BasicErrorController라는 스프링 컨트롤러를 자동으로 등록한다. ErrorPage에서 등록한 /error를 매핑해서 처리하는 컨트롤러다

BasicErrorController

@Controller 
@RequestMapping("${server.error.path:${error.path:/error}}") 
public class BasicErrorController extends AbstractErrorController { 
	@RequestMapping(produces = MediaType.TEXT_HTML_VALUE) 
	public ModelAndView errorHtml(HttpServletRequest request, HttpServletResponse response) {} 
	@RequestMapping 
	public ResponseEntity> error(HttpServletRequest request) {}
}

${server.error.path:${error.path:/error}} 구조

이 표현식은 Spring의 Property Placeholder Syntax입니다.

  • ${...}: 프로퍼티 값을 참조합니다. (프로퍼티=application.properties)
  • :: 기본값(default)을 정의할 때 사용합니다.

단계별 해석

  1. ${server.error.path}
    • 먼저 server.error.path라는 프로퍼티를 찾습니다.
    • 만약 해당 프로퍼티가 정의되어 있다면, 그 값을 사용합니다.
  2. ${error.path}
    • server.error.path가 정의되지 않은 경우, 대신 error.path를 찾습니다.
  3. /error (기본값)
    • 위 두 프로퍼티 중 어느 것도 정의되지 않았다면, 기본값으로 /error를 사용합니다.

실제 사용 목적

Spring Boot의 예외 처리 엔드포인트(error path)를 정의합니다.

  • Spring Boot에서 기본적으로 에러 발생 시 "/error" URL로 매핑된 컨트롤러를 통해 에러를 처리합니다.
  • 사용자가 application.properties 또는 application.yml에서 server.error.patherror.path 값을 설정하면, 이 기본 경로를 커스터마이징할 수 있습니다.

코드가 의미하는 바

@RequestMapping("${server.error.path:${error.path:/error}}")

  • server.error.path 프로퍼티가 정의되어 있다면 그 값을 사용합니다.
  • 그렇지 않으면 error.path 프로퍼티를 찾습니다.
  • 둘 다 없으면 기본값으로 "/error"를 사용하여 요청을 처리합니다.

/error 동일한 경로를 처리하는 errorHtml() , error() 두 메서드를 확인할 수 있다.

  • errorHtml() : produces = MediaType.TEXT_HTML_VALUE : 클라이언트 요청의 Accept 해더 값이 text/html인 경우에는 errorHtml() 을 호출해서 view를 제공한다.
  • error() : 그외 경우에 호출되고 ResponseEntity 로 HTTP Body에 JSON 데이터를 반환한다.

Spring MVC

오류가 발생했을 때 오류 페이지로 /error를 기본 요청한다. 스프링 부트가 자동 등록한 BasicErrorController는 이 경로를 기본으로 받는다.

@Controller 
public class ServletExController { 
	@GetMapping("/error-ex") 
	public void errorEx() { 
		throw new RuntimeException("예외 발생!"); 
	} 
	@GetMapping("/error-404") 
	public void error404(HttpServletResponse response) throws IOException { 
		response.sendError(404, "404 오류!"); 
	} 
	@GetMapping("/error-500") 
	public void error500(HttpServletResponse response) throws IOException { 
	response.sendError(500); 
	}
}

resources/templates/error/4xx.html
resources/templates/error/404.html
resources/templates/error/500.html
결과
http://localhost:8080/error-404 -> 404.html
http://localhost:8080/error-400 -> 4xx.html (400 오류 페이지가 없지만 4xx가 있음)
http://localhost:8080/error-500 -> 500.html
http://localhost:8080/error-ex -> 500.html (예외는 500으로 처리)

스프링 부트가 제공하는 BasicErrorController 는 HTML 페이지를 제공하는 경우에는 매우 편리하다. 4xx, 5xx 등등 모두 잘 처리해준다. 그런데 API 오류 처리는 다른 차원의 이야기이다. API 마다, 각각의 컨트롤러나 예외마 다 서로 다른 응답 결과를 출력해야 할 수도 있다. 예를 들어서 회원과 관련된 API에서 예외가 발생할 때 응답과, 상품과 관련된 API에서 발생하는 예외에 따라 그 결과가 달라질 수 있다. 결과적으로 매우 세밀하고 복잡하다. 따라서 이 방법 은 HTML 화면을 처리할 때 사용하고, API 오류 처리는 뒤에서 설명할 @ExceptionHandler 를 사용하자.

0개의 댓글