캐시가 마음에 드네요 ❤️

사이트를 두 번 로드하는 사용자는 HTTP 캐시를 사용하므로 제대로 작동하는지 확인해야 합니다.

이 게시물은 Chrome Dev Summit 2020의 확장 콘텐츠 중 일부인 Love your cache 동영상의 보조 자료입니다. 다음 동영상을 확인하세요.

사용자가 사이트를 다시 로드하면 브라우저에서 HTTP 캐시 내의 리소스를 사용하여 로드 속도를 높입니다. 하지만 웹에서 캐싱하는 표준은 1999년으로 거슬러 올라가며 상당히 광범위하게 정의되어 있습니다. CSS 또는 이미지와 같은 파일을 네트워크에서 다시 가져올 수 있는지 아니면 캐시에서 로드하는지 여부를 결정하는 것은 다소 부정확한 과학입니다.

이 게시물에서는 실제로 캐싱을 전혀 하지 않는 합리적이고 현대적인 캐싱 기본값에 관해 설명합니다. 하지만 이는 기본값일 뿐이며 물론 '끄기'보다 더 복잡합니다. 꼭 확인해 보세요.

목표

사이트가 두 번째로 로드되면 다음과 같은 두 가지 목표가 있습니다.

  1. 사용자가 사용할 수 있는 가장 최신 버전을 사용할 수 있도록 합니다. 변경 사항이 있는 경우 신속하게 반영되어야 합니다.
  2. 첫 번째 작업으로 네트워크에서 최대한 적게 가져오기

즉, 고객이 사이트를 다시 로드할 때 가장 작은 변경사항만 전송하는 것이 좋습니다. 또한 모든 변경사항을 가장 효율적으로 배포하도록 사이트를 구성하는 것은 쉬운 일이 아닙니다 (자세한 내용은 아래 동영상 참조).

하지만 캐싱을 고려할 때 다른 노브도 있습니다. 아마도 사용자의 브라우저 HTTP 캐시가 사이트에 오랫동안 유지되도록 하여 네트워크 요청이 전혀 제공되지 않도록 하기로 했을 수 있습니다. 또는 사이트가 최신 상태인지 확인하기 전에 완전히 오프라인으로 사이트를 제공하는 서비스 워커를 구축했습니다. 이는 극단적인 옵션으로 유효하며 오프라인 우선 앱과 같은 많은 웹 환경에 사용됩니다. 하지만 웹이 캐시 전용 극단적일 필요는 없으며 심지어는 완전히 네트워크 전용 극단일 필요도 없습니다.

배경

웹 개발자라면 모두 '오래된 캐시'가 있다는 아이디어에 익숙합니다. 하지만 Google은 이 문제를 해결하는 데 사용할 수 있는 도구를 거의 본능적으로 알고 있습니다. '기기 새로고침', 시크릿 창 열기, 브라우저의 개발자 도구 조합을 사용하여 사이트 데이터를 지우는 도구 등을 예로 들 수 있습니다.

인터넷의 일반 사용자에게는 이와 같은 사치품이 없습니다. 따라서 사용자가 두 번째 로드로 즐거운 시간을 보내도록 하는 핵심 목표가 있지만, 사용자가 불편한 시간을 갖지 않도록 하거나 막히지 않도록 하는 것도 중요합니다. web.dev/live 사이트가 어떻게 막히게 되었는지 알아보려면 동영상을 시청하세요.

'오래된 캐시'의 가장 일반적인 이유는 실제로는 1999년의 캐싱 기본값입니다. Last-Modified 헤더를 사용합니다.

사용자의 브라우저에서 여러 애셋이 캐시되는 기간을 보여주는 다이어그램
서로 다른 시간 (회색)에 생성된 애셋은 서로 다른 시간에 캐시되므로 두 번째 로드 시 캐시된 애셋과 새로운 애셋을 조합하여 가져올 수 있습니다.

로드하는 모든 파일은 브라우저에서 인식하는 대로 현재 수명 중 추가로 10% 동안 보관됩니다. 예를 들어 index.html가 한 달 전에 생성된 경우 브라우저에서 약 3일 동안 캐시됩니다.

과거에는 좋은 생각이었지만 오늘날 웹사이트의 밀접하게 통합된 특성을 고려할 때 이 기본 동작은 사용자가 웹사이트의 여러 출시에 맞게 설계된 파일 (예: 화요일 출시의 JS, 금요일 버전의 CSS)이 있는 상태가 될 수 있음을 의미합니다. 이 모든 파일은 정확히 동시에 업데이트되지 않았기 때문입니다.

