최신 서비스 워커(기본)

제프 포스닉
제프 포스닉

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시간)보다 크면 86,400인 것처럼 처리되어 사용자가 특정 버전을 계속 사용할 수 없게 됩니다.

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

updateViaCache

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

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

  • 'imports'로 설정하면 /service-worker.js 스크립트의 업데이트를 확인할 때 HTTP 캐시가 참조되지 않지만 가져온 스크립트를 가져올 때 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부터는 최상위 서비스 워커 파일에 대한 업데이트 검사를 수행할 때마다 동시에 검사를 실행하여 가져온 스크립트의 콘텐츠가 변경되었는지 확인합니다. 사용된 Cache-Control 헤더에 따라 이러한 가져온 스크립트 검사는 updateViaCache'all' 또는 'imports' (기본값)로 설정된 경우 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 getchas'를 모두 읽어보는 것이 좋습니다.