서비스 워커에서 성능 측정

제이크 아치볼드는 개발자 스킬이 부러지거나 떨어질까봐 걱정하는 것을 제외하고는 서비스 워커를 지능적으로 사용하면 사이트 또는 앱의 성능을 획기적으로 개선할 수 있다는 확고한 사례를 주장했습니다. 다음 동영상에서 개요를 확인하세요.

Jake가 제안한 대로 페이지 로드 시간을 강화하려면 서비스 워커가 페이지 요청에 미치는 영향을 이해할 수 있어야 합니다.

Resource TimingUser Timing API는 많은 사이트 RUM (실제 사용자 모니터링) 인프라에서 중요한 구성요소입니다. 이를 통해 모든 사용자가 사이트의 실적을 보는 방식을 전체적으로 파악할 수 있기 때문입니다 (다른 사용 사례에서 콘텐츠 삽입을 감지함). 간단히 말해, 서비스 워커나 웹 워커가 없는 한 사이트에서 생성된 모든 웹 요청의 거의 모든 측면을 이해할 수 있습니다.

다음은 현재 도메인이 아닌 도메인에 전송된 모든 요청 목록을 가져오는 방법을 보여주는 간단한 예시입니다.

var getThirdPartyRequests = function() {
    var thirdPartyRequests = [];
    var requests = window.performance.getEntriesByType("resource");
    
    var currentHost = window.location.host

    for(var requestIdx = 0; requestIdx < requests.length; requestIdx++) {
    var request = requests[requestIdx];
    var url = new URL(request.name);
    var host = url.host;

    if(host != currentHost) {
        thirdPartyRequests.push(request);
    }
    }
    
    return thirdPartyRequests;
};

Resource Timing API와 User Timing API는 서비스 워커가 엔지니어의 눈에 띄어지기 전에 생성 및 구현되었으며 위의 코드로는 서비스 워커가 서비스 워커에 미치는 영향을 이해할 수 없었습니다.

Chrome 45 (2015년 7월 베타 버전)의 최근 변경사항은 모든 형태의 작업자 (웹 및 서비스 워커)가 Resource Timing 및 User Timing API에 액세스할 수 있는 기능을 도입하여 모든 사용자의 네트워크 성능을 파악할 수 있도록 하는 데 도움이 될 것입니다.

서비스 워커에서 성능 측정항목에 액세스

가장 큰 변화는 performance 객체를 worker 컨텍스트 (웹 및 ServiceWorker)에 추가한 것입니다. 이를 통해 이제 worker의 컨텍스트에서 생성된 모든 요청의 성능 타이밍을 파악하고 JS 실행 측정을 위한 자체 표시도 설정할 수 있습니다. 현재 창의 컨텍스트에서만 어떤 일이 일어나는지만 볼 수 있다면 다음과 같은 중요한 타이밍 정보를 놓칠 수 있습니다.

  • 서비스 워커의 oninstall 이벤트 내에서 수행된 fetch() 요청
  • 이제 onpush 이벤트의 데이터를 캐싱할 때 이루어진 fetch() 요청을 추적하여 사용자에게 표시되는 성능을 파악할 수 있습니다.
  • 마지막으로 onfetch 핸들러에 의해 생성되고 가로채인 fetch() 요청입니다.

마지막 요점이 중요합니다. 서비스 워커는 웹 UI와 네트워크 사이에 있는 프록시로 생각할 수 있습니다 windowperformance 객체는 호출하는 요청의 일부에 대한 타이밍과 정보만 볼 수 있습니다. 클라이언트와 네트워크 사이에 있는 서비스 워커에 관해서는 알지 못하므로 서비스 워커의 영향을 파악할 수 없습니다.

어떻게 사용할 수 있나요?

오프라인을 먼저 지원하는 일반적인 서비스 워커에는 나중에 사용할 수 있도록 모든 애셋을 다운로드하고 저장하는 설치 단계가 있습니다.

이 데이터가 사용될 수 있는 예로는 설치 단계의 타이밍 데이터를 기록하고 기록하여 실제 사용자의 실제 사용 방식을 바탕으로 설치 성능을 개선할 방법에 관한 측정된 결정을 내릴 수 있습니다.

self.addEventListener("install", function() {
    var urls = [
    '/',
    '/images/chrome-touch-icon-192x192.png',
    '/images/ic_add_24px.svg',
    '/images/side-nav-bg@2x.jpg',
    '/images/superfail.svg',
    '/scripts/voicememo-core.js',
    '/styles/voicememo-core.css',
    '/third_party/Recorderjs/recorder.js',
    '/third_party/Recorderjs/recorderWorker.js',
    '/third_party/Recorderjs/wavepcm.js',
    '/third_party/moment.min.js',
    '/favicon.ico',
    '/manifest.json'
    ];

    urls = urls.map(function(url) {
    return new Request(url, {credentials: 'include'});
    });

    event.waitUntil(
    caches
        .open(CACHE_NAME + '-v' + CACHE_VERSION)
        .then(function(cache) {
        // Fetch all the URL's and store in the cache
        return cache.addAll(urls);
        })
        .then(function () {
        // Analyze all the requests
        var requests = self.performance.getEntriesByType("resource");
        
        // Loop across all the requests and save the timing data.
        return;
        })
    );
});

오늘날 많은 사이트에서 대다수의 사용자가 사이트를 경험하는 방식을 파악하기 위해 RUM을 사용합니다. Google 애널리틱스와 같은 도구는 이미 Navigation Timing API를 사용하여 사이트 속도 데이터를 보고하지만 작업자 컨텍스트의 성능 분석을 포함하도록 업데이트해야 합니다.

Navigation Timing API가 서비스 워커에 도착하나요?

서비스 워커에는 기존 탐색이 없으므로 현재로서는 Navigation Timing API를 서비스 워커 컨텍스트에 추가할 계획이 없습니다. 여기서 흥미로운 점은 서비스 워커의 제어 대상 페이지 집합의 모든 탐색이 리소스 가져오기처럼 보인다는 점입니다. 이것만으로도 서비스 워커는 대부분의 성능 로직을 웹 앱에 중앙 집중화하는 매우 매력적인 방법입니다.

무엇이 달라졌는지 확인할 수 있나요?

논의 및 사양에 관심이 있습니다.