서비스 워커 등록

서비스 워커 등록 타이밍을 지정하기 위한 권장사항입니다.

서비스 워커는 웹 앱에 대한 반복 방문 속도를 유의미하게 높일 수 있지만 서비스 워커의 초기 설치로 인해 사용자의 첫 번째 방문 환경이 저하되지 않도록 조치를 취해야 합니다.

일반적으로 초기 페이지가 로드된 이후까지 서비스 워커 등록을 연기하면 사용자, 특히 네트워크 연결이 느린 휴대기기를 사용하는 사용자에게 최상의 환경을 제공할 수 있습니다.

일반적인 등록 상용구

서비스 워커에 관해 읽어본 적이 있다면 다음과 유사한 상용구를 본 적이 있을 것입니다.

if ('serviceWorker' in navigator) {
    navigator.serviceWorker.register('/service-worker.js');
}

여기에는 사용자에게 페이지를 새로고침하도록 알리는 방법으로 몇 개의 console.log() 문 또는 이전 서비스 워커 등록에 대한 업데이트를 감지하는 코드가 수반될 수 있습니다. 그러나 이는 표준 코드 몇 줄을 살짝 바꾼 것에 불과합니다.

그렇다면 navigator.serviceWorker.register에 미묘한 차이가 있나요? 따라야 할 권장사항이 있나요? 이 글이 여기서 끝나지 않는다는 점을 고려하면 이 두 가지에 대한 대답은 당연히 '예'입니다.

사용자의 첫 방문

사용자가 웹 앱을 처음 방문한다고 가정해 보겠습니다. 아직 서비스 워커는 없으며 브라우저는 최종적으로 설치될 서비스 워커가 있는지 미리 알 수 없습니다.

개발자는 대화형 페이지를 표시하는 데 필요한 최소한의 중요 리소스 집합을 브라우저가 빠르게 가져오도록 해야 합니다. 이러한 응답을 가져오는 속도를 저하시키는 모든 것은 신속한 상호작용까지의 시간(time-to-Interactive) 환경의 적입니다.

이제 페이지에서 렌더링해야 하는 자바스크립트 또는 이미지를 다운로드하는 과정에서 브라우저가 백그라운드 스레드 또는 프로세스를 시작하기로 결정했다고 가정해 보겠습니다 (간략히 설명하기 위해 스레드라고 가정함). 데스크톱 컴퓨터가 아니라 전 세계 대부분의 사람들이 주로 사용하는 기기로 간주하는 성능이 저하된 유형의 휴대전화를 사용 중이라고 가정해 보겠습니다. 이 추가 스레드를 가동하면 브라우저가 대화형 웹페이지를 렌더링하는 데 소비할 수 있는 CPU 시간 및 메모리 경합이 추가됩니다.

유휴 백그라운드 스레드는 큰 차이를 만들 것 같지 않습니다. 하지만 스레드가 유휴 상태가 아니고 네트워크에서 리소스 다운로드를 시작하기로 한 경우 어떻게 될까요? CPU 또는 메모리 경합에 관한 우려는 많은 휴대기기에서 사용할 수 있는 제한된 대역폭에 관한 우려보다 이면에서 고려해야 합니다. 대역폭은 중요하므로 보조 리소스를 동시에 다운로드하여 중요한 리소스를 손상시키지 마세요.

즉, 백그라운드에서 리소스를 다운로드하고 캐시하기 위해 새 서비스 워커 스레드를 가동하면 사용자가 사이트를 처음 방문할 때 상호작용까지의 최단 시간 환경을 제공한다는 목표에 어긋날 수 있습니다.

상용구 개선

해결 방법은 navigator.serviceWorker.register() 호출 시점을 선택하여 서비스 워커의 시작을 제어하는 것입니다. 일반적인 규칙은 다음과 같이 load eventwindow에서 실행될 때까지 등록을 지연하는 것입니다.

if ('serviceWorker' in navigator) {
    window.addEventListener('load', function() {
    navigator.serviceWorker.register('/service-worker.js');
    });
}

그러나 서비스 워커 등록을 시작하는 적절한 시점은 웹 앱이 로드된 직후에 어떤 작업을 수행하는지에 따라 달라질 수 있습니다. 예를 들어 Google I/O 2016 웹 앱은 기본 화면으로 전환하기 전에 짧은 애니메이션을 제공합니다. Google팀에서는 애니메이션 중에 서비스 워커 등록을 시작하면 저사양 휴대기기에서 버벅거림이 발생할 수 있음을 확인했습니다. Google은 사용자에게 좋지 않은 환경을 제공하기보다는 애니메이션이 몇 초 동안 유휴 상태일 가능성이 가장 높은 애니메이션 이후까지 서비스 워커 등록을 지연시켰습니다.

마찬가지로 웹 앱에서 페이지가 로드된 후 추가 설정을 실행하는 프레임워크를 사용하는 경우 작업 완료 시점을 알리는 프레임워크별 이벤트를 찾습니다.

후속 방문

