JiwonDev

Spring ์˜ˆ์™ธ์ฒ˜๋ฆฌ - ์˜ค๋ฅ˜ํŽ˜์ด์ง€(404,500)

by JiwonDev

์„œ๋ธ”๋ฆฟ ์ปจํ…Œ์ด๋„ˆ๋Š” ์–ด๋–ค ๋ฐฉ๋ฒ•์œผ๋กœ ์˜ˆ์™ธ๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š”์ง€ ๋ฐฐ์›Œ๋ณด๊ณ  Spring์—์„œ์˜ ์˜ˆ์™ธ์ฒ˜๋ฆฌ ๋ฐฉ๋ฒ•์„ ๋ฐฐ์›Œ๋ณด์ž.

 Vaildator๋Š” ํƒ€์ž„๋ฆฌํ”„์—์„œ๋งŒ ์˜ˆ์™ธ์ฒ˜๋ฆฌ๊ฐ€ ๊ฐ€๋Šฅํ–ˆ์—ˆ๋‹ค. ์Šคํ”„๋ง์—์„œ์˜ ์˜ˆ์™ธ์ฒ˜๋ฆฌ ๋ฐฉ๋ฒ•์„ ์•Œ์•„๋ณด์ž.

 

 

# ์„œ๋ธ”๋ฆฟ ์˜ˆ์™ธ ์ฒ˜๋ฆฌ

์„œ๋ธ”๋ฆฟ์€ WAS์—์„œ ๋™์ž‘ํ•˜๋Š” ์ž๋ฐ” ๊ฐ์ฒด์ด๋‹ค. ์„œ๋ธ”๋ฆฟ์€ ๋‹ค์Œ 2๊ฐ€์ง€ ๋ฐฉ๋ฒ•์œผ๋กœ ์˜ˆ์™ธ๋ฅผ ์ฒ˜๋ฆฌํ•œ๋‹ค.

  • Java Exception (์˜ˆ์™ธ)
  • response.sendError (HTTP ์ƒํƒœ์ฝ”๋“œ, ์˜ค๋ฅ˜ ๋ฉ”์‹œ์ง€ ์ „์†ก)

 

@ Java Exception

์ž๋ฐ”์—์„œ ์˜ˆ์™ธ์ฒ˜๋ฆฌ๋ฅผ ํ•˜์ง€์•Š์œผ๋ฉด ์•ฑ์˜ ์ง„์ž…์ ์ธ Main๊นŒ์ง€ ์ „๋‹ฌ๋˜๊ณ , Main์—์„œ ์ฒ˜๋ฆฌ๋ฅผ ํ•˜์ง€ ์•Š์œผ๋ฉด JVM์œผ๋กœ ๋„˜๊ฒจ์ง€๋ฉฐ ์˜ค๋ฅ˜ ๋ฉ”์‹œ์ง€๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ํ•ด๋‹น ์“ฐ๋ ˆ๋“œ๋ฅผ ์ข…๋ฃŒํ•˜๊ฒŒ ๋œ๋‹ค.

 

๊ทธ๋ ‡๋‹ค๋ฉด ํ†ฐ์บฃ ๊ฐ™์€ WAS์—์„œ ์‹คํ–‰๋˜๋Š” ์„œ๋ธ”๋ฆฟ์€ ์–ด๋–ป๊ฒŒ ์˜ˆ์™ธ๊ฐ€ ์ฒ˜๋ฆฌ๋ ๊นŒ?

@Slf4j
@Controller
public class ServletExController {
    @GetMapping("/error-ex")
    public void errorEx() { // ๊ถ๊ธˆํ•˜๋‹ˆ ์ง์ ‘ ์˜ˆ์™ธ๋ฅผ ๋งŒ๋“ค์–ด์„œ ๋˜์ ธ๋ณด์ž.
        throw new RuntimeException("์˜ˆ์™ธ ๋ฐœ์ƒ!");
    }
}

๊ทธ๋ƒฅ ์ด๋ ‡๊ฒŒ HTTP 500 ์ฝ”๋“œ๊ฐ€ ์ „์†ก๋˜๋ฒ„๋ฆฐ๋‹ค. (*์Šคํ”„๋ง๋ถ€ํŠธ๋‚˜ WAS์—์„œ ๊ธฐ๋ณธ ์˜ค๋ฅ˜ํŽ˜์ด์ง€๋ฅผ ์ œ๊ณตํ•ด์ฃผ๊ธฐ๋„ ํ•œ๋‹ค.)

 

