최신 서비스 워커(기본)

tl;dr

Chrome 68부터 서비스 워커 스크립트에 대한 업데이트를 확인하는 HTTP 요청은 더 이상 기본적으로 HTTP 캐시에 의해 처리되지 않습니다. 이 방법은 서비스 워커 스크립트에 의도치 않은 Cache-Control 헤더를 설정할 경우 업데이트가 지연될 수 있는 일반적인 개발자의 문제를 해결합니다.

/service-worker.js 스크립트에 Cache-Control: max-age=0를 제공하여 이미 HTTP 캐싱을 선택 해제한 경우 새로운 기본 동작으로 인해 변경사항이 표시되지 않습니다.

또한 Chrome 78부터 importScripts()를 통해 서비스 워커에 로드된 스크립트에 바이트 단위 비교가 적용됩니다. 가져온 스크립트를 변경하면 최상위 서비스 워커의 변경과 마찬가지로 서비스 워커 업데이트 흐름이 트리거됩니다.

배경

서비스 워커 범위에 있는 새 페이지로 이동할 때마다 JavaScript에서 명시적으로 registration.update()를 호출하거나 서비스 워커가 push 또는 sync 이벤트를 통해 '활성화'되면 브라우저가 동시에 navigator.serviceWorker.register() 호출에 원래 전달된 JavaScript 리소스를 요청하여 서비스 워커 스크립트에 대한 업데이트를 찾습니다.

이 문서에서는 URL이 /service-worker.js이고 서비스 워커 내에서 실행되는 추가 코드를 로드하는 importScripts()에 대한 단일 호출이 포함되어 있다고 가정해 보겠습니다.

// Inside our /service-worker.js file:
importScripts('path/to/import.js');

// Other top-level code goes here.

변경되는 사항

Chrome 68 이전에는 /service-worker.js의 업데이트 요청이 HTTP 캐시를 통해 이루어졌습니다(대부분의 가져오기와 마찬가지로). 즉, 스크립트가 원래 Cache-Control: max-age=600로 전송된 경우 다음 600초 (10분) 내의 업데이트가 네트워크로 이동하지 않으므로 사용자가 최신 버전의 서비스 워커를 수신하지 못할 수 있습니다. 그러나 max-age이 86,400 (24시간)보다 크면 사용자가 특정 버전을 계속 유지하지 않도록 86400인 것처럼 처리됩니다.

68부터 서비스 워커 스크립트에 대한 업데이트를 요청할 때 HTTP 캐시가 무시되므로 기존 웹 애플리케이션의 서비스 워커 스크립트에 대한 요청 빈도가 증가할 수 있습니다. importScripts 요청은 계속 HTTP 캐시를 통해 진행됩니다. 하지만 이는 기본값일 뿐이며 이 동작에 관한 제어를 제공하는 새로운 등록 옵션인 updateViaCache를 사용할 수 있습니다.

updateViaCache

이제 개발자는 navigator.serviceWorker.register()를 호출할 때 새 옵션인 updateViaCache 매개변수를 전달할 수 있습니다. 'imports', 'all', 'none'의 세 가지 값 중 하나를 사용합니다.

이 값은 업데이트된 서비스 워커 리소스를 확인하기 위해 HTTP 요청을 할 때 브라우저의 표준 HTTP 캐시가 실행되는지 여부와 그 방법을 결정합니다.

  • 'imports'로 설정하면 /service-worker.js 스크립트에 대한 업데이트를 확인할 때 HTTP 캐시를 참조하지 않지만 가져온 스크립트(이 예시에서는 path/to/import.js)를 가져올 때 참조됩니다. 이는 기본값이며 Chrome 68부터의 동작과 일치합니다.

  • 'all'로 설정하면 최상위 /service-worker.js 스크립트 및 서비스 워커 내부에서 가져온 모든 스크립트(예: path/to/import.js)에 대해 요청을 수행할 때 HTTP 캐시를 참고합니다. 이 옵션은 Chrome 68 이전의 Chrome 동작에 해당합니다.

  • 'none'로 설정하면 최상위 /service-worker.js 또는 가져온 스크립트(예: 가상의 path/to/import.js)에 대해 요청할 때 HTTP 캐시를 참조하지 않습니다.

예를 들어 다음 코드는 서비스 워커를 등록하고 /service-worker.js 스크립트에 대한 업데이트를 확인할 때 또는 /service-worker.js 내부의 importScripts()를 통해 참조되는 스크립트에 대한 업데이트를 확인할 때 HTTP 캐시를 참조하지 않도록 합니다.

