제공 중

프로그레시브 웹 앱의 주요 특징은 안정성입니다. 자산을 빠르게 로드하여 사용자의 참여를 유도하고 네트워크 상태가 좋지 않은 경우에도 즉시 피드백을 제공할 수 있다는 점입니다. 어떻게 이런 일이 가능한가요? 서비스 워커 fetch 이벤트 덕분에

가져오기 이벤트

브라우저 지원

  • 40
  • 17
  • 44
  • 11.1

소스

fetch 이벤트를 사용하면 동일 출처 및 교차 출처 요청에 대해 서비스 워커 범위에서 PWA가 수행한 모든 네트워크 요청을 가로챌 수 있습니다. 탐색 및 자산 요청 외에도 설치된 서비스 워커에서 가져오기를 수행하면 사이트가 처음 로드된 후 네트워크 호출 없이 페이지 방문이 렌더링될 수 있습니다.

fetch 핸들러는 URL과 HTTP 헤더를 포함한 앱의 모든 요청을 수신하고 앱 개발자가 처리 방법을 결정할 수 있도록 합니다.

서비스 워커는 클라이언트와 네트워크 사이에 위치합니다.

서비스 워커는 요청을 네트워크에 전달하거나, 이전에 캐시된 응답으로 응답하거나, 또는 새로운 응답을 생성할 수 있습니다. 원하는 대로 선택하면 됩니다. 다음 예를 참조하세요.

self.addEventListener("fetch", event => {
    console.log(`URL requested: ${event.request.url}`);
});

요청에 응답

서비스 워커에 요청이 들어오면 두 가지 조치를 취할 수 있습니다. 요청을 무시하여 네트워크로 이동하거나 응답할 수 있습니다. 서비스 워커 내에서 요청에 응답하면 사용자가 오프라인일 때도 무엇을 어떻게 PWA로 반환할지 선택할 수 있습니다.

수신 요청에 응답하려면 다음과 같이 fetch 이벤트 핸들러에서 event.respondWith()를 호출합니다.

// fetch event handler in your service worker file
self.addEventListener("fetch", event => {
    const response = .... // a response or a Promise of response
    event.respondWith(response);
});

respondWith()를 동기식으로 호출해야 하며 Response 객체를 반환해야 합니다. 그러나 비동기 호출 내에서와 같이 가져오기 이벤트 핸들러가 완료된 후에는 respondWith()를 호출할 수 없습니다. 완전한 응답을 기다려야 하는 경우 응답으로 확인되는 프로미스를 respondWith()에 전달할 수 있습니다.

응답 만들기

Fetch API를 사용하면 자바스크립트 코드에서 HTTP 응답을 만들 수 있으며 이러한 응답은 Cache Storage API를 사용하여 캐시하고 웹 서버에서 온 것처럼 반환할 수 있습니다.

응답을 만들려면 새 Response 객체를 만들고 본문과 옵션(예: 상태, 헤더)을 설정합니다.

const simpleResponse = new Response("Body of the HTTP response");

const options = {
   status: 200,
   headers: {
    'Content-type': 'text/html'
   }
};
const htmlResponse = new Response("<b>HTML</b> content", options)

캐시에서 응답

서비스 워커에서 HTTP 응답을 제공하는 방법을 알았으니 이제 캐싱 스토리지 인터페이스를 사용하여 기기에 애셋을 저장할 차례입니다.

Cache Storage API를 사용하면 PWA에서 수신된 요청을 캐시에서 사용할 수 있는지 확인하고 사용할 수 있는 경우 respondWith()에 응답할 수 있습니다. 이렇게 하려면 먼저 캐시 내에서 검색해야 합니다. 최상위 caches 인터페이스에서 사용할 수 있는 match() 함수는 원본 또는 단일 열린 캐시 객체에서 모든 저장소를 검색합니다.

match() 함수는 HTTP 요청 또는 URL을 인수로 수신하고 해당 키와 연결된 응답으로 결정되는 프로미스를 반환합니다.

// Global search on all caches in the current origin
caches.match(urlOrRequest).then(response => {
   console.log(response ? response : "It's not in the cache");
});

// Cache-specific search
caches.open("pwa-assets").then(cache => {
  cache.match(urlOrRequest).then(response => {
    console.log(response ? response : "It's not in the cache");
  });
});

캐싱 전략

브라우저 캐시에서만 파일을 제공하는 것이 모든 사용 사례에 적합한 것은 아닙니다. 예를 들어 사용자 또는 브라우저가 캐시를 제거할 수 있습니다. 따라서 PWA에 사용할 애셋을 전송하기 위한 전략을 직접 정의해야 합니다. 하나의 캐싱 전략만 사용할 필요가 없습니다. 여러 URL 패턴에 대해 서로 다른 URL을 정의할 수 있습니다. 예를 들어 최소 UI 애셋에 대한 전략, API 호출을 위한 전략, 이미지 및 데이터 URL을 위한 전략 하나를 사용할 수 있습니다. 이렇게 하려면 ServiceWorkerGlobalScope.onfetch에서 event.request.url를 읽고 정규 표현식 또는 URL 패턴을 통해 파싱합니다. 이 문서의 작성 현재, 일부 플랫폼에서는 URL 패턴이 지원되지 않습니다.

가장 일반적인 전략은 다음과 같습니다.

