-
스프링 url-pattern 설정(/ 와 *.) 차이에 대한 개념!!Spring(스프링) 2015. 12. 1. 09:46반응형
[*.do에서 /* 로 바꾸게 된 이유]
스프링 3.1 샘플 프로젝트의 web.xml(DD) 구성 시 url-pattern을 *.do와 같이 설정하였다.
이유는 단순하다.
프로젝트를 진행할 때 항상 *.do를 사용했기 때문이다.
하지만 REST 방식의 웹 어플리케이션을 구성하기 위해서는 다음과 같은 URL 형식을 제공해야 하는데 현재는 *.do와 같이 되어 있기 때문에 pattern을 /* 와 같이 변경해야만 했다.
http://localhost:8080/user/list
[현상]
이제 내가 만들어 놓은 프로젝트는 REST 방식을 지원하는 spring web application이 되었다.
허나 controller mapping url을 호출하면 404 에러가 발생하면서 아래와 같은 로그가 찍힌다.
No mapping found for HTTP request with URI [/WEB-INF/view/common/layout/default/layout.jsp] in
DispatcherServlet with name 'dispatcher'
[원인]controller mapping url을 못 찾아서 발생하는 404가 아닌 /WEB-INF/view/common/layout/default/layout.jsp 의 매핑 URL을 찾을 수 없어서 발생하는 오류였다.이 오류가 발생하는 원인을 알기 위해서는 서블릿 컨테이너와 웹 어플리케이션간의 연동 방법을 알아야 한다.일단 url-pattern에 등록할 수 있는 URL은 다음과 같다."/"로 시작하고 "/*"로 끝나는 패턴은 path로 인식"*."으로 시작하는 경우 확장자 매칭"/"만 정의한 경우 디폴트 서블릿 의미그 외의 경우 동치 매칭위의 패턴 매칭에 존재하지는 않지만 /*는 요청 받는 모든 URL을 처리한다는 의미다. (아래와 같은 유형의 패턴 모두)/user/list/user/list.do/user/userList.jsp/img/test.png결국 모든 요청을 DispatcherServlet에서 처리하겠다고 지정했으니 jsp에 대한 호출도 DispatcherServlet이 처리를 하려고 했던 것이다.이로 인하여 jsp에 해당하는 mapping url을 찾을 수 없어 HTTP 404 오류가 발생하게 된 것이다.[해결 방안]그럼 해결 방법은 뭘까?결론적으로 말하자면 url-pattern을 "/" 로 지정하면 된다.해결 방법은 간단하지만 왜 이렇게 설정하면 잘 되는지 궁금해 졌다.위에서 언급했지만 "/"로 정의한 경우 디폴트 서블릿을 의미한다고 하였다.이게 뭔 말인가?이 말의 의미를 찾아 보니 디폴트 서블릿은 서블릿 매핑 URL에 걸리지 않는 요청들을 처리한다고 한다.또 의문이 생긴다.난 서블릿 매핑을 "/" 와 같이 한 개만 만들었는데...결국 거르는 작업 없이 내가 만들어 놓은 서블릿 매핑에 모두 걸리는 것 아닌가?그리고 디폴트 서블릿은 뭔가?위의 의문들을 해결하기 위해서 이제 tomcat 서블릿 컨테이너에 대해서 언급할 때가 왔다.${TOMCAT_HOME}/conf/web.xml 파일을 열어 보면 다음과 같이 세 개의 서블릿 매핑이 존재한다.<servlet-mapping><servlet-name>default</servlet-name><url-pattern>/</url-pattern></servlet-mapping><servlet><servlet-name>default</servlet-name><servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class><init-param><param-name>debug</param-name><param-value>0</param-value></init-param><init-param><param-name>listings</param-name><param-value>false</param-value></init-param><load-on-startup>1</load-on-startup></servlet><servlet-mapping><servlet-name>jsp</servlet-name><url-pattern>*.jsp</url-pattern></servlet-mapping><servlet-mapping><servlet-name>jsp</servlet-name><url-pattern>*.jspx</url-pattern></servlet-mapping><servlet><servlet-name>jsp</servlet-name><servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class><init-param><param-name>fork</param-name><param-value>false</param-value></init-param><init-param><param-name>xpoweredBy</param-name><param-value>false</param-value></init-param><load-on-startup>3</load-on-startup></servlet>*.jsp, *.jspx와 같은 url 패턴은 JspServlet이 처리하고, DefaultServlet은 spring Controller mapping과 jsp 패턴에 걸리지 않는 요청 들을 처리한다는 결론이 나온다.즉, DefaultServlet은 png, jpg, js, html등 정적인 content를 처리한다는 말이다.정리하면http://localhost:8080/user/userList.jsp <- JspServlet 요청 처리http://localhost:8080/img/button.jpg <- DefaultServlet 요청 처리http://localhost:8080/user/list <- DispatcherServlet 요청 처리[스프링에서 정적 content 호출 시 404 에러 발생]문제가 생겼다.http://localhost:8080/user/list 는 정상적으로 동작하는데http://localhost:8080/img/button.jpg 로 호출 할 때 404 에러가 발생한다.DispatcherServlet with name 'dispatcher' processing GET request for [/img/button.jpg]로그를 보면 *.jpg 호출 시 DefaultServlet이 처리하는 것이 아닌 DispatcherServlet이 처리를 하게 되는 것을 볼 수 있다.당연히 DispatcherServlet이 처리를 하게 되면 controller mapping URL이 존재하지 않으니 404 오류가 발생한다.DispatcherServlet은 url-pattern을 "/" 와 같이 설정하게 되면서 tomcat의 server.xml에 정의되어 있는 url-pattern "/"을 무시하기 때문이다.결국 DispatcherServlet url-pattern을 재정의하게 되어서 DefaultServlet은 더이상 동작할 수 없게 된 것이다.스프링에서는 이를 해결하기 위해서 <mvc:default-servlet-handler /> 설정을 지원한다.<mvc:default-servlet-handler /> 설정은 내부적으로 DefaultServletHttpRequestHandler가 담당하게 되고, 이 핸들러(컨트롤러)는 /**로 매핑되어 있다고 한다. (아래 토비님 글 참고)DefaultServletHttpRequestHandler가 하는 역할은 DispatcherServlet이 처리 못하는 매핑 url을 DefaultServlet으로 넘기는 것이다.드디어 정리 끝...이라고 생각하면 오산.<mvc:default-servlet-handler /> 설정을 추가하니 http://localhost:8080/user/list 호출 시 404에러가 발생한다.로그를 확인해 보니 이상한 부분이 있었다.아래와 같이 SimpleUrlHandlerMapping에서 처리를 하고 있는 것이다.SimpleUrlHandlerMapping - Matching patterns for request [/user/list] are [/**]디폴트 핸들러 매핑인 DefaultAnnotationHandlerMapping이 처리해야 하는데 왜 SimpleUrlHandlerMapping이 처리를 하게 된 것일까?이유는 두 개 이상의 핸들러 매핑이 등록되었을 경우에는 디폴트 전략이 무시되기 때문이다.결국 <mvc:annotation-driven /> 설정을 통해 DefaultAnnotationHandlerMapping이 자동 등록되게 설정하였고, 이로써 모든 요청이 정상적으로 동작하였다.단지 url-pattern만 정리하려고 했는데 꼬리에 꼬리를 물어서 스프링까지 설정까지 오게 되었다.지금까지 url-pattern에 대해서 대수롭지 않게 생각했는데 까면 깔수록 공부해야 할 것들이 산더미이다.그래도 오늘 하루 내가 뭔가를 배울 수 있었다는 것에 보람을 느낀다.(출처 : http://lng1982.tistory.com/97)
반응형'Spring(스프링)' 카테고리의 다른 글
스프링 컴포넌트 스캔(component-scan) 짚고 넘어가기 (0) 2016.01.02 스프링 ApplicationContext 동작방식 (0) 2015.12.31 스프링 viewResolver (0) 2015.09.25 스프링 @ResponseBody 어노테이션 (0) 2015.09.15 스프링 DI(Dependency Injection) 개념 및 설정 방법!! (1) 2015.07.05