Home spring.web.resources.add-mappings 옵션
Post
Cancel

spring.web.resources.add-mappings 옵션

기대와 다른 DispatcherServlet 의 동작 방식

회사에서 특정 엔드포인트에 접속 시 톰캣 에러페이지가 그대로 노출되는 이슈를 디버깅하다가 DispatcherServlet 의 기이한(?) 동작을 발견하고 왜 그런지 궁금하여 알아봤다.

컨트롤러가 바인딩되지 않은 경로로 접속을 하면 당연히 DispatcherServlet 에서 NoHandlerFoundException 이 발생할 것으로 기대했지만 실제 동작은 그렇지 않았다. 오히려 HandlerMapping 단계에서 ResourceHttpRequestHandler 라는 핸들러를 아주 잘 매핑하고 있었다.

스크린샷 2022-11-05 오전 6 34 06

구글링 후 아래 설정에 따라 동작이 달라진다는 사실을 알 수 있었고, 기본값은 true 다.

spring.web.resources.add-mappings: true (default)

핸들러가 없으면 Resource 경로로 매핑한다.

위 설정 하에서는 매핑되는 컨트롤러(=핸들러)가 없더라도 SimpleUrlHandlerMapping.getHandler 에 의해 ResourceHttpRequestHandler 가 매핑된다. 즉, 핸들러가 없는 /no-path-like-this 라는 경로에 요청이 들어왔을 때, 이 경로를 Resource 경로로 판단한다는 뜻이다.

물론 Resource 디렉토리에 이에 해당하는 리소스가 없을 것이니 404를 잘 응답하겠지만, 존재하지 않는 모든 경로를 Resource 경로로 인식하게 끔 하는 것은 내가 의도한 바가 아니었다.

이 같은 동작을 피하기 위해서는 spring.web.resources.add-mappings: false 로 설정하면 된다.

Why?

SimpleUrlHandlerMapping 이 생성될 때 urlMap 을 생성자로 전달 받는대, 이 값은 스프링 애플리케이션이 실행될 때 SimpleUrlHandlerMapping.registerHandlers 에 의해 SimpleUrlHandlerMapping.handlerMap 에 등록된다.

urlMap (이해를 위해 JSON 으로 표현)

1
2
3
4
5
{
  "/webjars/**": "ResourceHttpRequestHandler",
  "/**": "ResourceHttpRequestHandler",
  "/static/**": "ResourceHttpRequestHandler"
}

따라서 런타임에 실제로 없는 경로 (e.g. /no-path-like-me)로 요청이 들어오면 해당 경로가 /** 에 매치되면서 ResourceHttpRequestHandler 를 반환하게 되는것이다.

This post is licensed under CC BY 4.0 by the author.