캐시가 마음에 드네요 ❤️

사이트를 두 번 로드하는 사용자는 HTTP 캐시를 사용하므로 잘 작동하는지 확인하세요.

이 게시물은 Chrome Dev Summit 2020의 확장 콘텐츠 중 하나인 캐시 사용하기 동영상의 보조 자료입니다. 다음 동영상도 확인해 보세요.

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

이 게시물에서는 합리적이고 현대적인 캐싱 기본값을 설명합니다. 이 기본값은 실제로 전혀 캐싱하지 않습니다. 하지만 이는 기본 설정일 뿐이며 물론 '사용 중지'하는 것보다 더 미묘한 차이가 있습니다. 꼭 확인해 보세요.

목표

사이트가 두 번째로 로드되는 경우 두 가지 목표가 있습니다.

  1. 사용자가 가장 최신 버전을 사용할 수 있도록 함. 변경사항이 있는 경우 신속하게 반영되어야 함
  2. 네트워크에서 최대한 적은 양을 가져오는 동안 #1을 실행합니다.

가장 넓은 의미로 말하자면, 클라이언트가 사이트를 다시 로드할 때 작은 변경사항만 전송하는 것이 좋습니다. 변경사항이 가장 효율적으로 배포되도록 사이트를 구성하는 것도 어렵습니다 (자세한 내용은 아래 및 동영상에서 확인).

그렇더라도 캐싱을 고려할 때 다른 조정 기능도 있습니다. 사이트를 게재하는 데 네트워크 요청이 전혀 필요하지 않도록 사용자의 브라우저 HTTP 캐시가 사이트를 오랫동안 유지하도록 결정할 수 있습니다. 또는 사이트가 최신 상태인지 확인하기 전에 사이트를 완전히 오프라인으로 제공하는 서비스 워커를 빌드했습니다. 이는 극단적인 옵션으로, 유효하며 많은 오프라인 우선 앱과 같은 웹 환경에 사용됩니다. 하지만 웹이 캐시 전용 극단이나 완전히 네트워크 전용 극단에 있을 필요는 없습니다.

배경

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

인터넷을 이용하는 일반 사용자들은 이러한 고급스러움을 누릴 수 없습니다. 따라서 사용자에게 두 번째 로드 시 즐거운 경험을 제공하는 것이 핵심 목표이지만 불편함을 느끼거나 중단되지 않도록 하는 것도 매우 중요합니다. (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

이 값은 1년을 초 단위로 나타낸 값입니다. 사양에 따르면 이는 실질적으로 '영원히'와 같습니다.

중요한 것은 이러한 해시를 수동으로 생성하지 마세요. 수동 작업이 너무 많습니다. Webpack, Rollup과 같은 도구를 사용하여 이 문제를 해결할 수 있습니다. 도구 보고서에서 자세히 알아보세요.

지문 URL의 이점은 JavaScript뿐만 아니라 아이콘, CSS, 기타 변경 불가능한 데이터 파일과 같은 애셋에도 적용됩니다. 사이트가 변경될 때마다 더 적은 코드를 제공할 수 있는 코드 분할에 대해 자세히 알아보려면 위의 동영상을 시청하세요.

사이트에서 캐싱을 사용하는 방식과 관계없이 이러한 종류의 지문 파일은 빌드할 모든 사이트에 매우 유용합니다. 대부분의 사이트는 새 버전이 출시될 때마다 변경되지 않습니다.

물론 index.html 파일의 이름을 index.abcd12.html로 바꾸는 방식으로 사용자에게 친숙한 페이지의 이름을 바꿀 수는 없습니다. 사이트를 로드할 때마다 사용자에게 새 URL로 이동하라고 할 수는 없으니까요. 이러한 '친숙한' URL은 이렇게 이름을 변경하거나 캐시할 수 없으므로,

중간층

캐싱에 관해서는 중간 지점을 찾을 수 있습니다. 캐시 사용 안 함영구 캐시라는 두 가지 극단적인 옵션을 제시했습니다. 또한 위에 언급한 '친숙한' URL과 같이 한동안 캐시하고 싶은 파일이 여러 개 있습니다.

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

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

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

주의한다면 영향을 받지 않을 수도 있습니다. 하지만 일반적으로 최종 사용자가 캐시하면 사이트가 더 이상 서버에만 존재하지 않는다는 점을 기억해야 합니다. 대신 최종 사용자 브라우저의 캐시 내에 조각으로 존재할 수 있습니다.

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

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

마지막으로 한 가지 더 있습니다. 뉴스 기사와 같이 일반적으로 사용자가 한 번만 액세스할 수 있는 시의적절한 콘텐츠를 만드는 경우 이러한 콘텐츠는 캐시해서는 안 되며 위의 합리적인 기본값을 사용해야 한다고 생각합니다. 뉴스 기사나 현재 이벤트의 중요한 업데이트와 같이 항상 최신 콘텐츠를 보고 싶어 하는 사용자의 욕구보다 캐싱의 가치를 과대평가하는 경우가 많습니다.

HTML 이외 옵션

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

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

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

    • 사용자는 한 기사를 몇 번 이상 방문하지 않을 가능성이 높으므로 사진이나 대표 이미지를 영구적으로 캐시하여 저장용량을 낭비하지 마세요.
  • 그 자체로 수명이 있는 것을 나타내는 애셋

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

요약

사용자가 사이트를 두 번째로 로드하면 이미 신뢰를 얻은 것입니다. 다시 방문하여 더 많은 제품을 이용하고자 하는 것입니다. 이 시점에서 로드 시간을 단축하는 것만이 능사가 아닙니다. 브라우저가 빠르고 최신 환경을 제공하는 데 필요한 작업만 실행하도록 하는 다양한 옵션을 사용할 수 있습니다.

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

참고 항목

HTTP 캐시에 대한 일반 가이드는 HTTP 캐시를 사용하여 불필요한 네트워크 요청 방지를 참조하세요.