0. 배경
RFC(Request for Comments) 표준 방식에 의해 캐시 validation 방식이 변경됨
기존 : etag, last-modified 둘다 비교
변경 : etag 만 비교
etag 도입이 필요하다
1. etag 란
ETag == entity tag == 응답 body 값의 해시 값
HTTP 응답 헤더에 담아서 보내준다
응답 body 가 변하면 etag 도 변해야 한다
2. spring boot 에서 etag를 사용하기 위한 전제조건
# web.xml or build.gradle
<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>/foos/*</url-pattern>
</filter-mapping>
3-1. (내가 사용한 방법) servlet filter 사용
servlet filter 란?
Client -> Server 로 요청이 들어오기 전에 서블릿을 거쳐서 필터링 하는 것
@Bean
public ShallowEtagHeaderFilter shallowEtagHeaderFilter() {
return new ShallowEtagHeaderFilter();
}
위 코드만 작성해주면 해당 스프링부트 앱에서 제공하는 모든 응답에 etag 가 붙게 된다
@Bean
public FilterRegistrationBean<ShallowEtagHeaderFilter> shallowEtagHeaderFilter() {
FilterRegistrationBean<ShallowEtagHeaderFilter> filterRegistrationBean
= new FilterRegistrationBean<>( new ShallowEtagHeaderFilter());
filterRegistrationBean.addUrlPatterns("/foos/*");
return filterRegistrationBean;
}
나의 경우 위와 같이 UrlPattern을 등록해서,
등록된 url 과 맞는 패턴의 경우에만 etag가 붙도록 했다
3-2. ResponseEntity 의 etag 메소드 사용하기
@GetMapping(value = "/{id}/custom-etag")
public ResponseEntity<Foo>
findByIdWithCustomEtag(@PathVariable("id") final Long id) {
// ...Foo foo = ...
return ResponseEntity.ok()
.eTag(Long.toString(foo.getVersion()))
.body(foo);
}
위와 같이 ResponseEntity 에 .etag 메소드로 etag를 지정해줄 수 있다.
이 경우, etag 를 만들기 위한 해싱에 사용될 값을 직접 정의할 수 있고,
딱 etag 를 적용할 API 에만 적용할 수 있다는 장점이 있다
4. 의문점
의문점 1. ShallowEtagHeaderFilter 는 어떤 값을 받아서 해싱하는가?
답변 1. 응답 결과의 body 를 받아서 해싱하는게 아닐까?
spring web 의 ShallowEtagHeaderFilter.java 소스코드를 확인해보았지만 명확한 답을 찾지 못했음
(https://github.com/spring-projects/spring-framework/blob/main/spring-web/src/main/java/org/springframework/web/filter/ShallowEtagHeaderFilter.java#L95)
의문점 2. Servlet filter 을 사용하면 스프링의 모든 API 응답 헤더에 etag가 붙게 되는가?
이론상 다 붙어야 한다고 생각했는데, 적용해 보다보니 붙는 곳도 있고, 안붙는 곳도 있는 것 같다
* 테스트를 해보니 ResponseEntity 에 lastModified 와 cacheControl 설정 두개를 해주어야 자동으로 etag 가 헤더에 붙어 나왔다
* 아무래도 둘다 설정이 되어있어야 캐시 사용한다고 인식해서 그런듯..?
* 그런데 lastmodified 와 etag 는 양쪽다 validation 을 위해 사용되는데 왜 둘다 필요한지 의문..
5. 참고 링크
'Backend' 카테고리의 다른 글
nginx 버전이 노출되어 있으면 위험할 수 있다구? (0) | 2021.12.27 |
---|---|
java 의 로깅 이란 (JCL, SLF4J, log4j, logback) (0) | 2021.12.13 |
docker quick start 따라해보기 (0) | 2020.06.07 |
왜 도커를 사용해야 할까요? (0) | 2020.06.07 |
kotlin으로 java springboot 프로젝트 리팩토링 하기 2 (0) | 2020.04.19 |