지금까지는 첫 번째 방문 환경에 초점을 맞췄습니다. 서비스 워커 등록이 지연되면 사이트 재방문에 어떤 영향을 미칠까요? 당황스러울 수 있지만 전혀 영향을 미치지 않아야 합니다.

서비스 워커가 등록되면 installactivate 수명 주기 이벤트가 발생합니다. 서비스 워커가 활성화되면 이후에 웹 앱을 방문할 때 fetch 이벤트를 처리할 수 있습니다. 서비스 워커는 범위 내에 있는 페이지에 대한 요청이 이루어지기 전에 시작됩니다. 페이지를 방문하기 전에 기존 서비스 워커가 이미 실행되고 있지 않으면 탐색 요청의 fetch 이벤트를 처리할 기회가 없습니다.

따라서 활성 서비스 워커가 있는 경우 navigator.serviceWorker.register()를 언제 호출하든 실제로 호출 여부는 중요하지 않습니다. 서비스 워커 스크립트의 URL을 변경하지 않는 한 navigator.serviceWorker.register()는 후속 방문 중에 사실상 작동하지 않는 상태가 됩니다. 호출 시간은 관련성이 없습니다

일찍 등록해야 하는 이유

서비스 워커를 가능한 한 빨리 등록하는 것이 적합한 시나리오가 있나요? 첫 번째 방문 시 서비스 워커가 clients.claim()를 사용하여 페이지를 제어하고 서비스 워커가 fetch 핸들러 내에서 적극적으로 런타임 캐싱을 수행하는 경우를 고려해야 합니다. 이러한 상황에서는 서비스 워커를 최대한 빨리 활성화하여 나중에 편리하게 제공될 수 있는 리소스로 런타임 캐시를 채우는 것이 좋습니다. 웹 앱이 이 카테고리에 속하는 경우 서비스 워커의 install 핸들러가 기본 페이지의 요청과 대역폭을 두고 경쟁하는 리소스를 요청하지 않도록 한 걸음 물러서서야 합니다.

테스트하기

첫 방문을 시뮬레이션하는 좋은 방법은 Chrome 시크릿 창에서 웹 앱을 열고 Chrome DevTools에서 네트워크 트래픽을 확인하는 것입니다. 웹 개발자는 웹 앱의 로컬 인스턴스를 하루에 수십 번 새로고침하게 될 것입니다. 하지만 이미 서비스 워커와 완전히 채워진 캐시가 있을 때 사이트를 다시 방문하면 신규 사용자에게 제공되는 것과 동일한 경험을 할 수 없으며 잠재적인 문제를 무시하기 쉽습니다.

다음은 등록 타이밍에 따른 차이점을 보여주는 예입니다. 두 스크린샷 모두 시크릿 모드에서 네트워크 제한을 통해 샘플 앱을 방문하는 동안 느린 연결을 시뮬레이션합니다.

조기 등록 시 네트워크 트래픽

위의 스크린샷은 서비스 워커 등록을 가능한 한 빨리 수행하도록 샘플이 수정된 경우의 네트워크 트래픽을 반영합니다. 페이지를 표시하는 데 필요한 다른 리소스에 대한 요청과 함께 섞여 있는 사전 캐싱 요청 (서비스 워커의 install 핸들러에서 발생한 항목 옆에 톱니바퀴 아이콘이 있음)을 확인할 수 있습니다.

늦게 등록한 경우의 네트워크 트래픽

위 스크린샷에서 서비스 워커 등록은 페이지가 로드된 이후까지 지연되었습니다. 네트워크에서 모든 리소스를 가져올 때까지 사전 캐싱 요청이 시작되지 않으므로 대역폭 경합이 발생하지 않습니다. 또한 미리 캐시하는 항목 중 일부가 브라우저의 HTTP 캐시(크기 열에 (from disk cache)가 있는 항목)에 있으므로 네트워크로 다시 이동할 필요 없이 서비스 워커의 캐시를 채울 수 있습니다.

실제 모바일 네트워크의 실제 저사양 기기에서 이러한 종류의 테스트를 실행하면 보너스 포인트가 주어집니다. Chrome의 원격 디버깅 기능을 활용하여 USB를 통해 Android 휴대전화를 데스크톱 컴퓨터에 연결하고 실행 중인 테스트가 많은 사용자의 실제 환경을 반영하는지 확인할 수 있습니다.

결론

요약하자면, 사용자에게 최상의 첫 방문 경험을 제공하는 것을 최우선순위로 삼아야 합니다. 최초 방문 시 페이지가 로드된 이후까지 서비스 워커 등록을 지연하면 이렇게 하는 데 도움이 될 수 있습니다. 재방문 시에도 서비스 워커의 모든 이점을 누릴 수 있습니다.

첫 번째 페이지가 로드된 이후까지 서비스 워커의 초기 등록을 지연하는 간단한 방법은 다음을 사용하는 것입니다.

if ('serviceWorker' in navigator) {
    window.addEventListener('load', function() {
    navigator.serviceWorker.register('/service-worker.js');
    });
}