캐싱

캐시 스토리지는 강력한 도구입니다. 네트워크 상태에 대한 앱의 영향을 줄일 수 있습니다. 캐시를 잘 사용하면 웹 앱을 오프라인에서 사용할 수 있도록 하고 어떤 네트워크 조건에서든 가능한 한 빠르게 자산을 제공할 수 있습니다. 애셋 및 데이터에서 설명한 것처럼 필요한 애셋을 캐싱하기 위한 최상의 전략을 결정할 수 있습니다. 캐시를 관리하기 위해 서비스 워커는 Cache Storage API와 상호작용합니다.

브라우저 지원

  • Chrome: 43. <ph type="x-smartling-placeholder">
  • Edge: 16. <ph type="x-smartling-placeholder">
  • Firefox: 41. <ph type="x-smartling-placeholder">
  • Safari: 11.1. <ph type="x-smartling-placeholder">

소스

Cache Storage API는 다음과 같이 다양한 컨텍스트에서 사용할 수 있습니다.

  • 창 컨텍스트 (PWA의 기본 스레드)
  • 서비스 워커
  • 사용하는 다른 모든 작업자.

서비스 워커를 사용하여 캐시를 관리할 경우의 한 가지 이점은 수명 주기가 창에 연결되지 않아 메인 스레드를 차단하지 않는다는 것입니다. Cache Storage API를 사용하려면 이러한 컨텍스트 대부분이 TLS 연결을 사용해야 합니다.

캐시할 콘텐츠

캐싱에 대해 가장 먼저 생각할 수 있는 질문은 무엇을 캐시할지입니다. 이 질문에 대한 한 가지 답변은 없지만, 사용자 인터페이스를 렌더링하는 데 필요한 모든 최소한의 리소스부터 시작할 수 있습니다.

이러한 리소스에는 다음이 포함되어야 합니다.

  • 기본 페이지 HTML (앱의 start_url)입니다.
  • 기본 사용자 인터페이스에 필요한 CSS 스타일시트.
  • 사용자 인터페이스에서 사용되는 이미지
  • 사용자 인터페이스를 렌더링하는 데 필요한 JavaScript 파일입니다.
  • 기본 환경을 렌더링하는 데 필요한 데이터(예: JSON 파일)
  • 웹 글꼴
  • 다중 페이지 애플리케이션에서 빠르게 또는 오프라인으로 제공하려는 기타 HTML 문서
를 통해 개인정보처리방침을 정의할 수 있습니다.

오프라인 지원

오프라인 기능이 지원되는 것이 프로그레시브 웹 앱의 요구사항 중 하나이기는 하지만, 모든 PWA에 완전한 오프라인 환경(예: 클라우드 게임 솔루션 또는 암호화폐 자산 앱)이 필요한 것은 아니라는 점을 이해해야 합니다. 따라서 사용자에게 이러한 상황을 안내하는 기본 사용자 인터페이스를 제공하는 것은 괜찮습니다.

PWA는 웹 렌더링 엔진이 페이지를 로드할 수 없다는 브라우저의 오류 메시지를 렌더링해서는 안 됩니다. 그 대신, 서비스 워커를 사용하여 자신의 메시지를 표시하고, 일반적이고 혼동을 주는 브라우저 오류를 피합니다.

PWA의 요구사항에 따라 다양한 캐싱 전략을 사용할 수 있습니다. 따라서 빠르고 안정적인 환경을 제공하도록 캐시 사용을 설계하는 것이 중요합니다. 예를 들어 모든 앱 애셋이 빠르게 다운로드되고, 공간을 많이 소비하지 않으며, 모든 요청에서 업데이트할 필요가 없는 경우, 모든 애셋을 캐시하는 것은 유효한 전략입니다. 반면에 최신 버전이어야 하는 리소스가 있으면 해당 애셋을 전혀 캐시하지 않는 것이 좋습니다.

API 사용

Cache Storage API를 사용하여 원본 내의 캐시 집합을 정의합니다. 각 캐시는 사용자가 정의할 수 있는 문자열 이름으로 식별됩니다. caches 객체를 통해 API에 액세스하면 open 메서드를 사용하여 이미 생성된 캐시를 만들거나 열 수 있습니다. open 메서드는 캐시 객체에 대한 프로미스를 반환합니다.

caches.open("pwa-assets")
.then(cache => {
  // you can download and store, delete or update resources with cache arguments
});

애셋 다운로드 및 저장

애셋을 다운로드하고 저장하도록 브라우저에 요청하려면 add 또는 addAll 메서드를 사용하세요. add 메서드는 요청을 실행하고 하나의 HTTP 응답을 저장하고 addAll는 요청 또는 URL 배열을 기반으로 HTTP 응답 그룹을 트랜잭션으로 저장합니다.

caches.open("pwa-assets")
.then(cache => {
  cache.add("styles.css"); // it stores only one resource
  cache.addAll(["styles.css", "app.js"]); // it stores two resources
});
드림

