본문으로 건너뛰기

HTTP Caching

· 약 4분

https://developer.mozilla.org/ko/docs/Web/HTTP/Caching 글을 정리했습니다.

빠른 웹사이트 로딩(First load times)을 위한 방법들은 여러가지가 있습니다.

  • WebCache
  • Code Compress
  • Lazy loading
  • Critical Rendering Path
  • ...

이중 Http Caching에 대해 정리해보았습니다. HTTP 캐시들은 일반적으로 GET에 대한 응답만을 캐싱합니다. GET이 REST적 의미로 가져오다이기 때문에, 가져온 데이터를 저장해두고 두고두고 사용합니다. 일반적으로 200(성공), 301(다른 주소로 이동 후 가져옴), 404(가져올게 없음) 상태 코드로 온 응답을 캐싱합니다.

Cache-control 헤더​

캐시 정책들을 정의할 때 쓰는 헤더입니다.

캐시하지 않음​

클라이언트 요청 혹은 응답에 대해 어떤 것도 저장하지 않습니다.

Cache-Control: no-store

캐시하지만 재검증​

캐시를 사용하기 전에 서버에게 이 캐시 진짜 써도 되는지 물어봅니다.

Cache-Control: no-cache

사설 캐시와 공개 캐시​

"public"은 어떤 캐시(CDN)에 의해서든지 캐시되어도 좋다는 뜻입니다.

"private"는 공유 캐시에 저장되어서는 안된다는 뜻입니다.(브라우저)

Cache-Control: private
Cache-Control: public

만료​

max-age
리소스가 유효하다고 판단되는 최대 시간을 말합니다. 요청 시간에 상대적이며, Expires가 설정되어 있어도 그보다 우선합니다. 변경되지 않을 파일에 대해 긴시간 캐싱할 수 있습니다. 예를들어 이미지, CSS 파일, JS파일과 같은 정적 파일들입니다.

Cache-Control: max-age=3153600

Age
Age 헤더는 캐시 응답 때 나타나는데, max-age 시간 내에서 얼마나 흘렸는지 초 단위로 알려줍니다. max-age를 1시간으로 설정한 후 1분이 지나면

Cache-Control: max-age=3600
Age: 60

이 캐시 응답 헤더에 포함됩니다.

Expires
Cache-Control과 별개로 응답에 Expires라는 헤더를 줄 수도 있습니다.
response contents가 언제 만료되는지를 나타내며, Cache-Control의 max-age가 있는 경우 이 헤더는 무시됩니다.

검증​

만료된 캐시면 서버에서 확인을 받아야 합니다.

Cache-Control: must-revalidate

유효성(Freshness)​

리소스가 캐시에 저장되고 나면 이론적으로는 영원히 캐시에 의해 서비스될 수 있습니다. 하지만 캐시는 유한한 저장공간을 가지므로 주기적으로 스토리지에서 제거되는데 이를 캐시축출(cache eviction)이라고 부릅니다.

만료시간 이전의 리소스는 유효하다(fresh)라고 부르고, 만료시간 이후의 리소스는 실효(stale)됐다고 이야기 합니다.

캐시가 실효된 리소스에 대해 요청을 받았을 때(max-age 초과, no-cache, must-revalidate) 리소스가 아직 유효한지 아닌지를 확인하고, 유효하다면 서버는 요청된 리소스 본문을 전송하지 않고 304(Not Modified)헤더를 돌려보내 대역폭을 절약합니다.

캐시 검증​

캐시된 리소스의 만료시간이 가까워지면, 리소스를 검증하거나 다시 불러오게 됩니다.

ETags​

HTTP 컨텐츠가 바뀌였는지를 검사할 수 있는 태그입니다. 같은 주소의 자원이더라도 컨텐츠가 달라졌다면 ETag가 다릅니다.

Example​

200 (from memory cache)(from disk cache)​

max-age가 거의 무한이고, age도 많이 흐르지 않았기에 유효한 리소스라 memory에 있는 리소스(캐시된 리소스)를 그대로 사용한다.

memory cache vs disk cache​

브라우저가 캐시를 사용할 때 memory에 저장되어 있는 캐시를 사용하거나 disk에 저장된 캐시를 사용할 수 있다. memory는 최근에 사용했다면 있을 것이고 그렇지않다면 disk에 있을 것이다.

disk가 memory보다 데이터를 가져오는 속도가 느리기에 당연히 속도 차이가 난다. (memory: 0ms, disk: 3ms)

cache-memory-disk

[General]
Request URL: https://abcd.com/a.js
Request Method: GET
Status Code: 200 (from memory cache)
Remote Address: 54.192.175.42:443
Referrer Policy: strict-origin-when-cross-origin

[Response Headers]
accept-ranges: bytes
age: 34710
cache-control: public, max-age=31536000, immutable
content-encoding: gzip
content-type: application/javascript; charset=UTF-8
date: Thu, 19 Aug 2021 04:48:26 GMT
etag: W/"1ffd7-17b5cba00f8"
last-modified: Thu, 19 Aug 2021 04:44:59 GMT
server: CloudFront
vary: Accept-Encoding
via: 1.1 f681dbff28feeb503e3ad2f4be29ead3.cloudfront.net (CloudFront)
x-amz-cf-id: Lcm5rnqwYZiSzQT9XETch79qqg6XHOpATvBUWVnefT4VlI2CNs9Veg==
x-amz-cf-pop: ICN55-C1
x-cache: Hit from cloudfront

304 (Not Modified)​

max-age=0 이라 컨텐츠가 유효한지 sever로 재검증을 하게 된다. 하지만 CloudFront에 저장된 리소스 ETag 일치하므로 서버의 리소스가 갱신되지 않았다는 것을 알 수 있고 304 status code를 보내어 브라우저에 저장된 캐시를 재사용한다.

[General]
Request URL: https://abcd.com/a.png
Request Method: GET
Status Code: 304
Remote Address: 54.192.175.42:443
Referrer Policy: strict-origin-when-cross-origin

[Response Headers]
accept-ranges: bytes
cache-control: public, max-age=0
date: Thu, 19 Aug 2021 14:27:09 GMT
etag: W/"82cc92-17b5cb83408"
last-modified: Thu, 19 Aug 2021 04:43:01 GMT
server: CloudFront
via: 1.1 f681dbff28feeb503e3ad2f4be29ead3.cloudfront.net (CloudFront)
x-amz-cf-id: OgTtmM59-0C7A8KfeXsoiUWBrAduM1CHuVZnjHNFuFzPy6BgS7Datg==
x-amz-cf-pop: ICN55-C1
x-cache: Miss from cloudfront

Reference​