IE11과 다른 브라우저 전반에 적용되는 웹 애플리케이션의 실제 성능 이해하기

W3C 웹 성능 작업 그룹은 Google, Mozilla를 비롯한 커뮤니티 리더와 함께 탐색 타이밍, 리소스 타이밍, 사용자 타이밍, 성능 시간 표시줄 인터페이스를 표준화했습니다. 이러한 인터페이스를 사용하면 인공적인 환경에서 애플리케이션의 성능을 테스트하는 종합 테스트에 의존하지 않고도 실제 고객이 사용하는 웹 애플리케이션 환경이 어떤지 캡처하고 분석할 수 있습니다. 이 타이밍 데이터를 통해 웹 애플리케이션의 실제 성능을 개선할 기회를 확인할 수 있습니다. IE11에서는 이 모든 인터페이스가 지원됩니다. 이 인터페이스들의 실제 활용에 대해서는 성능 타이밍 테스트 드라이브를 확인하십시오.

성능 타이밍 테스트 드라이브를 통해 타이밍 API를 사용해볼 수 있음
성능 타이밍 테스트 드라이브를 통해 타이밍 API를 사용해볼 수 있음

성능 시간 표시줄

성능 시간 표시줄 사양은 W3C 권고안으로 게시되었으며 IE11과 Chrome 30에서 완전히 지원됩니다. 이 인터페이스를 사용하면 탐색, 리소스 가져오기, 애플리케이션에서 실행되는 스크립트를 실행하는 동안 소요된 시간에 대한 전체 보기를 확인할 수 있습니다. 이 사양은 모든 성능 메트릭이 실행해야 하는 최소 특성과 개발자들이 성능 메트릭의 형식을 검색할 때 사용할 수 있는 인터페이스를 둘 다 정의합니다.

모든 성능 메트릭은 다음과 같은 네 가지 특성을 지원해야 합니다.

  • name. 이 특성은 성능 메트릭의 고유 식별자를 저장합니다. 예를 들어 리소스의 경우에는 리소스의 해독된 URL이 될 것입니다.
  • entryType. 이 특성은 성능 메트릭의 형식을 저장합니다. 예를 들어 리소스의 메트릭은 "resouce"로 저장됩니다.
  • startTime. 이 특성은 성능 메트릭의 처음 기록한 타임스탬프를 저장합니다.
  • duration. 이 특성은 메트릭에 의해 기록 중인 이벤트의 전체 기간을 저장합니다.

모든 타이밍 데이터는 고분해능 시간 사양에서 정의한 DOMHighResTimeStamps 형식을 사용한 고분해능 시간에 기록됩니다. 고분해능 시간 값은 1970년 1월 1일 UTC부터 밀리초 단위의 시간 값을 측정하는 DOMTimeStamps와는 달리 문서 탐색 시작부터 최소 마이크로초 분해능으로 측정됩니다. 예를 들어 performance.now()를 사용하는 현재 시간, Date.now()와 유사한 고분해능 시간을 확인하면 다음과 같이 현재 시간을 해석할 수 있습니다.

> performance.now();

4038.2319370044793

 

> Date.now()

1386797626201

또한 이 시간 값은 클럭 스큐나 조정의 영향을 받지 않다는 이점이 있습니다. What Time Is It 테스트 드라이브를 살펴보면서 고분해능 시간의 용도를 파악할 수 있습니다.

다음 인터페이스를 사용하여 호출 시점에 기록된 성능 메트릭의 목록을 검색할 수 있습니다. startTime과 기간, 메트릭으로 제공되는 그 외 모든 특성을 사용하여 고객이 경험하는 페이지 성능의 전체 시간 표시줄 보기를 얻을 수 있습니다.

PerformanceEntryList getEntries();

PerformanceEntryList getEntriesByType(DOMString entryType);

PerformanceEntryList getEntriesByName(DOMString name, optional DOMString entryType);

getEntries메서드는 페이지의 모든 성능 메트릭 목록을 반환하는 것에 반해 다른 메서드는 이름 또는 형식에 따라 특정 항목을 반환합니다. 대부분의 개발자들은 메트릭 전체 목록에 JSON 문자열화를 사용하고, 분석도 클라이언트에서 하는 것이 아니라 서버로 결과를 보내서 분석할 것으로 생각합니다.

다양한 성능 메트릭을 하나하나 자세히 살펴보겠습니다. 탐색, 리소스, 마크, 측정 메트릭입니다.

탐색 타이밍

탐색 타이밍 인터페이스는 웹 애플리케이션 탐색의 각 단계에 대해 정확한 타이밍 측정을 제공합니다. 탐색 타이밍 L1 사양은 IE9, Chrome 28, Firefox 23 이후 완벽하게 지원된 W3C 권고안으로 게시되었습니다. 탐색 타이밍 L2 사양은 첫 번째 공개 작업 초안으로서 IE11에서 지원됩니다.

