[주의] Spring Boot가 아닌 Spring MVC Legacy Project를 생성해 공부 중인 자료입니다.
오늘 겪었던 일이다. 현재 개인공부로 스프링 프레임워크로 나만의 페이지를 제작하고 있다. 오늘은 오픈소스로 공개된 글 에디터를 사용해보기 위해 나는 다음에서 제작한 다음 에디터를 내 홈페이지 글쓰기 페이지에다가 입히려고 했다.
분명 리소스들의 경로도 제대로 설정 했고, 확인도 했다.
하지만 결과는...
오류 코드를 보면 404 오류 천지, 그니깐 찾을 수 없단다. (net::ERR_ABORTED, .... is not defined ...)
구글링을 통해 알게 된 결론은 컨트롤러 단에서 매핑하지 않은 정적 리소스 파일들은 불러오지를 못하고 만다는 것이다.
(이게 정확한 워딩은 아니다. 나도 초보고, 이제 막 배우기 시작했다)
그렇다면 이제 해결해보자
방법은 두 가지를 찾았다.
첫 번째로는 직접 처리가 필요한 리소스 파일의 확장자를 매핑해주는 방법이다.
일단, <web.xml> 파일을 찾아가자 (단축키는 'Ctrl + Shift + R', 빠르게 필요한 파일을 찾을 때 유용하다)
여기에 도착하면 별 알 수 없는 여러 코드들이 우릴 마주한다.
대충 웹 어플리케이션 실행 시 우리가 어떻게 무엇을 할지에 대한 설정을 정의해주는 곳이다.
그렇다면 여기서 우리가 사용할 리소스 파일들을 선언해 실행시에 불러와 줄 수 있도록 하자.
<!-- Processes application requests --> 라는 주석을 발견할 수 있을 것이다.
직역하면 '애플리케이션 요청 처리'를 하는 곳이다. 우리가 필요한 부분이다.
(사실 아무대나 써도 되지만, 코드를 보기 좋게 처음부터 쓰면 나중에 유지보수가 용이하지 않을까)
<!-- Processes application requests -->
<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>appServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!-- *.js 확장자 파일의 요청이 오면 default 서블릿을 사용하겠다 -->
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.js</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.css</url-pattern>
</servlet-mapping>
이와 같이 js 파일과 css 파일을 매핑해보자. 주석 내용 처럼 될까?
톰캣 서버를 다시 실행해보자.
뭔가 바뀌긴 했다. 근데 밋밋하게 느껴진다. 뭘까?
그렇다. 다른 gif, png, ico 파일 등 많은 다른 정적 리소스들이 누락되었다. 물론 필요한 확장자만 추가해서 불러오도록 하는 장점이 있지만, 위 캡쳐같이 다른 파일들을 놓칠 수도 있겠다는 생각이 들었다.
그렇다면 한번에 모든 정적 파일들을의 요청을 처리할 수는 없을까?
그렇다. 있었다.
바로 <servlet-context.xml>에
<default-servlet-handler />
라는 핸들러를 작성해주면 된다.
이게 무엇을 말하는 거냐면...
Servlet Context는 Servlet에 대한 설정을 작성하는 클래스라고 보면 되는데, Servlet과 Container의 연동시 사용하며, 웹 어플리케이션마다 하나의 Servlet Context가 생성된다. Bean을 찾는 순서가 Servlet Context가 Application Context 보다 먼저 실행되고, 컨테이너 종료시 소멸한다.
나도 더 공부해야겠다. 말이 많이 어려운 듯 하다.
(잘못된 점이 있다면 따끔하게 댓글 남겨주세요)
어쨌거나 저쨌거나 이제 사용을 해보자.
일단, 먼저 Namespaces를 추가해 주어야 한다.
그렇다면 요렇게 추가가 된다. 그 후에 위에 적은 핸들러 코드를 잘 집어 넣어보자.
<servlet-context.xml 예제>
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure -->
<!-- Enables the Spring MVC @Controller programming model -->
<annotation-driven />
<!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources directory -->
<resources mapping="/resources/**" location="/resources/" />
<!-- Resolves views selected for rendering by @Controllers to .jsp resources in the /WEB-INF/views directory -->
<beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<beans:property name="prefix" value="/WEB-INF/views/" />
<beans:property name="suffix" value=".jsp" />
</beans:bean>
<context:component-scan base-package="com.example.mvcboard" />
<!-- .js .css 등 정적 리소스를 불러오지 못할 때 -->
<default-servlet-handler />
</beans:beans>
서버를 다시 실행하면?
보다시피 오류 하나 없이 모든 리소스를 불러와 깔끔하게 화면이 출력됨을 알 수 있다.
이거 하나 찾느라 꽤 시간을 투자한 것 같다. 하지만 해결하면서 몰랐던 용어들도 공부할 수 있었고 좋았다.
하지만 더 찾아보고 이해해보려 노력해야겠다.
블로그를 통해 많은 공부, 복습을 할 수 있도록 하겠다.
도움 받은 곳들
- Spring에서 css,image,js 등의 정적 리소스를 찾을 수 없을때 :: 밍깅료의 블로그 (tistory.com)
- [Spring Framework] Spring MVC : <mvc:default-servlet-handler/> 개념 (tistory.com)
- 그외 구글링.....