캐시 우선
캐시된 응답을 먼저 검색하고 응답을 찾지 못한 경우 네트워크로 대체합니다.
네트워크 우선
네트워크에 먼저 응답을 요청하고 응답이 없으면 캐시에서 응답을 확인합니다.
재확인 중 비활성
캐시에서 응답을 제공하고 백그라운드에서 최신 버전을 요청하고 다음번에 애셋이 요청될 때 사용할 수 있도록 캐시에 저장합니다.
네트워크 전용
항상 네트워크로부터 응답을 받거나 오류가 발생한 경우 응답합니다. 캐시는 참조되지 않습니다.
캐시 전용
항상 캐시의 응답으로 응답하거나 오류가 있는 경우 응답합니다. 네트워크는 참조되지 않습니다. 이 전략을 사용하여 게재되는 애셋은 요청 전에 캐시에 추가되어야 합니다.

캐시 우선

이 전략을 사용하면 서비스 워커는 캐시에서 일치하는 요청을 찾고, 캐시된 경우 해당 응답을 반환합니다. 그렇지 않으면 네트워크에서 응답을 검색합니다 (선택적으로 향후 호출을 위해 캐시를 업데이트). 캐시 응답이나 네트워크 응답이 모두 없으면 요청에서 오류가 발생합니다. 네트워크로 이동하지 않고 애셋을 게재하는 것이 더 빠른 경향이 있으므로 이 전략은 최신 상태보다 실적에 우선 순위를 둡니다.

캐시 우선 전략

self.addEventListener("fetch", event => {
   event.respondWith(
     caches.match(event.request)
     .then(cachedResponse => {
       // It can update the cache to serve updated content on the next request
         return cachedResponse || fetch(event.request);
     }
   )
  )
});

네트워크 우선

이 전략은 캐시 우선 전략을 반영하며, 네트워크에서 요청을 처리할 수 있는지 확인하고 처리할 수 없는 경우 캐시에서 요청을 검색하려고 시도합니다. 캐시가 우선입니다. 네트워크 응답도 캐시 응답도 없으면 요청에서 오류가 발생합니다. 네트워크에서 응답을 가져오는 것은 일반적으로 캐시에서 응답을 가져오는 것보다 느립니다. 이 전략은 성능 대신 업데이트된 콘텐츠에 우선 순위를 둡니다.

네트워크 우선 전략

self.addEventListener("fetch", event => {
   event.respondWith(
     fetch(event.request)
     .catch(error => {
       return caches.match(event.request) ;
     })
   );
});

재확인 중 비활성

재확인 전략은 캐시된 응답을 즉시 반환한 다음 네트워크에 업데이트가 있는지 확인하여 캐시된 응답이 있는 경우 이를 대체합니다. 이 전략은 항상 네트워크 요청을 수행합니다. 캐시된 리소스가 있는 경우에도 네트워크에서 수신한 항목으로 캐시에 있던 항목을 업데이트하여 다음 요청에서 업데이트된 버전을 사용하기 때문입니다. 따라서 이 전략은 캐시 우선 전략의 빠른 제공을 활용하고 백그라운드에서 캐시를 업데이트할 수 있는 방법을 제공합니다.

재검증 전략 중 오래된 비활성

self.addEventListener('fetch', event => {
  event.respondWith(
    caches.match(event.request).then(cachedResponse => {
        const networkFetch = fetch(event.request).then(response => {
          // update the cache with a clone of the network response
          const responseClone = response.clone()
          caches.open(url.searchParams.get('name')).then(cache => {
            cache.put(event.request, responseClone)
          })
          return response
        }).catch(function (reason) {
          console.error('ServiceWorker fetch failed: ', reason)
        })
        // prioritize cached response over network
        return cachedResponse || networkFetch
      }
    )
  )
})

네트워크 전용

네트워크 전용 전략은 브라우저가 서비스 워커 또는 Cache Storage API 없이 작동하는 방식과 유사합니다. 요청에서 리소스를 네트워크에서 가져올 수 있는 경우에만 리소스를 반환합니다. 이 방식은 온라인 전용 API 요청과 같은 리소스에 유용한 경우가 많습니다.

네트워크 전용 전략

캐시 전용

캐시 전용 전략은 요청이 네트워크로 이동하지 않도록 합니다. 수신되는 모든 요청은 미리 채워진 캐시 항목으로 응답하게 됩니다. 다음 코드는 fetch 이벤트 핸들러와 캐시 저장소의 match 메서드를 사용하여 캐시에만 응답합니다.

self.addEventListener("fetch", event => {
   event.respondWith(caches.match(event.request));
});

캐시 전용 전략

맞춤 전략

위에서 설명한 것은 일반적인 캐싱 전략이지만, 서비스 워커와 요청 처리 방식을 직접 관리해야 합니다. 이 중에서 원하는 것이 없으면 직접 만드세요.

예를 들어 시간 제한이 있는 네트워크 우선 전략을 사용하여 업데이트된 콘텐츠에 우선순위를 지정할 수 있지만 이는 응답이 설정한 기준점 내에 표시되는 경우에만 가능합니다. 또한 캐시된 응답을 네트워크 응답과 병합하여 서비스 워커로부터 복잡한 응답을 작성할 수도 있습니다.

저작물 업데이트 중

PWA의 캐시된 애셋을 최신 상태로 유지하기란 어려울 수 있습니다. 재검증 전략 중 부실이 이를 수행하는 한 가지 방법이지만 유일한 방법은 아닙니다. 업데이트 챕터에서는 앱의 콘텐츠와 애셋을 최신 상태로 유지하는 다양한 기법을 알아봅니다.

자료