조명이 밝은 오솔길

현대적인 캐싱 기본값은 실제로는 캐싱을 전혀 하지 않고 CDN을 사용하여 콘텐츠를 사용자에게 가깝게 제공하는 것입니다. 사용자는 사이트를 로드할 때마다 네트워크로 이동하여 사이트가 최신 버전인지 확인합니다. 이 요청은 지리적으로 각 최종 사용자와 가까운 CDN에서 제공되므로 지연 시간이 짧습니다.

다음 헤더로 웹 요청에 응답하도록 웹 호스트를 구성할 수 있습니다.

Cache-Control: max-age=0,must-revalidate,public

기본적으로는 파일이 아무 시간도 유효하지 않으므로 다시 사용하려면 네트워크에서 유효성을 검사해야 합니다 (그렇지 않으면'제안됨'일 뿐').

이 유효성 검사 프로세스는 전송되는 바이트 면에서 비교적 저렴합니다. 대용량 이미지 파일이 변경되지 않은 경우 브라우저에 304 응답이 적게 수신되지만 사용자가 이를 찾으려면 여전히 네트워크로 이동해야 하므로 지연 시간이 발생합니다. 그리고 이것이 이 접근 방식의 가장 큰 단점입니다. 첫 번째 세계의 고속 인터넷 연결을 사용하거나 선택한 CDN의 노출 범위가 넓은 사용자에게는 효과적일 수 있지만 모바일 연결이 느리거나 인프라가 열악한 사용자에게는 적합하지 않습니다.

그럼에도 불구하고 이는 인기 있는 CDN인 Netlify의 기본값인 현대적인 접근 방식이지만 거의 모든 CDN에서 구성할 수 있습니다. Firebase 호스팅의 경우 firebase.json 파일의 호스팅 섹션에 다음 헤더를 포함할 수 있습니다.

"headers": [
  // Be sure to put this last, to not override other headers
  {
    "source": "**",
    "headers": [ {
      "key": "Cache-Control",
      "value": "max-age=0,must-revalidate,public"
    }
  }
]

따라서 여전히 합리적인 기본값을 제안합니다. 계속 읽으면서 기본값을 업그레이드하고 업그레이드하는 방법을 알아보세요.

디지털 지문이 포함된 URL

사이트에서 제공되는 애셋, 이미지 등의 이름에 파일 콘텐츠의 해시를 포함하면 이러한 파일에 항상 고유한 콘텐츠가 있도록 할 수 있습니다. 예를 들어 sitecode.af12de.js라는 파일이 생성됩니다. 서버가 이러한 파일의 요청에 응답하면 다음 헤더로 파일을 구성하여 최종 사용자의 브라우저가 파일을 오랫동안 캐시하도록 안전하게 지시할 수 있습니다.

Cache-Control: max-age=31536000,immutable

이 값은 연도(초)입니다. 사양에 따르면 이는 사실상 'forever'와 같습니다.

너무 많은 수동 작업이 필요하므로 이러한 해시를 수동으로 생성하지 않는 것이 중요합니다. Webpack, Rollup과 같은 도구를 사용하여 이를 해결할 수 있습니다. 자세한 내용은 도구 보고서를 참고하세요.

디지털 지문 URL의 이점을 누릴 수 있는 것은 JavaScript만이 아닙니다. 아이콘, CSS, 기타 변경할 수 없는 데이터 파일과 같은 애셋도 이러한 방식으로 이름을 지정할 수 있습니다. (위 동영상에서 코드 분할에 대해 자세히 알아보세요. 코드 분할을 사용하면 사이트가 변경될 때마다 코드를 적게 전송할 수 있습니다.)

사이트가 캐싱에 접근하는 방식과 관계없이 이러한 종류의 디지털 지문 파일은 빌드하는 모든 사이트에 매우 유용합니다. 대부분의 사이트는 새 버전이 출시될 때마다 바뀌지 않습니다.

물론 '친숙한' 사용자 대상 페이지의 이름을 이러한 방식으로 바꿀 수는 없습니다. index.html 파일의 이름을 index.abcd12.html로 바꾸는 것은 불가능합니다. 이렇게 하는 것은 사용자가 사이트를 로드할 때마다 새 URL로 이동하라고 지시할 수는 없습니다. 이러한 '알기 쉬운' URL은 이런 방식으로 이름을 바꾸고 캐시할 수 없으므로 가능한 중간 지점으로 연결할 수 있습니다.

중간 지점

캐싱에 관해서는 중간 지점의 여지가 분명히 있습니다. 캐시 사용 안 함영구적으로 캐시하는 두 가지 극단적인 옵션을 제시했습니다. 위에서 언급한 '알기 쉬운' URL과 같이 한동안 캐시에 저장하고 싶은 파일도 많이 있습니다.

이러한 '친숙한' URL과 HTML을 캐시하려면 포함된 종속 항목이 무엇인지, URL이 캐시되는 방식, 일정 시간 동안 URL을 캐시하면 어떤 영향을 미치는지 고려해야 합니다. 다음과 같은 이미지가 포함된 HTML 페이지를 살펴보겠습니다.

<img src="/images/foo.jpeg" loading="lazy" />

지연 로드 이미지를 삭제하거나 변경하여 사이트를 업데이트하거나 변경하면 캐시된 버전의 HTML을 보는 사용자가 사이트를 다시 방문할 때 여전히 원래 /images/foo.jpeg를 캐시했기 때문에 잘못되거나 누락된 이미지가 표시될 수 있습니다.

조심한다면 이로 인해 영향을 받지 않을 수도 있습니다. 하지만 최종 사용자가 캐시한 사이트는 더 이상 내 서버에만 존재하지 않는다는 사실을 명심해야 합니다. 최종 사용자 브라우저 캐시 내부의 조각에 존재할 수 있습니다.

일반적으로 캐싱에 관한 대부분의 가이드에서는 이러한 종류의 설정에 대해 설명합니다. 한 시간, 몇 시간 등을 캐시하시겠습니까? 이러한 종류의 캐시를 설정하려면 다음과 같은 헤더를 사용하세요 (3,600초 또는 1시간 동안 캐시됨).

Cache-Control: max-age=3600,immutable,public

마지막 질문입니다. 일반적으로 사용자가 한 번만 액세스할 수 있는 시의적절한 콘텐츠(예: 뉴스 기사)를 만드는 경우라면 이러한 콘텐츠는 캐시되면 안 되며 위의 적절한 기본값을 사용해야 한다고 생각합니다. 저는 뉴스 기사나 시사에 관한 중요한 업데이트와 같이 항상 유용한 최신 콘텐츠를 보고 싶다는 사용자의 욕구보다 캐싱의 가치를 종종 과대평가한다고 생각합니다.

HTML이 아닌 옵션

HTML 외에 중간 부분에 있는 파일의 다른 옵션은 다음과 같습니다.

  • 일반적으로 다른 애셋에 영향을 미치지 않는 애셋을 찾습니다.

    • 예를 들어 CSS는 HTML이 렌더링되는 방식을 변경하므로 사용하지 마세요.
  • 시의적절한 기사의 일부로 사용되는 큰 이미지

    • 사용자는 기사를 한 번도 방문하지 않을 것이므로 사진이나 히어로 이미지를 영원히 캐시하지 않고 저장용량을 낭비하지 마세요.
  • 그 자체로 평생 가치가 있는 것을 나타내는 애셋

    • 날씨에 관한 JSON 데이터는 1시간마다 게시될 수 있으므로 이전 결과를 한 시간 동안 캐시할 수 있습니다(창에서 변경되지 않음).
    • 오픈소스 프로젝트의 빌드는 속도가 제한될 수 있으므로 상태가 변경될 수 있을 때까지 빌드 상태 이미지를 캐시합니다.

요약

사용자가 사이트를 두 번째로 로드하면 확신을 갖게 됩니다. 사용자는 사이트를 다시 방문하여 제공하는 제품 또는 서비스를 더 많이 얻기를 원합니다. 이 시점에서는 로드 시간을 줄이는 것만으로는 충분하지 않으며, 브라우저에서 빠른 환경과 최신 환경을 모두 제공하는 데 필요한 작업만 수행하도록 할 수 있는 다양한 옵션이 있습니다.

캐싱은 웹에서 새로운 개념은 아니지만 아마도 합리적인 기본값이 필요할 수 있습니다. 필요할 때 더 나은 캐싱 전략을 사용하도록 적극 선택하는 것이 좋습니다. 읽어주셔서 감사합니다.

참고 항목

HTTP 캐시에 관한 일반 가이드는 HTTP 캐시로 불필요한 네트워크 요청 방지를 참고하세요.