즉각적인 탐색 환경

서비스 워커를 사용하여 기존의 미리 가져오기 기법을 보완합니다.

Demián Renzulli
Demián Renzulli
Gilberto Cocchi
Gilberto Cocchi

사이트에서 작업을 실행하려면 일반적으로 여러 단계를 거쳐야 합니다. 예를 들어 전자상거래 웹사이트에서 제품을 구매하려면 제품을 검색하고, 검색 결과 목록에서 상품을 선택하고, 장바구니에 상품을 추가하고, 결제하여 작업을 완료해야 할 수 있습니다.

기술적으로는 여러 페이지를 이동하는 것을 탐색 요청이라고 합니다. 일반적으로 장기 Cache-Control 헤더를 사용하여 탐색 요청의 HTML 응답을 캐시하면 안 됩니다. 일반적으로 HTML이 후속 네트워크 요청 체인과 함께 (합리적으로) 최신 상태를 유지하도록 Cache-Control: no-cache를 사용하여 네트워크를 통해 충족해야 합니다. 사용자가 새 페이지로 이동할 때마다 네트워크를 거쳐야 하므로 탐색 속도가 느려질 수 있습니다. 최소한 안정적으로 빠르지는 않을 것입니다.

이러한 요청을 가속화하려면 사용자의 작업을 예상할 수 있는 경우 이러한 페이지와 애셋을 미리 요청하고 사용자가 이러한 링크를 클릭할 때까지 잠시 캐시에 보관하면 됩니다. 이 기법을 미리 로드라고 하며 일반적으로 미리 로드할 리소스를 나타내는 <link rel="prefetch"> 태그를 페이지에 추가하여 구현합니다.

이 가이드에서는 서비스 워커를 기존의 미리 가져오기 기술을 보완하는 방법으로 사용할 수 있는 다양한 방법을 살펴봅니다.

프로덕션 케이스

MercadoLibre는 중남미 최대의 전자상거래 사이트입니다. 탐색 속도를 높이기 위해 흐름의 일부에 <link rel="prefetch"> 태그를 동적으로 삽입합니다. 예를 들어 등록정보 페이지에서 사용자가 등록정보 하단으로 스크롤하는 즉시 다음 결과 페이지를 가져옵니다.

MercadoLibre의 등록정보 페이지 1과 2의 스크린샷과 두 페이지를 연결하는 링크 미리 가져오기 태그

미리 가져온 파일은 '가장 낮음' 우선순위로 요청되며 리소스를 캐시할 수 있는지 여부에 따라 HTTP 캐시 또는 메모리 캐시에 브라우저에 따라 달라지는 시간 동안 저장됩니다. 예를 들어 Chrome 85에서는 이 값이 5분입니다. 리소스는 5분 동안 유지되며 그 후에는 리소스에 대한 일반 Cache-Control 규칙이 적용됩니다.

서비스 워커 캐싱을 사용하면 5분 이외의 기간 동안 미리 가져오기 리소스의 전체 기간을 연장할 수 있습니다.

예를 들어 이탈리아 스포츠 포털 Virgilio Sport에서는 서비스 워커를 사용하여 홈페이지에서 가장 인기 있는 게시물을 미리 로드합니다. 또한 Network Information API를 사용하여 2G 연결을 사용하는 사용자의 미리 로드를 방지합니다.

Virgilio Sport 로고

그 결과 3주간의 관찰 결과 Virgilio Sport에서는 기사 탐색의 로드 시간이 78% 개선되고 기사 노출수가 45% 증가했습니다.

미리 로드 후 효과 측정항목이 포함된 Virgilio Sport 홈 및 기사 페이지의 스크린샷

Workbox로 미리 캐싱 구현

다음 섹션에서는 Workbox를 사용하여 이 작업을 완전히 서비스 워커에 위임하여 <link rel="prefetch">를 보완하거나 대체하는 데 사용할 수 있는 다양한 캐싱 기법을 서비스 워커에 구현하는 방법을 보여줍니다.

1. 정적 페이지 및 페이지 하위 리소스 사전 캐시

사전 캐싱은 서비스 워커가 설치되는 동안 파일을 캐시에 저장하는 기능입니다.

다음 경우에는 탐색 속도를 높이는 것과 같은 미리 로드와 유사한 목표를 달성하기 위해 미리 캐싱이 사용됩니다.

정적 페이지 미리 캐싱

빌드 시간 (예: about.html, contact.html) 또는 완전히 정적 사이트에서 생성되는 페이지의 경우 사이트의 문서를 미리 캐시 목록에 추가하기만 하면 됩니다.그러면 사용자가 문서에 액세스할 때마다 캐시에서 문서를 사용할 수 있습니다.

workbox.precaching.precacheAndRoute([
  {url: '/about.html', revision: 'abcd1234'},
  // ... other entries ...
]);

페이지 하위 리소스 미리 캐싱