개발자들은 탐색 타이밍을 통해 서버에서 페이지를 받는 데 소요되는 시간 등 정확한 전체 페이지 로드 시간을 알 수 있을 뿐만 아니라 그 시간이 각 네트워킹 및 DOM 처리 단계에 소요된 부분, 즉 언로드, 리디렉션, 앱 캐시, DNS, TCP, 요청, 응답, DOM 처리, 로드 이벤트 분류도 알 수 있습니다. 아래 스크립트는 탐색 타이밍 L2를 사용하여 이 상세 정보를 받습니다. 이 메트릭의 입력 형식은 "navigation"이지만 이름은 "document"입니다. IE 테스트 드라이브 사이트에서 탐색 타이밍 데모를 확인하십시오.

<!DOCTYPE html>

<html>

<head></head>

<body>

<script>

 function sendNavigationTiming() {

   var nt = performance.getEntriesByType('navigation')[0];

   var navigation = ' Start Time: ' + nt.startTime + 'ms';

   navigation += ' Duration: ' + nt.duration + 'ms';

   navigation += ' Unload: ' + (nt.unloadEventEnd - nt.unloadEventStart) + 'ms';

   navigation += ' Redirect: ' + (nt.redirectEnd - nt.redirectStart) + 'ms';

   navigation += ' App Cache: ' + (nt. domainLookupStart - nt.fetchStart) + 'ms';

   navigation += ' DNS: ' + (nt.domainLookupEnd - nt.domainLookupStart) + 'ms';

   navigation += ' TCP: ' + (nt.connectEnd - nt.connectStart) + 'ms';

   navigation += ' Request: ' + (nt.responseStart - nt.requestStart) + 'ms';

   navigation += ' Response: ' + (nt.responseEnd - nt.responseStart) + 'ms';

   navigation += ' Processing: ' + (nt.domComplete - nt.domLoading) + 'ms';

   navigation += ' Load Event: ' + (nt.loadEventEnd - nt.loadEventStart) + 'ms';

   sendAnalytics(navigation);

 }

</script>

</body>

</html>

각 네트워크 단계에 소요된 세부 시간을 살펴보면 성능 문제를 더 잘 진단하고 수정할 수 있습니다. 예를 들어, 리디렉션 시간이 길다고 느끼면 리디렉션을 사용하지 않는 방법을 고려할 수 있고, DNS 시간이 길면 DNS 캐싱 서비스를 사용하고, 요청 시간이 길면 사용자와 더 가까운 CND를 사용하고, 응답 시간이 길면 콘텐츠를 GZip할 수 있습니다. 네트워크 성능 개선에 대한 팁과 힌트는 이 동영상을 확인하십시오.

두 가지 탐색 타이밍 사양 버전의 주된 차이점은 타이밍 데이터 액세스와 시간 측정 방법입니다. L1 인터페이스는 1970년 1월 01일부터 이 특성을 performance.timing 개체로 밀리초 단위로 정의합니다. L2 인터페이스를 사용하면 동일한 특성을 성능 시간 표시줄 메서드를 사용하여 검색할 수 있고, 이 특성을 시간 표시줄 보기에 더 쉽게 둘 수 있으며, 이것을 고분해능 타이머로 기록할 수 있습니다.

탐색 타이밍 이전에는 개발자들이 일반적으로 아래 코드 샘플의 경우처럼 문서 헤드에 JavaScript를 작성하여 페이지 로드 성능을 측정하려고 시도했습니다. IE 테스트 드라이브 사이트에서 이 기술의 데모를 확인하십시오.

<!DOCTYPE html>

<html>

<head>

<script>

    var start = Date.now();

 

    function sendPageLoad() {

        var now = Date.now();

        var latency = now - start;

        sendAnalytics('Page Load Time: ' + latency);

    }

 

</script>

</head>

<body onload='sendPageLoad()'>

</body>

</html>

하지만 이 기술은 서버에서 페이지를 받는 데 소요되는 시간이 포함되지 않아 페이지 로드 성능을 정확히 측정할 수 없습니다. 또한, 문서 헤드에 JavaScript를 실행하는 것은 일반적으로 좋은 성능 패턴이 아닙니다.

리소스 타이밍

리소스 타이밍은 페이지에 리소스 가져오기에 대한 정확한 타이밍 정보를 제공합니다. 리소스 타이밍은 탐색 타이밍과 비슷하게 가져온 리소스의 리디렉션, DNS, TCP, 요청, 응답 단계에 대한 자세한 타이밍 정보를 제공합니다. 리소스 타이밍 사양은 IE10과 Chrome 30에서의 지원이 포함된 W3C 권고 후보안으로 게시되었습니다.