์ฆ‰ ์„œ๋ฒ„ ๋‚ด๋ถ€์—์„œ ์˜ˆ์™ธ๋ฅผ ์ฒ˜๋ฆฌํ•˜์ง€ ๋ชปํ•œ๋‹ค๋ฉด WAS๋Š” ๋ฐ˜ํ™˜ํ•  Response๊ฐ€ ์—†๋‹ค. 

  • HTTP 500 ์ฝ”๋“œ์™€ ํ•จ๊ป˜ ๊ธฐ๋ณธ ์˜ค๋ฅ˜ํŽ˜์ด์ง€๋ฅผ ๋ฐ˜ํ™˜ํ•˜๊ฒŒ ๋œ๋‹ค. 
  • ์˜ˆ์™ธ๊ฐ€ ํ„ฐ์ง„๊ฑด ์•„๋‹ˆ์ง€๋งŒ, ํ•ด๋‹น URL์„ ์ฒ˜๋ฆฌํ•  ์ปจํŠธ๋กค๋Ÿฌ๊ฐ€ ์—†๋‹ค๋ฉด HTTP 404 ์ฝ”๋“œ๋ฅผ ์ „์†กํ•œ๋‹ค.

 

 

@ response.sendError (HTTP ์ƒํƒœ์ฝ”๋“œ, ์˜ค๋ฅ˜ ๋ฉ”์‹œ์ง€)

์˜ˆ์™ธ์ฒ˜๋ฆฌ๋ฅผ ํ•˜์ง€์•Š๊ณ  WAS๊นŒ์ง€ ๋˜์ ธ๋ฒ„๋ฆฌ๋Š” ๊ฑด ์ข‹์€ ๋ฐฉ๋ฒ•์ด ์•„๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ์„œ๋ธ”๋ฆฟ response ๊ฐ์ฒด์—๋Š” Exception ๋Œ€์‹  ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” sendError() ๋ผ๋Š” ๋ฉ”์„œ๋“œ๊ฐ€ ์กด์žฌํ•œ๋‹ค. 

 โžก response.senError()๊ฐ€ ํ˜ธ์ถœ๋˜๋ฉด, WAS๋Š” ํด๋ผ์ด์–ธํŠธ ์š”์ฒญ์— ํ•ด๋‹น ์˜ค๋ฅ˜์ฝ”๋“œ์™€ ๋ฉ”์‹œ์ง€๋ฅผ ์ „์†กํ•œ๋‹ค.

@Slf4j
@Controller
public class ServletExController {

    @GetMapping("/error-404")
    public void error404(HttpServletResponse response) throws IOException {
        response.sendError(404, "404 ์˜ค๋ฅ˜!"); // ์˜ค๋ฅ˜์ฝ”๋“œ์™€ ๋ฉ”์‹œ์ง€๋ฅผ ๋‚ด๊ฐ€ ์ง€์ •ํ•  ์ˆ˜ ์žˆ๋‹ค.
    }
}

 


# ์„œ๋ธ”๋ฆฟ ์˜ค๋ฅ˜ ํŽ˜์ด์ง€ ๋งŒ๋“ค๊ธฐ

์„œ๋ธ”๋ฆฟ ์ปจํ…Œ์ด๋„ˆ๋‚˜ ์Šคํ”„๋ง๋ถ€ํŠธ๊ฐ€ ์ œ๊ณตํ•˜๋Š” ์˜ค๋ฅ˜ํ™”๋ฉด์„ ๊ทธ๋Œ€๋กœ ๊ณ ๊ฐ์—๊ฒŒ ์ „์†กํ•˜๋ฉด ์•ˆ๋œ๋‹ค. ์–ด๋–ค ์ž๋ฐ” ์ฝ”๋“œ์—์„œ ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ–ˆ๋Š”์ง€๋ฅผ ๊ณ ๊ฐ์—๊ฒŒ ๊ตณ์ด ๋ณด์—ฌ์ค„ ํ•„์š”๋Š” ์—†๋‹ค. 