캐시 저장소 인터페이스는 모든 헤더와 본문을 포함하여 응답 전체를 저장합니다. 따라서 나중에 HTTP 요청 또는 URL을 키로 사용하여 검색할 수 있습니다. 이를 수행하는 방법은 서빙 챕터에서 확인할 수 있습니다.

캐시하는 경우

PWA에서는 파일을 캐시할 시기를 결정해야 합니다. 한 가지 접근 방식은 서비스 워커가 설치될 때 최대한 많은 애셋을 저장하는 것이지만, 일반적으로 가장 좋은 방법은 아닙니다. 불필요한 리소스를 캐시하면 대역폭과 저장공간이 낭비되고 앱에서 의도하지 않은 오래된 리소스를 제공할 수 있습니다.

모든 애셋을 한 번에 캐시할 필요는 없으며, 다음과 같이 PWA의 수명 주기 동안 애셋을 여러 번 캐시할 수 있습니다.

  • 서비스 워커 설치 시
  • 첫 페이지 로드 후
  • 사용자가 섹션 또는 경로로 이동할 때
  • 네트워크가 유휴 상태인 경우

기본 스레드 또는 서비스 워커 컨텍스트 내에서 새 파일의 캐싱을 요청할 수 있습니다.

서비스 워커에서 애셋 캐싱

가장 일반적인 시나리오 중 하나는 서비스 워커가 설치될 때 최소한의 자산 집합을 캐시하는 것입니다. 이를 위해 서비스 워커의 install 이벤트 내에서 캐시 스토리지 인터페이스를 사용하면 됩니다.

서비스 워커 스레드는 언제든지 중지할 수 있으므로 addAll 프로미스가 완료될 때까지 기다리도록 브라우저에 요청하여 모든 애셋을 저장하고 앱을 일관성 있게 유지할 수 있는 기회를 늘릴 수 있습니다. 다음 예에서는 서비스 워커 이벤트 리스너에 수신된 이벤트 인수의 waitUntil 메서드를 사용하여 이를 수행하는 방법을 보여줍니다.

const urlsToCache = ["/", "app.js", "styles.css", "logo.svg"];
self.addEventListener("install", event => {
   event.waitUntil(
      caches.open("pwa-assets")
      .then(cache => {
         return cache.addAll(urlsToCache);
      });
   );
});

waitUntil() 메서드는 프로미스를 수신하고 서비스 워커 프로세스를 종료하기 전에 프로미스의 작업이 해결 (처리 또는 실패)될 때까지 기다리도록 브라우저에 요청합니다. 단일 결과가 waitUntil() 메서드에 도달하도록 프로미스를 체인으로 연결하고 add() 또는 addAll() 호출을 반환해야 할 수도 있습니다.

async/await 구문을 사용하여 프로미스를 처리할 수도 있습니다. 이 경우 다음 예와 같이 await를 호출할 수 있고 호출된 후 waitUntil()에 프로미스를 반환하는 비동기 함수를 만들어야 합니다.

const urlsToCache = ["/", "app.js", "styles.css", "logo.svg"];
self.addEventListener("install", (event) => {
   let cacheUrls = async () => {
      const cache = await caches.open("pwa-assets");
      return cache.addAll(urlsToCache);
   };
   event.waitUntil(cacheUrls());
});

교차 도메인 요청 및 불투명 응답

PWA는 서드 파티 CDN의 콘텐츠와 같은 원본 및 교차 도메인의 애셋을 다운로드하고 캐시할 수 있습니다. 교차 도메인 앱에서 캐시 상호작용은 동일 출처 요청과 매우 유사합니다. 요청이 실행되고 응답 사본이 캐시에 저장됩니다. 캐시된 다른 애셋과 마찬가지로, 앱의 원본에서만 사용할 수 있습니다.

애셋은 불투명 응답으로 저장됩니다. 즉, 코드에서 해당 응답의 콘텐츠나 헤더를 보거나 수정할 수 없습니다. 또한 불투명 응답은 Storage API의 실제 크기를 노출하지 않으므로 할당량에 영향을 미칩니다. 일부 브라우저는 파일이 1Kb에 불과한지 여부에 상관없이 7Mb와 같은 큰 크기를 표시합니다.

애셋 업데이트 및 삭제

cache.put(request, response)를 사용하여 애셋을 업데이트하고 delete(request)로 애셋을 삭제할 수 있습니다.

자세한 내용은 캐시 객체 문서를 참고하세요.

캐시 저장소 디버깅

대부분의 브라우저는 DevTools Application 탭 내에서 캐시 저장소의 콘텐츠를 디버그하는 방법을 제공합니다. 여기에서 현재 원본 내에 있는 모든 캐시의 콘텐츠를 볼 수 있습니다. 이러한 도구에 관해서는 도구 및 디버그 장에서 자세히 다루겠습니다.

캐시 저장소 콘텐츠를 디버깅하는 Chrome DevTools

리소스