HTTP 캐싱은 웹 어플리케이션의 성능을 크게 향상시킬 수 있다. HTTP 캐싱은 Cache-Control 응답 헤더나 Last-Modified 요청 헤더나 ETag 요청 헤더의 결합으로 이루어진다.
Cache-Control 응답 헤더는 어떻게 캐싱하고 응답을 재사용할지 명시한다. ETag 헤더는 만약에 응답 내용이 변경되지 않는 경우, 본문이 없는 304(NOT_MODIFIED) 응답을 만들기 위한 조건적인 요청을 보낼 때 사용한다. ETtag 헤더는 Last-Modified 헤더보다 더 정교하게 설정할 수 있게 해준다.
CacheControl은 Cache-Control 헤더 설정을 할 수 있게 해주며, 다음과 같은 위치에서 매개변수로 사용할 수 있다.
// Cache for an hour - "Cache-Control: max-age=3600"
CacheControl ccCacheOneHour = CacheControl.maxAge(1, TimeUnit.HOURS);
// Prevent caching - "Cache-Control: no-store"
CacheControl ccNoStore = CacheControl.noStore();
// Cache for ten days in public and private caches,
// public caches should not transform the response
// "Cache-Control: max-age=864000, public, no-transform"
CacheControl ccCustom = CacheControl.maxAge(10, TimeUnit.DAYS).noTransform().cachePublic();
WebContentGenerator는 다음과 같이 작동하는 간단한 cachePeriod 속성을 허용한다.
컨트롤러는 HTTP 캐싱에 대한 설정을 할 수 있다. 또한 컨트롤러는 Last-Modified 요청 헤더 또는 ETag 요청 헤더와 비교하여 계산할 수 있다. 다음의 예제는 컨트롤러가 ResponseEntity에 ETag 헤더와 Cache-Control 응답 헤더를 설정할 수 있는 것을 보여준다.
@GetMapping("/book/{id}")
public ResponseEntity<Book> showBook(@PathVariable Long id) {
Book book = findBook(id);
String version = book.getVersion();
return ResponseEntity
.ok()
.cacheControl(CacheControl.maxAge(30, TimeUnit.DAYS))
.eTag(version) // lastModified is also available
.body(book);
}
위의 예는 조건부 요청 헤더(Etag 헤더)와 비교해서 콘텐츠가 변경되지 않았음을 명시할 경우 본문이 없는 304(NOT_MODIFIED) 응답을 보내는 경우를 보여준다. 그렇지 않으면, ETag나 Cache-Control 헤더가 응답에 추가된다.
또한 다음과 같이 컨트롤러에서 조건부 요청 헤더에 대해 체크할 수 있다.
@RequestMapping
public String myHandleMethod(WebRequest request, Model model) {
long eTag = ... // 1.
if (request.checkNotModified(eTag)) {
return null; // 2.
}
model.addAttribute(...); // 3.
return "myViewName";
}
ETag 요청 헤더와 Last-Modified 요청 헤더를 각각 체크하거나 둘 다 체크할 수도 있다. 또한 GET, HEAD 요청에 대해서는 응답을 304(NOT_MODIFIED)로 설정할 수 있으며 POST, PUT, DELTETE 요청에 대해서는 동시 수정을 방지하기 위해 응답을 412 (PRECONDITION_FAILED)로 설정할 수 있다.
참고