Tomcat์—์„œ ์ž๋™์œผ๋กœ ์ƒ์„ฑํ•˜๋Š” ์˜ค๋ฅ˜ํŽ˜์ด์ง€. ์ด๋Ÿฐ ํŽ˜์ด์ง€๋ฅผ ๊ณ ๊ฐ์—๊ฒŒ ๋ณด๋‚ด์ค„ ํ•„์š”๋Š” ์—†๋‹ค.

 

๊ทธ๋ž˜์„œ ์„œ๋ธ”๋ฆฟ์—์„œ๋Š” ์•„๋ž˜์™€ ๊ฐ™์€ ๋ฐฉ๋ฒ•์œผ๋กœ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ–ˆ์„ ๋•Œ ๋‹ค์‹œ ํ˜ธ์ถœํ•  URL์„ ์ง€์ •ํ•  ์ˆ˜ ์žˆ๋‹ค.

 โžก ์˜ˆ๋ฅผ ๋“ค์–ด WAS์— HTTP 404 ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด https://myhome/error-page/404 ๋กœ ๋‹ค์‹œ ์š”์ฒญํ•œ๋‹ค.
 โžก ๋งˆ์น˜ ๋ฆฌ๋‹ค์ด๋ ‰์…˜์ฒ˜๋Ÿผ ๋™์ž‘ํ•˜์ง€๋งŒ, HTTP ์š”์ฒญ์„ ๋‹ค์‹œ ๋ณด๋‚ด๋Š”๊ฑด์•„๋‹ˆ๋‹ค. ํด๋ผ์ด์–ธํŠธ๋Š” ์ด ์‚ฌ์‹ค์„ ๋ชจ๋ฅธ๋‹ค.

@Component
public class WebServerCustomizer
                    implements WebServerFactoryCustomizer<ConfigurableWebServerFactory> {
                    
    @Override
    public void customize(ConfigurableWebServerFactory factory) {
        // 200, 300 ์ด๋ ‡๊ฒŒ ์ˆซ์ž๋ฅผ ์ง์ ‘ ์จ๋„ ๋˜์ง€๋งŒ ์ƒ์ˆ˜ ๊ฐ’์„ ์‚ฌ์šฉํ•˜๋Š”๊ฒŒ ๋ชจ๋“  ๋ฐฉ๋ฉด์—์„œ ์ข‹๋‹ค.
        ErrorPage errorPage404 = new ErrorPage(HttpStatus.NOT_FOUND, "/error-page/404");
        ErrorPage errorPage500 = new ErrorPage(HttpStatus.INTERNAL_SERVER_ERROR, "/error-page/500");

        // ๊ทธ ์™ธ RuntimeException์— ๋ฐ”์ธ๋”ฉ ๋˜๋Š” ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ–ˆ์„ ๋•Œ ์‚ฌ์šฉํ•  ํŽ˜์ด์ง€
        ErrorPage errorPageEx = new ErrorPage(RuntimeException.class, "/error-page/500");

        factory.addErrorPages(errorPage404, errorPage500, errorPageEx);
    }
}

์ด ๊ณผ์ •์—์„œ ํ•„ํ„ฐ์™€ ์ธํ„ฐ์…‰ํ„ฐ๋Š” ์˜ต์…˜์œผ๋กœ ์„ค์ •์ด ๊ฐ€๋Šฅํ•œ๋ฐ, ์ด๋Š” ์กฐ๊ธˆ์žˆ๋‹ค๊ฐ€ ์•Œ์•„๋ณด์ž

 

์ฆ‰ ์œ„์—์„œ ๋งŒ๋“  ์˜ค๋ฅ˜ URL ๊ฒฝ๋กœ๋“ค์„ ์ปจํŠธ๋กค๋Ÿฌ์—์„œ ๊ตฌํ˜„ํ•ด์ฃผ๋ฉด ๋œ๋‹ค.

@Slf4j
@Controller
public class ErrorPageController {

  // ์ฐธ๊ณ ๋กœ ์•„๋ž˜ ๊ฐ’๋“ค์€ RequestDispatcher ์— ์ƒ์ˆ˜๋กœ ์ •์˜๋˜์–ด ์žˆ์Œ
  public static final String ERROR_EXCEPTION = "javax.servlet.error.exception";
  public static final String ERROR_EXCEPTION_TYPE = "javax.servlet.error.exception_type";
  public static final String ERROR_MESSAGE = "javax.servlet.error.message";
  public static final String ERROR_REQUEST_URI = "javax.servlet.error.request_uri";
  public static final String ERROR_SERVLET_NAME = "javax.servlet.error.servlet_name";
  public static final String ERROR_STATUS_CODE = "javax.servlet.error.status_code";