다음 샘플 코드는 getEntriesByType 메서드를 사용하여 <img> 요소로 시작되는 모든 리소스를 가져옵니다. 리소스의 입력 형식은 "resource"이고 이름은 리소스의 해독된 URL이 될 것입니다. IE 테스트 드라이브 사이트에서 리소스 타이밍 데모를 확인하십시오.

<!DOCTYPE html>

<html>

  <head>

  </head>

  <body onload='sendResourceTiming()'>

    <img src='https://some-server/image1.png'>

    <img src='https://some-server/image2.png'>

 

    <script>

        function sendResourceTiming()

        {

            var resourceList = window.performance.getEntriesByType('resource');

            for (i = 0; i < resourceList.length; i++)

            {

                if (resourceList[i].initiatorType == 'img')

                {

                    sendAnalytics('Image Fetch Time: ' + resourceList[i].duration);

                }

            }

        }

    </script>

  </body>

</html>

보안을 위해 cross-origin 리소스는 시작 시간과 기간만 표시하고 상세 타이밍 특성은 0으로 설정됩니다. 이렇게 하면 상세 네트워크 시간을 확인하여 응답이 캐시에 있는지를 확인함으로써 조직의 일원임을 확인하는 통계적 지문 인식 문제를 방지할 수 있습니다. Cross-origin 서버는 타이밍 데이터를 사용자와 공유하고자 할 경우 timing-allow-origin HTTP 헤더를 전송할 수 있습니다.

사용자 타이밍

사용자 타이밍은 애플리케이션의 스크립트 실행에 대한 상세 타이밍 정보를 제공하여 상세 네트워크 타이밍 정보를 제공하는 탐색 타이밍 및 리소스 타이밍을 보완합니다. 사용자 타이밍을 사용하면 네트워크 타이밍 데이터와 같은 시간 표시줄 보기로 스크립트 타이밍 정보를 표시할 수 있어 앱 성능에 대한 전체적인 이해를 얻을 수 있습니다. 사용자 타이밍 사양은 IE10과 Chrome 30에서의 지원이 포함된 W3C 권고안으로 게시되었습니다

사용자 타이밍 인터페이스는 스크립트 타이밍 측정에 사용되는 두 가지 메트릭, 즉 마크와 측정 메트릭을 정의합니다. 마크는 스크립트 진행 중 기준 시점에서의 고분해능 타임스탬프를 나타냅니다. 측정은 두 마크의 차이를 나타냅니다.

다음 메서드를 사용하여 마크와 측정을 생성할 수 있습니다.

void mark(DOMString markName);

void measure(DOMString measureName, optional DOMString startMark, optional DOMString endMark);

스크립트에 마크와 측정을 추가한 후에는 getEntry, getEntryByType 또는 getEntryByName 메서드를 사용하여 타이밍 데이터를 검색할 수 있습니다. 마크의 입력 형식은 "mark"이고 측정의 입력 형식은 "measure"입니다.

다음 샘플 코드는 마크와 측정 메서드를 사용하여 doTask1()과 doTask2() 메서드를 실행하는 데 소요되는 시간을 측정합니다. IE 테스트 드라이브 사이트에서 사용자 타이밍 데모를 확인하십시오.

<!DOCTYPE html>

<html>

  <head>

  </head>

  <body onload='doWork()'>

    <script>

        function doWork()

        {

            performance.mark('markStartTask1');

            doTask1();

            performance.mark('markEndTask1');

           

            performance.mark('markStartTask2');

            doTask2();

            performance.mark('markEndTask2');

 

            performance.measure('measureTask1', 'markStartTask1', 'markEndTask1');

            performance.measure('measureTask2', 'markStartTask2', 'markEndTask2');

 

            sendUserTiming(performance.getEntries());

        }

    </script>

  </body>

</html>

이 모든 인터페이스를 설계할 수 있도록 도와준 W3C 웹 성능 작업 그룹, 그리고 상호 운용성에 대한 선견지명을 가지고 이러한 인터페이스의 구현을 위해 노력한 브라우저 공급업체들에게 감사의 말씀을 드립니다. 웹 개발자들은 이러한 인터페이스를 통해 어떻게 애플리케이션 성능을 향상시킬 수 있는지를 실질적으로 측정하고 이해할 수 있게 되었습니다.

IE11에서 웹 앱과의 성능 측정 인터페이스를 직접 사용해 보시고 Connect를 통해 의견을 보내 주십시오.

감사합니다.

Internet Explorer 프로그램 관리자, Jatinder Mann