기존에 정적리소스(css,js 등)을 수정하고 운영서버에 업로드하면 기존 사용자들에게는 최신 버전의 리소스가 적용되지 않는 문제가 있어서 파일을 수정할 때마다 해당 파일을 사용하는 부분에 finger-print 이용하여 강제로 불러오게 했었다.
ex)<script src='/js/test.js?ver=1.0'></script>
하지만 수정한 파일이 많으면 아무래도 수정할 부분이 많아서 일일이 다 찾아서 수정하기가 쉽지 않았다. 그래서 etag를 이용한 정적 리소스 캐시 관리방법을 생각하게 되었다.
스프링과 apache-tomcat 환경에서 정적리소스 캐시관리를 하기 위해선 여러 방법이 있는데 나는 Etag를 사용했다. 우선 정적 리소스에 대해 cache-control을 설정하는 클래스를 만들어야 된다.
etag와 캐시 정책에 대한 정보는 아래글에 자세히 나와있다.
HTTP (7) - 캐시와 조건부 요청 (Last-Modified / ETag)
[HTTP 로컬 캐시] [검증 헤더] [조건부 요청]
velog.io
그 밖에 캐시의 원리, 정책과 다양한 캐싱 방식에 대한건 아래글에 자세히 나와있다.
더 빠른 웹을 위하여 - 웹 캐쉬 (WEB CACHE)
WEB-CACHE (TIME-SPACE TRADEOFF) 더 빠른 웹사이트를 위해 저희 개발자들은 눈물겨운 노력을 많이 합니다. - WebCache - Code Compressing - Image Optimizing - Image Spriting - Critical Rendering Path - Webfont Optimizing - Lazy Loadin
cyberx.tistory.com
어쨌든 그래서 내가 사용하는 스프링에선 web.xml을 사용하는데 필터 클래스를 만들고 web.xml에 등록해주어야 된다.
먼저 java 코드는 아래와 같다.
import javax.servlet.*;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class CacheControlFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
// 초기화 작업이 필요하면 구현
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletResponse httpResp = (HttpServletResponse) response;
//캐시 사용하지 않도록 설정
httpResp.setHeader("Cache-Control", "no-cache, must-revalidate");
// 또는 캐시 유효시간을 1시간(max-age=3600)으로 설정
// httpResp.setHeader("Cache-Control", "max-age=3600, must-revalidate");
chain.doFilter(request, response);
}
@Override
public void destroy() {
// 종료 작업이 필요하면 구현
}
}
web.xml에 필터를 등록해준다.
<filter>
<filter-name>cacheControlFilter</filter-name>
<filter-class>com.ex.CacheControlFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>cacheControlFilter</filter-name>
<url-pattern>*.js</url-pattern>
<url-pattern>*.css</url-pattern>
</filter-mapping>
이제 etag를 설정해줘야 되는데 spring에서 제공하는 ShallowEtagHeaderFilter라는게 있다. 해당 클래스를 이용해서 등록을 해보겠다.
<filter>
<filter-name>etagFilter</filter-name>
<filter-class>org.springframework.web.filter.ShallowEtagHeaderFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>etagFilter</filter-name>
<url-pattern>*.js</url-pattern>
<url-pattern>*.css</url-pattern>
</filter-mapping>
이런식으로 web.xml에 추가해주면 작업은 완료된다. 한 가지 유의할 점은 만약 운영하고 있는 사이트에 기존파일의 캐시를 가지고 있는 사용자가 있다면 먼저 그 캐시를 날려줘야 새로운 캐시 정책이 적용이 된다. 따라서 운영중에 이 작업을 할 경우 반영 시 사용자의 모든 캐시를 날려야 한다.