  @RequestMapping("/error-page/404")
  public String errorPage404(HttpServletRequest request, HttpServletResponse response) {
    log.info("errorPage 404");
    this.printErrorInfo(request);
    return "error-page/404"; // 404.html ํŽ˜์ด์ง€ ๊ฒฝ๋กœ
  }

  @RequestMapping("/error-page/500")
  public String errorPage500(HttpServletRequest request, HttpServletResponse response) {
    log.info("errorPage 500");
    this.printErrorInfo(request);
    return "error-page/500"; // 500.html ํŽ˜์ด์ง€ ๊ฒฝ๋กœ
  }

  private void printErrorInfo(HttpServletRequest request) {
    //RequestDispatcher ์— ์žˆ๋Š” ์ƒ์ˆ˜๊ฐ’์œผ๋กœ ์ด๋ ‡๊ฒŒ request์—์„œ ์—๋Ÿฌ์ •๋ณด๋ฅผ ๋ฐ›์•„์˜ฌ ์ˆ˜ ์žˆ๋‹ค.
    log.info("ERROR_EXCEPTION: {}", request.getAttribute(ERROR_EXCEPTION));
    log.info("ERROR_EXCEPTION_TYPE: {}", request.getAttribute(ERROR_EXCEPTION_TYPE));
    log.info("ERROR_MESSAGE: {}", request.getAttribute(ERROR_MESSAGE));
    log.info("ERROR_REQUEST_URI: {}", request.getAttribute(ERROR_REQUEST_URI));
    log.info("ERROR_SERVLET_NAME: {}", request.getAttribute(ERROR_SERVLET_NAME));
    log.info("ERROR_STATUS_CODE: {}", request.getAttribute(ERROR_STATUS_CODE));
    log.info("dispatchType={}", request.getDispatcherType());
  }
}

 


# ์˜ค๋ฅ˜๊ฐ€ ์ƒํ–ˆ์„ ๋•Œ ํ•„ํ„ฐ, ์ธํ„ฐ์…‰ํ„ฐ

1๋ฒˆ๊ณผ 2๋ฒˆ์€ DispatcherType์ด ๋‹ค๋ฅด๋‹ค (REQUEST, ERROR)

์ด์ฒ˜๋Ÿผ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด, WAS์—์„œ๋Š” ๋งˆ์น˜ ๋ฆฌ๋‹ค์ด๋ ‰์…˜๋œ ๊ฒƒ์ฒ˜๋Ÿผ ์˜ค๋ฅ˜ํŽ˜์ด์ง€์šฉ ์ปจํŠธ๋กค๋Ÿฌ๋ฅผ ๋™์ž‘ํ•œ๋‹ค. ํ•˜์ง€๋งŒ ์ด ๊ฒฝ์šฐ์—๋„ ํ•„ํ„ฐ์™€ ์ธํ„ฐ์…‰ํ„ฐ๋„ ํ•œ๋ฒˆ ๋” ์‹คํ–‰๋˜๋Š”๋ฐ ์ด๋Š” ์˜๋ฏธ์—†๋Š” ๋ถˆํ•„์š”ํ•œ ์ž‘์—…์ด๋‹ค.

 

๊ทธ๋ž˜์„œ ์„œ๋ธ”๋ฆฟ์€ ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ–ˆ์„ ๋•Œ ํ•„ํ„ฐ์—์„œ ๋™์ž‘์„ ๊ฒฐ์ •ํ•  ์ˆ˜ ์žˆ๊ฒŒ DispatcherTypes๋ผ๋Š” Enum๊ฐ’์„ ์ œ๊ณตํ•œ๋‹ค.

 

 

@ํ•„ํ„ฐ์˜ DispatcherType

ํ•„ํ„ฐ ๊ฐ์ฒด์—๋Š” setDispatcherTypes( dispatcherType ) ๋ผ๋Š” ๋ฉ”์„œ๋“œ๊ฐ€ ์žˆ๋‹ค.

ํ•ด๋‹น ์š”์ฒญ ํƒ€์ž…์ผ ๋•Œ๋งŒ ํ•„ํ„ฐ๊ฐ€ ์‹คํ–‰๋˜๋„๋ก ์„ค์ •ํ•˜๋Š” ๊ธฐ๋Šฅ์œผ๋กœ, ๊ธฐ๋ณธ๊ฐ’์€ REQUEST๋งŒ ๋“ฑ๋ก๋˜์–ด์žˆ๋‹ค.