사이트의 여러 섹션에서 사용할 수 있는 정적 애셋 (예: JavaScript, CSS 등)을 미리 캐시하는 것은 일반적인 권장사항이며 미리 캐시 시나리오에서 성능을 더욱 향상시킬 수 있습니다.

전자상거래 사이트에서 탐색 속도를 높이려면 등록정보 페이지에서 <link rel="prefetch"> 태그를 사용하여 등록정보 페이지의 처음 몇 개 제품에 대한 제품 세부정보 페이지를 미리 로드할 수 있습니다. 제품 페이지 하위 리소스를 이미 미리 캐시했다면 탐색 속도가 더욱 빨라질 수 있습니다.

이를 구현하려면 다음 단계를 따르세요.

  • 페이지에 <link rel="prefetch"> 태그를 추가합니다.
 <link rel="prefetch" href="/phones/smartphone-5x.html" as="document">
  • 서비스 워커의 미리 캐시 목록에 페이지 하위 리소스를 추가합니다.
workbox.precaching.precacheAndRoute([
  '/styles/product-page.ac29.css',
  // ... other entries ...
]);

2. 미리 가져오기 리소스의 전체 기간 연장

앞서 언급한 것처럼 <link rel="prefetch">는 HTTP 캐시에서 리소스를 가져와 일정 시간 동안 유지한 후 리소스에 대한 Cache-Control 규칙을 적용합니다. Chrome 85부터 이 값은 5분입니다.

서비스 워커를 사용하면 미리 가져오기 페이지의 전체 기간을 연장할 수 있으며, 이러한 리소스를 오프라인에서 사용할 수 있다는 추가 이점도 제공됩니다.

이전 예에서는 제품 페이지를 미리 로드하는 데 사용된 <link rel="prefetch">Workbox 런타임 캐싱 전략으로 보완할 수 있습니다.

이를 구현하려면 다음 단계를 따르세요.

  • 페이지에 <link rel="prefetch"> 태그를 추가합니다.
 <link rel="prefetch" href="/phones/smartphone-5x.html" as="document">
  • 다음 유형의 요청에 대해 서비스 워커에 런타임 캐싱 전략을 구현합니다.
new workbox.strategies.StaleWhileRevalidate({
  cacheName: 'document-cache',
  plugins: [
    new workbox.expiration.Plugin({
      maxAgeSeconds: 30 * 24 * 60 * 60, // 30 Days
    }),
  ],
});

이 경우 비활성 상태에서 재검증 전략을 사용하기로 했습니다. 이 전략에서는 페이지를 캐시와 네트워크에서 동시에 요청할 수 있습니다. 응답은 사용 가능한 경우 캐시에서 가져오고 그렇지 않은 경우 네트워크에서 가져옵니다. 캐시는 요청이 성공할 때마다 네트워크 응답을 통해 항상 최신 상태로 유지됩니다.

3. 서비스 워커에 미리 로드 위임

대부분의 경우 <link rel="prefetch">를 사용하는 것이 가장 좋습니다. 이 태그는 최대한 효율적으로 미리 로드할 수 있도록 설계된 리소스 힌트입니다.

하지만 경우에 따라 이 작업을 서비스 워커에 완전히 위임하는 것이 더 나을 수 있습니다. 예를 들어 클라이언트 측에서 렌더링된 제품 등록정보 페이지에서 처음 몇 개의 제품을 미리 로드하려면 API 응답을 기반으로 페이지에 여러 개의 <link rel="prefetch"> 태그를 동적으로 삽입해야 할 수 있습니다. 이렇게 하면 페이지의 기본 스레드에서 잠시 시간이 소요되고 구현이 더 어려워질 수 있습니다.

이 경우 '페이지-서비스 워커 통신 전략'을 사용하여 미리 가져오기 작업을 완전히 서비스 워커에 위임합니다. 이러한 유형의 통신은 worker.postMessage()를 사용하여 실행할 수 있습니다.

서비스 워커와 양방향 통신을 하는 페이지의 아이콘

Workbox Window 패키지는 이러한 유형의 통신을 간소화하여 실행 중인 기본 호출의 많은 세부정보를 추상화합니다.

Workbox Window를 사용한 미리 로드는 다음과 같이 구현할 수 있습니다.

  • 페이지에서: 서비스 워커를 호출하여 메시지 유형과 미리 로드할 URL 목록을 전달합니다.
const wb = new Workbox('/sw.js');
wb.register();

const prefetchResponse = await wb.messageSW({type: 'PREFETCH_URLS', urls: […]});
  • 서비스 워커에서: 미리 로드할 각 URL에 대해 fetch() 요청을 실행하는 메시지 핸들러를 구현합니다.
addEventListener('message', (event) => {
  if (event.data.type === 'PREFETCH_URLS') {
    // Fetch URLs and store them in the cache
  }
});