HTTP 캐싱은 웹 애플리케이션의 성능을 크게 향상시킬 수 있습니다. HTTP 캐싱은 Cache-Control
응답 헤더와 그 이후의 조건부 요청 헤더(예: Last-Modified
및 ETag
)를 중심으로 진행됩니다. Cache-Control
은 private(예: 브라우저) 및 public(예: 프록시) 캐시에 응답을 캐시하고 재사용하는 방법을 advise합니다. ETag
헤더는 내용이 변경되지 않은 경우 본문 없이 304(NOT_MODIFIED)가 발생할 수 있는 조건부 요청을 만드는 데 사용됩니다. ETag
는 Last-Modified
헤더의 보다 정교한 후속 버전으로 볼 수 있습니다.
이 섹션에서는 Spring Web MVC에서 사용할 수 있는 HTTP 캐싱 관련 옵션에 대해 설명합니다.
CacheControl
CacheControl
은 Cache-Control
헤더와 관련된 설정 구성을 지원하며 여러 위치에서 인수로 허용됩니다.
RFC 7234는 Cache-Control
응답 헤더에 대해 가능한 모든 지시문을 설명하지만 CacheControl
유형은 일반적인 시나리오에 초점을 맞춘 사용 사례 중심 접근 방식을 취합니다.
// 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
속성(property)(초 단위로 정의)도 허용합니다.
-1
값은 `Cache-Control 응답 헤더를 생성하지 않습니다.
값이 0
이면 'Cache-Control: no-store'
지시문을 사용하여 캐싱을 방지합니다.
n > 0
값은 'Cache-Control: max-age=n'
지시문을 사용하여 n
초 동안 지정된 응답을 캐시합니다.
컨트롤러는 HTTP 캐싱에 대한 명시적 지원을 추가할 수 있습니다. 조건부 요청 헤더와 비교하기 전에 리소스의 lastModified
또는 ETag
값을 계산해야 하므로 그렇게 하는 것이 좋습니다. 컨트롤러는 다음 예제와 같이 ETag
헤더와 Cache-Control
설정을 ResponseEntity
에 추가할 수 있습니다.
@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);
}
앞의 예에서는 조건부 요청 헤더와의 비교 결과 내용이 변경되지 않았음을 나타내는 경우 빈 본문과 함께 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";
}
(1) 애플리케이션별 계산.
(2) 응답은 304(NOT_MODIFIED) — 추가 처리 없음으로 설정되었습니다.
(3) 요청 처리를 계속하세요.
eTag
값, lastModified
값 또는 둘 다를 기준으로 조건부 요청을 확인하는 세 가지 변형이 있습니다. 조건부 GET
및 HEAD
요청의 경우 응답을 304(NOT_MODIFIED)로 설정할 수 있습니다. 조건부 POST
, PUT
및 DELETE
의 경우 응답을 412(PRECONDITION_FAILED)로 설정하여 동시 수정을 방지할 수 있습니다.
최적의 성능을 위해서는 Cache-Control
및 조건부 응답 헤더를 사용하여 정적 리소스를 제공해야 합니다. Static Resources 구성에 대한 섹션을 참조하세요.
ETag
FilterShallowEtagHeaderFilter
를 사용하면 응답 콘텐츠에서 계산되는 "얕은" eTag
값을 추가할 수 있으므로 대역폭은 절약되지만 CPU 시간은 절약되지 않습니다. 얕은 ETag를 참조하세요.