사이트를 두 번 로드하는 사용자는 HTTP 캐시를 사용하므로 잘 작동하는지 확인하세요.
이 게시물은 Chrome Dev Summit 2020의 확장 콘텐츠 중 하나인 캐시 사용하기 동영상의 보조 자료입니다. 동영상을 확인하세요.
사용자가 사이트를 두 번째로 로드하면 브라우저는 HTTP 캐시 내의 리소스를 사용하여 로드 속도를 높입니다. 하지만 웹 캐싱 표준은 1999년에 시작되었으며 매우 광범위하게 정의되어 있습니다. CSS나 이미지와 같은 파일을 네트워크에서 다시 가져올지 아니면 캐시에서 로드할지 결정하는 것은 약간 부정확한 과학입니다.
이 게시물에서는 합리적이고 현대적인 캐싱 기본값을 설명합니다. 이 기본값은 실제로 전혀 캐싱하지 않습니다. 하지만 이는 기본 설정일 뿐이며 물론 '사용 중지'하는 것보다 더 미묘한 차이가 있습니다. 꼭 확인해 보세요.
목표
사이트가 두 번째로 로드되면 다음 두 가지 목표가 있습니다.
- 사용자가 가장 최신 버전을 사용할 수 있도록 함. 변경사항이 있는 경우 신속하게 반영되어야 함
- 네트워크에서 가능한 한 적게 가져오는 동안 첫 번째 수행
가장 넓은 의미로 말하자면, 클라이언트가 사이트를 다시 로드할 때 작은 변경사항만 전송하는 것이 좋습니다. 또한 변경사항을 가장 효율적으로 배포할 수 있도록 사이트를 구성하는 것은 쉽지 않습니다(아래 및 동영상에서 자세히 알아보기).
그렇더라도 캐싱을 고려할 때 다른 조정 기능도 있습니다. 사이트를 게재하는 데 네트워크 요청이 전혀 필요하지 않도록 사용자의 브라우저 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 캐시를 이용한 불필요한 네트워크 요청 예방을 참고하세요.