if ('serviceWorker' in navigator) {
  navigator.serviceWorker.register('/service-worker.js', {
    updateViaCache: 'none',
    // Optionally, set 'scope' here, if needed.
  });
}

가져온 스크립트의 업데이트 확인

Chrome 78 이전에는 importScripts()를 통해 로드된 모든 서비스 워커 스크립트가 한 번만 검색되었습니다 (updateViaCache 구성에 따라 HTTP 캐시 또는 네트워크를 통해 먼저 확인). 초기 검색 후에는 브라우저에서 내부적으로 저장되며 다시 가져오지 않습니다.

이미 설치된 서비스 워커가 가져온 스크립트의 변경사항을 선택하도록 강제하는 유일한 방법은 일반적으로 semver 값 (예: importScripts('https://example.com/v1.1.0/index.js'))을 추가하거나 콘텐츠의 해시 (예: importScripts('https://example.com/index.abcd1234.js'))를 포함하여 스크립트의 URL을 변경하는 것입니다. 가져온 URL을 변경하면 최상위 서비스 워커 스크립트의 콘텐츠가 변경되고, 그 결과 서비스 워커의 흐름이 업데이트되도록 하는 것이 부작용입니다.

Chrome 78부터 최상위 서비스 워커 파일에 대한 업데이트 검사가 수행될 때마다 동시에 가져온 스크립트의 콘텐츠가 변경되었는지 여부를 확인합니다. 이러한 가져온 스크립트 검사는 updateViaCache'all' 또는 'imports' (기본값)로 설정된 경우 사용되는 Cache-Control 헤더에 따라 HTTP 캐시로 수행되거나 updateViaCache'none'로 설정된 경우 네트워크에 대해 직접 검사가 실행될 수 있습니다.

가져온 스크립트에 대한 업데이트 검사로 인해 서비스 워커가 이전에 저장한 것과 바이트 단위 차이가 생기면 최상위 서비스 워커 파일이 동일하게 유지되더라도 전체 서비스 워커 업데이트 흐름이 트리거됩니다.

Chrome 78 동작은 몇 년 전 Firefox 56에서 Firefox가 구현한 동작과 일치합니다. Safari도 이미 이 동작을 구현하고 있습니다.

개발자는 무엇을 해야 하나요?

/service-worker.js 스크립트에 Cache-Control: max-age=0 (또는 유사한 값)을 제공하여 HTTP 캐싱을 효과적으로 선택 해제한 경우 새로운 기본 동작으로 인해 변경사항이 표시되지 않습니다.

의도적으로 또는 호스팅 환경의 기본값이기 때문에 HTTP 캐싱을 사용 설정한 상태에서 /service-worker.js 스크립트를 제공하면 서버에 대한 /service-worker.js의 추가 HTTP 요청이 증가할 수 있습니다. 이러한 요청은 HTTP 캐시로 처리되곤 했습니다. Cache-Control 헤더 값이 /service-worker.js의 최신 상태에 영향을 미치도록 계속 허용하려면 서비스 워커를 등록할 때 명시적으로 updateViaCache: 'all'를 설정해야 합니다.

이전 브라우저 버전에서는 롱테일 사용자가 있을 수 있으므로 최신 브라우저에서 무시되더라도 서비스 워커 스크립트에서 Cache-Control: max-age=0 HTTP 헤더를 계속 설정하는 것이 좋습니다.

개발자는 이 기회를 사용하여 가져온 스크립트를 지금 명시적으로 HTTP 캐싱을 선택 해제할지 결정하고 필요한 경우 updateViaCache: 'none'를 서비스 워커 등록에 추가할 수 있습니다.

가져온 스크립트 제공

Chrome 78부터는 개발자가 업데이트를 확인하므로 importScripts()를 통해 로드된 리소스에 관한 수신 HTTP 요청이 더 많이 표시될 수 있습니다.

이러한 추가 HTTP 트래픽을 방지하려면 URL에 semver 또는 해시가 포함된 스크립트를 제공할 때 수명이 긴 Cache-Control 헤더를 설정하고 'imports'의 기본 updateViaCache 동작을 사용합니다.

또는 가져온 스크립트가 자주 업데이트되는지 확인하려면 Cache-Control: max-age=0를 사용하거나 updateViaCache: 'none'를 사용해야 합니다.

추가 자료

제이크 아치볼드가 저술한 '서비스 워커 수명 주기' 및 '캐싱 권장사항 및 max-age 문제'는 웹에 배포하는 모든 개발자에게 권장됩니다.