네트워크를 통해 리소스를 가져오는 것은 무겁고 비쌉니다.

  • 큰 응답은 브라우저와 서버 간 많은 왕복이 필요합니다.
  • 페이지는 모든 필수 리소스가 완전히 다운로드 되기 전에 로드되지 않습니다.
  • 제한된 데이터 플랜을 가진 모바일 폰으로 웹사이트 접근 시, 불필요한 네트워크 요청은 돈낭비가 될 것입니다.

Browser compatibility

모든 브라우저에서 아래 API를 모두 지원합니다.

  • Cache-Control
  • ETag
  • Last-Modified

이전의 가져온 리소스들을 재사용하면 웹 사이트와 애플리케이션의 성능을 향상시킬 수 있습니다. HTTP 캐싱은 웹 사이트가 좀 더 빠르게 반응하도록 만들 수 있습니다.

캐싱: 주어진 리소스의 복사본을 저장하고 있다가 요청시에 제공하는 기술

⇒ 서버의 부하 완화, 성능 향상

⇒ but 리소스가 변할 수 있기 때문에 변하기 전에만 캐싱하고 변한 이후에 더 이상 캐싱하지 않는 것이 중요

캐싱 동작의 대상

  • 검색 요청의 성공적인 결과: HTML 문서, 이미지 혹은 파일과 같은 리소스를 포함하는 GET 요청에 대한 200(OK) 응답
  • 영구적인 리다이렉트: 301(Moved Permanently) 응답
  • 오류 응답: 404 (Not Found)
  • 완전하지 않은 결과: 206(Partial Content)
  • 캐시 키로 사용하기에 적절한 무언가가 정의된 경우의 GET 이외의 응답

캐싱 제어

Cache-Control 헤더

Cache-Control 헤더 필드는 요청과 응답 양쪽에 있어 캐싱 메커니즘을 위한 디렉티브를 지정하는데 사용합니다.

// 클라이언트 요청, 서버응답 모두 저장 안함, 요청은 매번 서버로 전송되고 전체 응답은 매번 다운로드
Cache-Control: no-store
// 캐시된 복사본을 사용하지만 먼저 서버에 요청해 유효성 검사하도록 강제
Cache-Control: no-cache
// 리소스가 공개적으로 캐싱될 수 있음
Cache-Control: public
// 단일 사용자만을 위한 것이고 공유 캐시에 의해 저장되서는 안된다.
Cache-Control: private
// 유효하다고 판단되는 최대 시간
Cache-Control: max-age=31536000
// 상태를 확인하고 만료된 리소스는 사용 안함, HTTP는 특정상황에서 fresh하지 않은 데이터도 사용하는 경우가 있는데 이를 막기위해 사용
Cache-Control: must-revalidate

유효성

어떤 리소스들은 서버 상에서 변경될 수 있고 캐시가 갱신되어야 합니다. 서버는 리소스에 대한 max-age를 리턴합니다. max-age 이전의 리소스는 fresh하고, 이후의 리소스는 stale하다고 합니다. stale된 리소스에 대한 요청을 받은 경우, 이 리소스가 현재 유효한지 여부를 판단하기 위해 If-None-Match(en-US)와 함께 요청을 전달하고 서버는 304 (Not Modified) 헤더를 돌려보내 대역폭을 절약합니다. max-age는 Cache-control: max-age=N 헤더 ⇒ Expires 헤더 ⇒ Last-Modifed 헤더 순으로 결정됩니다.

ETags

Etag Response 헤더는 사용자가 알 수 없는 값으로, 리소스에 대한 응답에 포함된다면 클라이언트는 이후 Request의 헤더 안에 If-None-Match(en-US)를 줄 수 있습니다.

Last-Modified

Last-Modified Response 헤더는 약한 검증을 위해 사용됩니다. Response 내에 Last-Modified 헤더가 존재하면 클라이언트는 캐시된 문서를 검증하기 위해 if-Modified-Since Requset 헤더를 줄 수 있습니다.

versioned URL들을 위한 장기간 캐싱

fingerprint나 버전 정보가 포함된 URL을 위한 요청에 응답할 때, 그리고 컨텐츠가 변경되지 않을 거라고 예상된다면 응답에 Cache-Control: max-age=31536000 를 추가할 수 있습니다. 31,536,000초(1년)는 지원하는 최대 값입니다. 웹팩에서 아래 설정을 통해 asset의 URL에 hash fingerprint를 할당할 수 있습니다.

output: {
   // filename: 'bundle.js',
   filename: '[name].[contenthash].js',
   path: path.resolve(__dirname, 'dist'),
   clean: true,
},

파일 내용이 변경되지 않더라도 [hash]값이 변경될 수 있는데, 웹팩에서 빌드 시에 항상 초기화 코드를 포함하기 때문입니다. 웹팩에서는 runtime 코드를 분리하기 위해 optimization.runtimeChunk option을 사용할 수 있는데요. single로 설정하면 모든 chunk들을 위한 하나의 runtime 번들을 생성합니다.

optimization: {
   runtimeChunk: 'single',
 },

자세한 내용은 https://webpack.js.org/guides/caching/#output-filenames 에서 확인할 수 있습니다.

unversioned URL들을 위한 서버 재검증

모든 URL이 버전 정보를 포함할 수 없습니다. Cache-Control 값을 통해 캐시 정책을 튜닝 할 수 있습니다.

Summary

  • 캐시를 사용하면 서버의 부하를 줄이고, 성능을 높힐 수 있다.
  • GET 요청의 200 응답, 301 응답, 404 응답, 206응답을 대상으로 동작한다.
  • 버전 정보가 포함된 URL은 재검증이 필요없으므로 신뢰성과 속도를 모두 얻을 수 있다. Webpack에서 output파일에 output filename에 hash를 사용하여 최적화 할 수 있다.

Reference

https://web.dev/http-cache/#flowchart

https://developer.mozilla.org/ko/docs/Web/HTTP/Caching

'기타 > 네트워크' 카테고리의 다른 글

L4 switch L7 switch  (0) 2021.08.23
최신 메시지 큐(Messgae Queue) MQ 기술  (0) 2019.09.02

+ Recent posts