โžก ๊ทธ๋ž˜์„œ ์‚ฌ์‹ค์€ ์˜ค๋ฅ˜ํŽ˜์ด์ง€ ์š”์ฒญ์—๋Š” ํ•„ํ„ฐ๊ฐ€ ์‹คํ–‰๋˜์ง€ ์•Š์•˜๋‹ค. ๊ธฐ๋ณธ๊ฐ’์€ REQUEST ํ•˜๋‚˜ ๋ฐ–์— ์—†์–ด์„œ ๊ทธ๋ ‡๋‹ค.

public enum DispatcherType {
 FORWARD, // RequestDispatcher.forward(request, response); ํฌ์›Œ๋“œ ์š”์ฒญ
 INCLUDE, // RequestDispatcher.include(request, response); ๋‹ค๋ฅธ ์„œ๋ธ”๋ฆฟ์˜ ๊ฒฐ๊ณผ๋ฅผ ํฌํ•จ
 REQUEST, // ํด๋ผ์ด์–ธํŠธ ํ˜ธ์ถœ
 ASYNC, // ์„œ๋ธ”๋ฆฟ ๋น„๋™๊ธฐ ํ˜ธ์ถœ
 ERROR //์˜ค๋ฅ˜
}

request.getDispatcherType( )

 

 

@ ์ธํ„ฐ์…‰ํ„ฐ์˜ DispatcherType

์ธํ„ฐ์…‰ํ„ฐ๋Š” ์Šคํ”„๋ง MVC์˜ DipatcherServlet์ด ์‹คํ–‰ ๋œ ์ดํ›„์— ์ž‘๋™ํ•˜๋Š” ์Šคํ”„๋ง์˜ ์ถ”๊ฐ€๊ธฐ๋Šฅ์ด๋‹ค. ์ธํ„ฐ์…‰ํ„ฐ์—์„œ๋„ request.DispatcherType ์ •๋ณด๋ฅผ ๋ฐ›์•„์˜ฌ ์ˆ˜๋Š” ์žˆ์ง€๋งŒ ํ•ด๋‹น ํƒ€์ž…์˜ ์ข…๋ฅ˜์™€ ์ƒ๊ด€์—†์ด ์ธํ„ฐ์…‰ํ„ฐ๋Š” ํ•ญ์ƒ ํ˜ธ์ถœ๋œ๋‹ค.

โžก ํ•˜์ง€๋งŒ ๊ฑฑ์ •๋งˆ๋ผ. ์ธํ„ฐ์…‰ํ„ฐ์—๋Š” excludePathPatterns(...)๋ฅผ ์ถ”๊ฐ€ํ•ด์„œ ์ž‘๋™ํ•˜์ง€ ์•Š๋„๋ก ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค.

@Configuration
public class WebConfig implements WebMvcConfigurer {

  @Override
  public void addInterceptors(InterceptorRegistry registry) {
    registry.addInterceptor(new LogInterceptor())
        .order(1)
        .addPathPatterns("/**") // ์‚ฌ์‹ค ๋ฒˆ๊ฑฐ๋กญ๊ฒŒ DispatcherType์„ ์ง€์ •ํ•  ํ•„์š”๊ฐ€ ์—†๋‹ค.
        .excludePathPatterns("/css/**", "*.ico", "/error", "/error-page/**");//์˜ค๋ฅ˜ ํŽ˜์ด์ง€ ๊ฒฝ๋กœ
  }
}

 


# ์Šคํ”„๋ง ๋ถ€ํŠธ์˜ ์˜ค๋ฅ˜ํŽ˜์ด์ง€ ๊ธฐ๋Šฅ

์˜ˆ์™ธ์ฒ˜๋ฆฌ๋ฅผ ๋งŒ๋“ค๊ธฐ์œ„ํ•ด ์šฐ๋ฆฌ๋Š” WebServerCustomizer, ErrorPage, ErroController๋ฅผ ๋”ฐ๋กœ ๋งŒ๋“ค์–ด์•ผ ํ–ˆ๋‹ค.

