서비스 워커에서 성능 측정

제이크 아치볼드는 개발자 기술이 퇴화하고 사라질까 걱정하는 것 외에도 서비스 워커를 지능적으로 사용하면 사이트 또는 앱의 성능을 대폭 개선할 수 있다고 강력하게 주장했습니다. 동영상을 시청하여 개요를 알아보세요.

제이크가 제안한 대로 페이지 로드 시간을 개선하려면 서비스 워커가 페이지 요청에 어떤 영향을 미치는지 이해해야 합니다.

리소스 타이밍사용자 타이밍 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월 베타)의 최근 변경사항은 모든 형태의 작업자 (웹 및 서비스 워커)가 리소스 타이밍 및 사용자 타이밍 API에 액세스할 수 있는 기능을 도입하여 모든 사용자의 네트워크 성능을 최적화하는 데 도움이 됩니다.

서비스 워커에서 실적 측정항목에 액세스

가장 큰 변화는 performance 객체가 Worker 컨텍스트 (Web 및 ServiceWorkers)에 추가된 것입니다. 이제 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를 사용하여 사이트 속도 데이터를 보고하고 있지만, Worker 컨텍스트의 성능 분석을 포함하도록 업데이트해야 합니다.

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

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

변경된 사항을 확인할 수 있나요?

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