Chrome 71에서 제공되는 cache.addAll() 및 importScripts()의 미세 조정

서비스 워커Cache Storage API를 사용하는 개발자는 Chrome 71에서 출시되는 두 가지 소규모 변경사항도 주의해야 합니다. 두 변경사항 모두 Chrome의 구현이 사양 및 다른 브라우저에 더 부합하도록 합니다.

비동기 importScripts() 금지

importScripts()는 기본 서비스 워커 스크립트에 현재 실행을 일시중지하고 지정된 URL에서 추가 코드를 다운로드한 후 현재 전역 범위에서 완료될 때까지 실행하도록 지시합니다. 완료되면 기본 서비스 워커 스크립트가 실행을 재개합니다. importScripts()는 기본 서비스 워커 스크립트를 조직상의 이유로 더 작은 조각으로 나누거나, 서드 파티 코드를 가져와 서비스 워커에 기능을 추가하려는 경우에 유용합니다.

브라우저는 importScripts()를 통해 가져온 모든 항목을 자동으로 캐시하여 '동기식 코드를 다운로드하고 실행'할 때 발생할 수 있는 성능 문제를 완화하려고 합니다. 즉, 초기 다운로드 후에는 가져온 코드를 실행하는 데 오버헤드가 거의 없습니다.

하지만 이 기능이 작동하려면 브라우저가 최초 설치 후 서비스 워커로 '예상치 못한' 코드를 가져올 수 없음을 알아야 합니다. 서비스 워커 사양에 따라 importScripts() 호출은 최상위 서비스 워커 스크립트를 동기식으로 실행하는 동안에만 작동하거나 필요한 경우 install 핸들러 내에서 비동기식으로 작동해야 합니다.

Chrome 71 이전에는 install 핸들러 외부에서 importScripts()를 비동기적으로 호출하면 작동했습니다. Chrome 71부터 이러한 호출에서는 다른 브라우저의 동작과 일치하는 런타임 예외가 발생합니다 (이전에 동일한 URL을 install 핸들러에서 가져오지 않은 경우).

다음과 같이 코드를 작성할 수 없습니다.

// This only works in Chrome 70 and below.
self.addEventListener('fetch', event => {
  importScripts('my-fetch-logic.js');
  event.respondWith(self.customFetchLogic(event));
});

서비스 워커 코드는 다음과 같습니다.

// Move the importScripts() to the top-level scope.
// (Alternatively, import the same URL in the install handler.)
importScripts('my-fetch-logic.js');
self.addEventListener('fetch', event => {
  event.respondWith(self.customFetchLogic(event));
});

cache.addAll()에 전달되는 반복 URL 지원 중단

서비스 워커와 함께 Cache Storage API를 사용하는 경우 관련 사양에 맞게 Chrome 71에서 또 다른 약간의 변경사항이 있습니다. 단일 cache.addAll() 호출에 동일한 URL이 여러 번 전달되는 경우 호출에서 반환된 프로미스를 거부하도록 사양에 명시되어 있습니다.

Chrome 71 이전에는 이러한 URL이 감지되지 않아 중복 URL이 사실상 무시됩니다.

Chrome 콘솔의 경고 메시지 스크린샷
Chrome 71부터 콘솔에 경고 메시지가 표시됩니다.

이 로깅은 Chrome 72의 이전 버전이며, 로깅된 경고 대신 중복 URL이 cache.addAll() 거부로 이어집니다. 일반적인 관행처럼 InstallEvent.waitUntil()에 전달된 프로미스 체인의 일부로 cache.addAll()를 호출하는 경우, 이러한 거부로 인해 서비스 워커가 설치되지 않을 수 있습니다.

다음과 같은 문제가 발생할 수 있습니다.

const urlsToCache = [
  '/index.html',
  '/main.css',
  '/app.js',
  '/index.html', // Oops! This is listed twice and should be removed.
];

self.addEventListener('install', event => {
  event.waitUntil(
    caches.open('my-cache').then(cache => cache.addAll(urlsToCache))
  );
});

이 제한사항은 cache.addAll()에 전달되는 실제 URL에만 적용되며, '/', '/index.html'와 같이 URL이 다른 두 개의 동등한 응답을 캐시하면 거부가 트리거되지 않습니다.

서비스 워커 구현을 광범위하게 테스트

서비스 워커는 모든 주요 '상시' 브라우저에서 광범위하게 구현됩니다. 여러 브라우저에서 프로그레시브 웹 앱을 정기적으로 테스트하거나 Chrome을 사용하지 않는 사용자가 많다면 이미 불일치를 감지하고 코드를 업데이트했을 가능성이 높습니다. 하지만 다른 브라우저에서 이 동작을 발견하지 못했을 수 있으므로 Chrome의 동작을 전환하기 전에 변경사항을 알려드리고자 합니다.