์‚ฌ์‹ค ๋ฒˆ๊ฑฐ๋กญ๊ฒŒ ๋งŒ๋“ค์ง€ ์•Š์•„๋„ ์Šคํ”„๋ง ๋ถ€ํŠธ๋Š” ์ด๋Ÿฐ ๊ณผ์ •์„ ๋ชจ๋‘ ๊ธฐ๋ณธ์œผ๋กœ ์ œ๊ณตํ•œ๋‹ค.

 

๐Ÿ“Œ์Šคํ”„๋ง๋ถ€ํŠธ์˜ ๋™์ž‘

  • /error/์˜ค๋ฅ˜์ฝ”๋“œ.html ์„ ๊ธฐ๋ณธ ์˜ค๋ฅ˜ํŽ˜์ด์ง€ ๊ฒฝ๋กœ๋กœ ์ธ์‹ํ•œ๋‹ค.

400๋Œ€ ์˜ค๋ฅ˜์ฝ”๋“œ์˜ default๊ฐ’ -> 4xx.html

  • ์Šคํ”„๋ง ๋ถ€ํŠธ์—์„œ BasicErrorController๋ผ๋Š” ์ปจํŠธ๋กค๋Ÿฌ๋ฅผ ์ž๋™์œผ๋กœ ๋“ฑ๋กํ•œ๋‹ค.
     โžก ๊ธฐ๋ณธ ๊ฒฝ๋กœ(/error/์˜ค๋ฅ˜์ฝ”๋“œ.html)๋ฅผ ๋งคํ•‘ํ•œ๋‹ค.
    BasicErrorController์˜ ๋งคํ•‘ ์šฐ์„ ์ˆœ์œ„

  • ์Šคํ”„๋ง ๋ถ€ํŠธ์˜ ErrorMvcAutoConfiguration๋ผ๋Š” ํด๋ž˜์Šค๊ฐ€ ์‚ฌ์šฉํ•  ์˜ค๋ฅ˜ํŽ˜์ด์ง€๋ฅผ WAS์— ๋“ฑ๋กํ•œ๋‹ค.
     โžก ์ด์ œ ์„œ๋ธ”๋ฆฟ ์˜ˆ์™ธ๋‚˜ response.sendError(...)๊ฐ€ ํ˜ธ์ถœ๋˜๋ฉด ๋ชจ๋“  ์˜ค๋ฅ˜๋ฅผ /error/... URL์„ ํ˜ธ์ถœํ•œ๋‹ค.

 


# ์‹ค์ œ๋กœ ๊ฐœ๋ฐœ์ž๊ฐ€ ํ•  ์ผ

์ด์ œ ์˜ค๋ฅ˜ํŽ˜์ด์ง€๋ฅผ ๋งŒ๋“ค๋ ค๊ณ  WebServerCustomizer๋ฅผ ์„ค์ •ํ•˜๊ณ , ์ปจํŠธ๋กค๋Ÿฌ๋ฅผ ๋งŒ๋“คํ•„์š”๊ฐ€ ์—†๋‹ค.

์Šคํ”„๋ง๋ถ€ํŠธ๋ฅผ ์ด์šฉํ•ด์„œ /error/... ๊ฒฝ๋กœ์— 404.html ๊ฐ™์€ ์—๋ŸฌํŽ˜์ด์ง€๋ฅผ ๋งŒ๋“ค๋ฉด ์ž๋™์œผ๋กœ ๋“ฑ๋ก๋œ๋‹ค.

  • BasicErrorController ์—์„œ๋Š” ์˜ค๋ฅ˜์ •๋ณด๋“ค์„ ๋ชจ๋ธ์— ๋‹ด์•„ ๋ทฐ์— ์ „๋‹ฌํ•œ๋‹ค. ํ•„์š”ํ•˜๋‹ค๋ฉด ์•„๋ž˜์™€ ๊ฐ™์ด ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
  <meta charset="utf-8">
</head>
<body>

