즉각적인 탐색 환경

서비스 워커로 기존의 미리 가져오기 기술을 보완.

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

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

기술적인 용어를 설명하면 다른 페이지를 이동하는 것은 탐색 요청을 하는 것을 의미합니다. 일반적으로 탐색 요청의 HTML 응답을 캐시하는 데 수명이 긴 Cache-Control 헤더를 사용하지 않는 것이 좋습니다. 후속 네트워크 요청 체인과 함께 HTML이 (합리적으로) 최신이 되도록 하려면 일반적으로 Cache-Control: no-cache를 사용하여 네트워크를 통해 충족되어야 합니다. 사용자가 새 페이지로 이동할 때마다 네트워크에 접속해야 한다면 안타깝게도 각 탐색이 느려질 수 있습니다. 적어도 안정적은 빠르지 않을 것입니다.

사용자의 동작을 예상할 수 있다면 요청 속도를 높이기 위해 이러한 페이지와 애셋을 미리 요청하고 사용자가 이 링크를 클릭할 때까지 짧은 시간 동안 캐시에 보관할 수 있습니다. 이 기술은 미리 가져오기라고 하며 일반적으로 미리 가져올 리소스를 나타내는 <link rel="prefetch"> 태그를 페이지에 추가하여 구현됩니다.

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

프로덕션 사례

MercadoLibre는 라틴 아메리카 최대 규모의 전자상거래 사이트입니다. 탐색 속도를 높이기 위해 흐름의 일부 부분에 <link rel="prefetch"> 태그를 동적으로 삽입합니다. 예를 들어 목록 페이지에서는 사용자가 목록 하단으로 스크롤하자마자 다음 결과 페이지를 가져옵니다.

MercadoLibre의 등록정보 페이지 1과 2와 두 페이지를 연결하는 Link Prefetch 태그의 스크린샷입니다.

미리 가져온 파일은 '가장 낮은' 우선순위로 요청되며 리소스 캐시 가능 여부에 따라 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분입니다.

서비스 워커를 사용하면 미리 가져오기 페이지의 수명을 연장하는 동시에 이러한 리소스를 오프라인에서 사용할 수 있는 추가적인 이점을 제공할 수 있습니다.

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

이를 구현하려면 다음 안내를 따르세요.

  • 페이지에 <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
    }),
  ],
});

이 경우에는 stale-while-revalidate 전략을 사용하기로 했습니다. 이 전략에서는 캐시와 네트워크 모두에서 페이지를 동시에 요청할 수 있습니다. 응답은 사용 가능한 경우 캐시에서, 그렇지 않은 경우 네트워크에서 가져옵니다. 요청이 성공할 때마다 네트워크 응답에 따라 캐시가 항상 최신 상태로 유지됩니다.

3. 미리 가져오기를 서비스 워커에 위임

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

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

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

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

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

Workbox 창을 사용한 미리 가져오기는 다음과 같은 방법으로 구현할 수 있습니다.

  • 페이지에서: 서비스 워커를 호출하여 메시지 유형과 미리 가져올 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
  }
});