지금까지는
Cache
인터페이스.
서비스 워커를 효과적으로 사용하려면 하나 이상의 캐싱 전략을 채택해야 합니다.
Cache
인터페이스를 어느 정도 숙지해야 합니다.
캐싱 전략은 서비스 워커의 fetch
이벤트와 Cache
인터페이스 간의 상호작용입니다.
캐싱 전략을 작성하는 방법은 다음과 같습니다.
예를 들어 정적 애셋에 대한 요청을 문서와 다른 방식으로 처리하는 것이
이는 캐싱 전략이 구성되는 방식에 영향을 미칩니다.
본격적으로 시작하기 전에
잠시 시간을 내어 Cache
인터페이스가 무엇이고, 무엇이고,
그리고 서비스 워커 캐시를 관리하기 위해 제공하는 몇 가지 메서드에 대한 간단한 설명을 제공합니다.
Cache
인터페이스와 HTTP 캐시 비교
이전에 Cache
인터페이스를 사용한 적이 없다면
그것을 다음과 같이 생각하고 싶을 수 있습니다.
적어도 HTTP 캐시와 관련이 있어야 합니다. 호출은 건너뛸 수 없습니다.
Cache
인터페이스는 HTTP 캐시와 완전히 분리된 캐싱 메커니즘입니다.Cache-Control
HTTP 캐시에 영향을 주기 위해 사용하는 구성은Cache
인터페이스에 저장되는 애셋에 영향을 미치지 않습니다.
브라우저 캐시는 계층화된 것으로 생각하는 것이 좋습니다. HTTP 캐시는 HTTP 헤더에 표현된 지시문을 포함하는 키-값 쌍에 의해 구동되는 하위 수준 캐시입니다.
반면에 Cache
인터페이스는 JavaScript API로 구동되는 상위 수준 캐시입니다.
이렇게 하면 비교적 단순한 HTTP 키-값 쌍을 사용할 때보다 유연성이 높아지며,
캐싱 전략을 가능하게 만드는 요소 중 절반입니다.
서비스 워커 캐시와 관련된 몇 가지 중요한 API 메서드는 다음과 같습니다.
CacheStorage.open
드림 새Cache
인스턴스를 만듭니다.Cache.add
드림 및Cache.put
서비스 워커 캐시에 저장할 수 있습니다.Cache.match
드림Cache
인스턴스에서 캐시된 응답을 찾습니다.Cache.delete
드림Cache
인스턴스에서 캐시된 응답을 삭제합니다.
예시는 극히 일부에 불과합니다. 다른 유용한 메서드도 있지만 이 가이드의 뒷부분에서 사용하게 될 기본적인 것들입니다.
소박한 fetch
이벤트
캐싱 전략의 나머지 절반은 서비스 워커의
fetch
이벤트를 호출합니다.
지금까지 이 문서에서는 '네트워크 요청 가로채기'에 대해 알아봤습니다.
서비스 워커 내부의 fetch
이벤트에서 다음과 같은 일이 발생합니다.
// Establish a cache name
const cacheName = 'MyFancyCacheName_v1';
self.addEventListener('install', (event) => {
event.waitUntil(caches.open(cacheName));
});
self.addEventListener('fetch', async (event) => {
// Is this a request for an image?
if (event.request.destination === 'image') {
// Open the cache
event.respondWith(caches.open(cacheName).then((cache) => {
// Respond with the image from the cache or from the network
return cache.match(event.request).then((cachedResponse) => {
return cachedResponse || fetch(event.request.url).then((fetchedResponse) => {
// Add the network response to the cache for future visits.
// Note: we need to make a copy of the response to save it in
// the cache and use the original as the request response.
cache.put(event.request, fetchedResponse.clone());
// Return the network response
return fetchedResponse;
});
});
}));
} else {
return;
}
});
이것은 예시일 뿐이며 직접 직접 확인할 수 있는 이미지이지만 서비스 워커가 무엇을 할 수 있는지 엿볼 수 있는 것입니다. 위 코드는 다음 작업을 실행합니다.
- 요청의
destination
속성을 검사하여 이미지 요청인지 확인합니다. - 이미지가 서비스 워커 캐시에 있으면 거기에서 이미지를 제공합니다. 그렇지 않으면 네트워크에서 이미지를 가져옵니다. 응답을 캐시에 저장하고 네트워크 응답을 반환합니다.
- 다른 모든 요청은 캐시와의 상호작용 없이 서비스 워커를 통해 전달됩니다.
가져오기의 event
객체에는
속성 request
개
다음은 각 요청의 유형을 식별하는 데 도움이 되는 유용한 정보입니다.
url
님, 이는 현재fetch
이벤트에 의해 처리 중인 네트워크 요청의 URL입니다.method
님, 이는 요청 메서드입니다 (예:GET
또는POST
).mode
님, - 요청 모드를 설명합니다.'navigate'
값은 HTML 문서에 대한 요청을 다른 요청과 구분하는 데 자주 사용됩니다.destination
님, 요청된 저작물의 파일 확장자를 사용하지 않는 방식으로 요청 중인 콘텐츠 유형을 설명합니다.
다시 말하지만, asynchrony가 게임의 이름입니다.
install
이벤트는
event.waitUntil
메서드를 호출합니다.
fetch
이벤트는 유사한
event.respondWith
메서드
비동기 호출의 결과를 반환하는 데 사용할 수 있는
요청 fetch
개
또는 Cache
인터페이스의
match
메서드를 표시합니다.
캐싱 전략
이제 Cache
인스턴스와 fetch
이벤트 핸들러를 약간 알아봤습니다.
몇 가지 서비스 워커 캐싱 전략을 배울 준비가 되었습니다.
가능성은 사실상 무궁무진하지만
이 가이드에서는 Workbox와 함께 제공되는 전략을
집중적으로 살펴보겠습니다
Workbox 내부에서 일어나는 일을 파악할 수 있습니다.
캐시 전용
'Cache Only'라는 간단한 캐싱 전략부터 시작해 보겠습니다. 서비스 워커가 페이지를 제어할 때, 캐시로만 이동합니다 즉, 캐시된 모든 자산을 사전 캐시해야 패턴이 작동할 수 있습니다. 서비스 워커가 업데이트될 때까지 이러한 자산이 캐시에서 업데이트되지 않습니다.
// Establish a cache name
const cacheName = 'MyFancyCacheName_v1';
// Assets to precache
const precachedAssets = [
'/possum1.jpg',
'/possum2.jpg',
'/possum3.jpg',
'/possum4.jpg'
];
self.addEventListener('install', (event) => {
// Precache assets on install
event.waitUntil(caches.open(cacheName).then((cache) => {
return cache.addAll(precachedAssets);
}));
});
self.addEventListener('fetch', (event) => {
// Is this one of our precached assets?
const url = new URL(event.request.url);
const isPrecachedRequest = precachedAssets.includes(url.pathname);
if (isPrecachedRequest) {
// Grab the precached asset from the cache
event.respondWith(caches.open(cacheName).then((cache) => {
return cache.match(event.request.url);
}));
} else {
// Go to the network
return;
}
});
위에서 애셋 배열은 설치 시 사전 캐시됩니다.
서비스 워커가 가져오기를 처리할 때
fetch
이벤트에 의해 처리된 요청 URL이 사전 캐시된 애셋 배열에 있는지 확인합니다.
만약 그렇다면, 캐시에서 리소스를 가져와서 네트워크를 건너뜁니다.
다른 요청은 네트워크로 전달되며
네트워크에서만 사용할 수 있습니다.
이 전략의 예를 확인하려면
콘솔을 연 상태에서 이 데모를 확인하세요.
네트워크 전용
'Cache Only'의 반대 의미 '네트워크만'이고 이 경우 요청이 서비스 워커 캐시와의 상호작용 없이 서비스 워커를 통해 네트워크로 전달됩니다. 이는 마크업과 같이 콘텐츠를 최신 상태로 유지하는 데 좋은 전략입니다. 단점은 사용자가 오프라인일 때는 작동하지 않는다는 것입니다.
요청이 네트워크로 전달되면 일치하는 요청에 대해 event.respondWith
를 호출하지 않습니다.
명시적으로 표현하려면
네트워크로 전달하려는 요청의 fetch
이벤트 콜백에서 빈 return;
를 칠 수 있습니다.
'Cache Only' 옵션에서 사전 캐시되지 않은 요청에 대한 전략 데모입니다.
먼저 캐시한 후 네트워크로 대체
이 전략에서는 더 많은 작업을 수행할 수 있습니다. 일치하는 요청의 경우 프로세스는 다음과 같습니다.
- 요청이 캐시에 도달합니다. 애셋이 캐시에 있으면 캐시에서 제공합니다.
- 요청이 캐시에 없는 경우 네트워크로 이동합니다.
- 네트워크 요청이 완료되면 캐시에 추가합니다. 네트워크에서 응답을 반환합니다
이 전략의 예는 라이브 데모:
// Establish a cache name
const cacheName = 'MyFancyCacheName_v1';
self.addEventListener('fetch', (event) => {
// Check if this is a request for an image
if (event.request.destination === 'image') {
event.respondWith(caches.open(cacheName).then((cache) => {
// Go to the cache first
return cache.match(event.request.url).then((cachedResponse) => {
// Return a cached response if we have one
if (cachedResponse) {
return cachedResponse;
}
// Otherwise, hit the network
return fetch(event.request).then((fetchedResponse) => {
// Add the network response to the cache for later visits
cache.put(event.request, fetchedResponse.clone());
// Return the network response
return fetchedResponse;
});
});
}));
} else {
return;
}
});
이 예에서는 이미지만 다루지만 이는 모든 정적 자산 (예: CSS, JavaScript, 이미지 및 글꼴)에 적용할 수 있는 훌륭한 전략입니다. 특히 해시 버전이 지정된 포드를 제공합니다 HTTP 캐시가 시작될 수 있는 서버에서 콘텐츠 최신성 검사를 생략하여 변경할 수 없는 자산에 대해 속도를 향상합니다. 무엇보다 캐시된 애셋은 오프라인에서도 사용할 수 있습니다.
네트워크 우선, 캐시로 대체
'캐시 우선, 네트워크 두 번째'로 바꾸려면 고양이가 머리 위에 있다면 '네트워크 우선, 캐시 두 번째'가 되고 말씀드리겠습니다.
- 먼저 요청을 위해 네트워크로 이동한 다음 응답을 캐시에 배치합니다.
- 나중에 오프라인 상태라면 캐시에서 해당 응답의 최신 버전으로 돌아갑니다.
이 전략은 다음과 같은 HTML 또는 API 요청에 적합합니다. 가장 최신 버전의 리소스가 필요할 때 사용 가능한 최신 버전에 대한 오프라인 액세스 권한을 부여하고 싶을 수 있습니다. HTML 요청에 적용하면 다음과 같이 표시될 수 있습니다.
// Establish a cache name
const cacheName = 'MyFancyCacheName_v1';
self.addEventListener('fetch', (event) => {
// Check if this is a navigation request
if (event.request.mode === 'navigate') {
// Open the cache
event.respondWith(caches.open(cacheName).then((cache) => {
// Go to the network first
return fetch(event.request.url).then((fetchedResponse) => {
cache.put(event.request, fetchedResponse.clone());
return fetchedResponse;
}).catch(() => {
// If the network is unavailable, get
return cache.match(event.request.url);
});
}));
} else {
return;
}
});
데모를 통해 사용해 볼 수 있습니다. 먼저 페이지로 이동합니다. HTML 응답이 캐시에 배치되기 전에 새로고침해야 할 수도 있습니다. 그런 다음 개발자 도구에서 오프라인 연결 시뮬레이션 다시 새로고침합니다 사용 가능한 마지막 버전이 캐시에서 즉시 제공됩니다.
오프라인 기능이 중요한 상황에서는 그러나 최신 버전의 마크업 또는 API 데이터에 대한 액세스와 이 기능 간의 균형을 맞춰야 합니다. "네트워크 우선, 캐시 두 번째" 이 목표를 달성하는 견고한 전략입니다.
재검증 중 비활성
지금까지 살펴본 전략 중 'Stale-while-revalidate' 가장 복잡합니다 마지막 두 가지 전략과 몇 가지 면에서 비슷합니다. 절차는 리소스에 대한 액세스 속도에 우선순위를 두고 백그라운드에서 최신 상태로 유지됩니다 이 전략은 다음과 같습니다.
- 애셋에 대한 첫 번째 요청에서 애셋을 네트워크에서 가져옵니다. 캐시에 배치하고 네트워크 응답을 반환합니다.
- 후속 요청 시에는 먼저 캐시에서 애셋을 제공한 다음 '백그라운드에서' 네트워크에서 다시 요청하고 자산의 캐시 항목을 업데이트합니다.
- 이후 요청의 경우 이전 단계에서 캐시에 배치된 네트워크에서 가져온 마지막 버전을 수신합니다.
이것은 최신 상태를 유지하는 중요한 항목을 위한 훌륭한 전략입니다. 중요하지 않습니다. 소셜 미디어 사이트에서 아바타 같은 것을 생각해 보세요. 사용자가 이리저리 돌아다닐 때 업데이트됩니다. 최신 버전이 모든 요청에 반드시 필요한 것은 아닙니다.
// Establish a cache name
const cacheName = 'MyFancyCacheName_v1';
self.addEventListener('fetch', (event) => {
if (event.request.destination === 'image') {
event.respondWith(caches.open(cacheName).then((cache) => {
return cache.match(event.request).then((cachedResponse) => {
const fetchedResponse = fetch(event.request).then((networkResponse) => {
cache.put(event.request, networkResponse.clone());
return networkResponse;
});
return cachedResponse || fetchedResponse;
});
}));
} else {
return;
}
});
자세한 내용은
또 다른 라이브 데모,
특히 브라우저의 개발자 도구에서 네트워크 탭에 주의를 기울이면
및 CacheStorage
뷰어 (브라우저의 개발자 도구에 이러한 도구가 있는 경우)가 포함됩니다.
Workbox로 나아가세요!
이 문서에서는 서비스 워커의 API에 대한 검토를 마무리합니다. 관련 API도 제공합니다 즉, 서비스 워커를 직접 사용하여 Workbox를 조작하는 방법을 충분히 배웠다는 것을 의미합니다.