<div class="container" style="max-width: 600px">
  <div class="py-5 text-center">
    <h2>500 ์˜ค๋ฅ˜ ํ™”๋ฉด ์Šคํ”„๋ง ๋ถ€ํŠธ ์ œ๊ณต</h2>
  </div>
  
  <h1> ์˜ค๋ฅ˜ํ™”๋ฉด์ž…๋‹ˆ๋‹ค </h1>
  <ul>
    <li>์˜ค๋ฅ˜ ์ •๋ณด</li>
    <ul> <!-- ํƒ€์ž„๋ฆฌํ”„์˜ ๋ฌธ์ž์—ด ์ƒ์„ฑ๊ธฐ๋Šฅ. ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์˜ `string ${value}s`์™€ ๋น„์Šท -->
      <li th:text="|timestamp: ${timestamp}|"></li>
      <li th:text="|path: ${path}|"></li>
      <li th:text="|status: ${status}|"></li>
      <li th:text="|message: ${message}|"></li>
      <li th:text="|error: ${error}|"></li>
      <li th:text="|exception: ${exception}|"></li>
      <li th:text="|errors: ${errors}|"></li>
      <li th:text="|trace: ${trace}|"></li>
    </ul>
    </li>
  </ul>

</div> <!-- /container -->

</body>
</html>

 

ํ•˜์ง€๋งŒ ์ด๋Ÿฌํ•œ ์ •๋ณด๋“ค์„ ์˜ค๋ฅ˜ํŽ˜์ด์ง€์— ๋„์šฐ๋ฉด ์‚ฌ์šฉ์ž ๊ฒฝํ—˜&์„œ๋ฒ„ ๋ณด์•ˆ์ƒ ์ข‹์ง€ ์•Š์€ ๋ฐฉ๋ฒ•์ด๋‹ค. ๊ทธ๋ž˜์„œ application.properties๋ฅผ ์ด์šฉํ•ด์„œ BasicErrorController์—์„œ ์ด๋Ÿฌํ•œ ์ •๋ณด๋ฅผ ์ „๋‹ฌํ•˜์ง€ ์•Š๋„๋ก ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค.

exception๋งŒ ์ „๋‹ฌ๋˜๊ณ  ๋‚˜๋จธ์ง€๋Š” ๋นผ๊ณ ์‹ถ์€๊ฒฝ์šฐ ์•„๋ž˜์™€ ๊ฐ™์ด ์„ค์ •ํ•˜๋ฉด ๋œ๋‹ค.

//application.properties
server.error.path=/error // ๊ธฐ๋ณธ ์˜ˆ์™ธ ํŽ˜์ด์ง€ ๊ฒฝ๋กœ
server.error.whitelabel.enabled=false // ์Šคํ”„๋ง ๊ธฐ๋ณธ ์˜ค๋ฅ˜ํŽ˜์ด์ง€[whitelabel.html]์˜ ์‚ฌ์šฉ์—ฌ๋ถ€

server.error.include-exception= true // exception ์ด๋ฆ„ ์ „๋‹ฌ์—ฌ๋ถ€
server.error.include-message= always // ์—๋Ÿฌ ๋ฉ”์‹œ์ง€๋ฅผ ํ•ญ์ƒ ์ „๋‹ฌ
server.error.include-stacktrace= on_param // [URL ์š”์ฒญ ํŒŒ๋ผ๋ฉ”ํƒ€๊ฐ€ ์žˆ์„ ๋•Œ๋งŒ] ์ „๋‹ฌ
server.error.include-binding-errors= never // [์ „๋‹ฌ์•ˆํ•จ]
  • on_param์€ ์•„๋ž˜์™€ ๊ฐ™์ด URL ์š”์ฒญ์ด ์žˆ์„ ๋•Œ๋งŒ ๋ณด์ด๊ฒŒํ•˜๋Š” ๊ธฐ๋Šฅ์ด๋‹ค.
    โžก https://jiwondev.com/error-page?message=&trace= (message์™€ trace ์ •๋ณด ์š”์ฒญ)

 

  • ์ž˜ ์‚ฌ์šฉํ• ์ผ์€ ์—†์ง€๋งŒ, ๋‚˜๋งŒ์˜ ์˜ค๋ฅ˜ ์ปจํŠธ๋กค๋Ÿฌ๊ฐ€ ํ•„์š”ํ•˜๋‹ค๋ฉด BasicErrorController๋ฅผ ์ƒ์†๋ฐ›๊ฑฐ๋‚˜ ErrorController ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ด์šฉํ•˜์—ฌ ์ฝ”๋“œ๋ฅผ ํ™•์žฅํ•˜์—ฌ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

๋ธ”๋กœ๊ทธ์˜ ์ •๋ณด

JiwonDev

JiwonDev

ํ™œ๋™ํ•˜๊ธฐ