ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Spring Boot : Default Error Response : 기본 에러 응답
    Spring Boot 2024. 4. 10. 18:33

    개발 환경

    • Java 21
    • Spring Boot 3.2.4

    기본 에러 응답

    Spring Boot에서 아무 설정도 하지 않고 RestController 구성하여 예외 발생시키면 다음과 같은 형태의 response body를 응답한다.

    {
        "timestamp": "2024-04-05T13:37:51.440+00:00",
        "status": 405,
        "error": "Method Not Allowed",
        "path": "/"
    }

    어디에서 기본 에러 응답 body를 만드나?

    어디에서 어떤 과정을 거쳐 이런 형태의 에러 응답을 하는지 궁금하여 간략하게 정리해보았다.
    아래에 그 과정에서 알게된 몇 가지 설정도 적어두었다.

    아래에서 1차 처리

    package org.springframework.web.servlet.mvc.support;
    
    public class DefaultHandlerExceptionResolver extends AbstractHandlerExceptionResolver {
    
        @Override
        @Nullable
        protected ModelAndView doResolveException(
                HttpServletRequest request, HttpServletResponse response, @Nullable Object handler, Exception ex) {
            // ...
        }
    }

    에러 응답하는 곳

    package org.springframework.boot.autoconfigure.web.servlet.error;
    
    @Controller
    @RequestMapping("${server.error.path:${error.path:/error}}")
    public class BasicErrorController extends AbstractErrorController {
    
        @RequestMapping
        public ResponseEntity<Map<String, Object>> error(HttpServletRequest request) {
            HttpStatus status = getStatus(request);
            if (status == HttpStatus.NO_CONTENT) {
                return new ResponseEntity<>(status);
            }
            Map<String, Object> body = getErrorAttributes(request, getErrorAttributeOptions(request, MediaType.ALL));
            return new ResponseEntity<>(body, status);
        }
    }

    response body 만드는 곳

    package org.springframework.boot.autoconfigure.web.servlet.error;
    
    @Order(Integer.MIN_VALUE)
    public class DefaultErrorAttributes implements ErrorAttributes, HandlerExceptionResolver, Ordered {
    
        public Map<String, Object> getErrorAttributes(WebRequest webRequest, ErrorAttributeOptions options) {
            Map<String, Object> errorAttributes = this.getErrorAttributes(webRequest, options.isIncluded(Include.STACK_TRACE));
            if (!options.isIncluded(Include.EXCEPTION)) {
                errorAttributes.remove("exception");
            }
    
            if (!options.isIncluded(Include.STACK_TRACE)) {
                errorAttributes.remove("trace");
            }
    
            if (!options.isIncluded(Include.MESSAGE) && errorAttributes.get("message") != null) {
                errorAttributes.remove("message");
            }
    
            if (!options.isIncluded(Include.BINDING_ERRORS)) {
                errorAttributes.remove("errors");
            }
    
            return errorAttributes;
        }
    }

    Spring Boot DevTools의 영향

    DevTools를 포함시키면 아래 설정들이 자동으로 들어가서 에러 응답이

    화려해진다.

     사용자에게 노출하지 않고 싶은 필드도 자동으로 추가된다.

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

    gradle에서 다음과 같이 추가되어 있다면, 로컬에서 gradle bootRun으로 실행할 때에만 포함되고, jar 빌드할 때에는 포함되지 않는다.
    즉, 별다른 설정을 하지 않아도 운영 환경에는 적용되지 않는다.

    dependencies {
        developmentOnly 'org.springframework.boot:spring-boot-devtools'
    }

    maven에서도 spring-boot-maven-plugin이 똑같은 역할을 해준다.

    만약 개발 환경에서 운영 환경의 에러 응답을 확인하고 싶다면 다음 두 가지 방법 중 하나를 적용하면 된다.

    방법 1

    아래 설정을 application.properties에 포함시킨다.
    DevTools가 없을 때의 기본 값이다.

    • 장점: 에러 응답에 관한 것만 적용할 수 있다.
    server.error.include-binding-errors=never
    server.error.include-message=never
    server.error.include-stacktrace=never

    방법 2

    아래 설정을 application.properties에 포함시킨다.

    • 장점: devtools로 인해 적용되는 properties를 한번에 끌 수 있다.
    spring.devtools.add-properties=false
Designed by Tistory.