웹 성능, 밀리초 분해능으로는 충분하지 않을 때
시간을 측정할 때 밀리초 분해능으로는 만족할 만한 정확성을 얻지 못할 때가 있습니다. 이 문제를 해결하기 위해 W3C 웹 성능 작업 그룹은 업계 및 커뮤니티 리더와 함께 고분해능 시간 규격을 표준화했습니다. 이번 주에 이 규격은 제안 권고안(PR)으로 게시되어 최신 브라우저에 널리 채택되고 있습니다. What Time is it? 테스트 드라이브 데모를 통해 API가 어떻게 작동하는지 살펴보시기 바랍니다.
이 규격은 아이디어에서 PR로 게시되기까지 8개월이 걸렸습니다. 표준화 단계에서 PR은 웹 표준이 공식 W3C 권고안이 되는 마지막 단계입니다. 또한 이 인터페이스는 Internet Explorer 10, Firefox 15는 물론 Chrome 22의 접두사를 비롯한 다양한 브라우저에 채택되고 있으며, 업계와 커뮤니티가 W3C에서 손을 맞잡았을 때 어떤 놀라운 일을 할 수 있는 보여주는 좋은 사례입니다.
그렇다면 왜 밀리초로는 충분하지 않을까요? 그동안 웹 플랫폼에서 시간을 측정하는 데 사용된 방법은 Date.now() 또는 DOMTimeStamp 방식의 몇몇 JavaScript Date 개체 형식을 사용하는 것이었습니다. Date 개체는 1970년 1월 1일 UTC부터의 시간 값을 나타냅니다. 실용적인 목적을 위해서 지금까지는 이러한 시간의 정의가 1970년 1월 1일부터 285,616년 UTC까지의 시간을 나타내기에는 충분했습니다.
예를 들면 이 글을 쓰고 있는 지금 Date.now() IE10 개발자 도구 콘솔의 시간 값은 1350509874902입니다. 이 13자리의 숫자는 1970년 1월 1일이라는 시간 기준을 원점으로 한 밀리초를 나타내는 것입니다. 이 시간은 2012년 10월 17일 21:37:54 UTC에 해당합니다.
이러한 정의가 현재의 달력 시간을 결정하는 데에는 계속 유용하다고 하더라도 효율적이지 못한 경우가 간혹 있습니다. 예를 들어 초당 60프레임(16.667밀리초당 1프레임)으로 부드럽게 움직이는 애니메이션을 만드는 개발자들에게는 이것이 유용할 것입니다. 하지만 마지막으로 만든 프레임 드로잉의 콜백을 측정하는 단순한 방법을 사용하여 즉각적인 FPS를 계산하면 58.8FPS(1/17) 또는 62.5FPS(1/16)로밖에 결정되지 않습니다.
이와 유사하게 서브 밀리초 분해능 역시 경과 시간, 예를 들면 사용자의 네트워크와 스크립트 타이밍을 계측하기 위한 탐색 타이밍, 리소스 타이밍, 사용자 타이밍 API를 정확하게 측정하거나 애니메이션을 동기화하고 오디오와 애니메이션을 통합하기에 적합합니다.
이 문제를 해결하기 위해 고분해능 시간 규격은 최소 마이크로초(1,000분의 1밀리초) 분해능이라는 새로운 시간 기반을 정의합니다. 1970년 1월 1일 UTC부터 측정한 시간을 나타내는 비트의 개수를 줄이고 가독성을 높이기 위해 이 새로운 시간 기반인 performance.timing.navigationStart는 문서 탐색을 시작한 시간을 측정합니다.
이 규격은 유사한 방식인 Date.now()처럼 고분해능으로 현재의 시간을 결정하는 performance.now()를 정의합니다. DOMHighResTimeStamp는 고분해능 시간 값을 정의하는 DOMTimeStamp와 유사한 방식입니다.
예를 들어 IE10 개발자 도구 콘솔의 performance.now()와 Date.com()으로 이 블로그를 쓰고 있는 현재 시간을 보면 다음 두 값을 볼 수 있습니다.
performance.now(): 196.304879519774
Date.now(): 1350509874902
만약 두 시간 값이 같은 인스턴스를 나타내는 경우라도 서로 다른 시간 기반으로 측정된 것입니다. performance.now() 시간 값의 가독성이 월등히 좋습니다.
문서 탐색이 시작될 때부터 고분해능 시간이 측정되듯이 하위 문서 내의 performance.now()는 루트 문서가 아닌 하위 문서의 탐색을 시작할 때부터 측정됩니다. 예를 들어 same-origin iFrame A와 cross-origin iFrame B가 있는 한 문서에서 루트 문서의 탐색을 시작한 후 iFrame A에서는 약 5밀리초 뒤에 iFrame B에서는 약 10밀리초 뒤에 탐색이 이루어졌다고 가정해 보겠습니다. 만일 루트 문서의 탐색을 시작한 후에 15밀리초의 정확한 순간을 측정한다면 performance.now()가 다른 컨텍스트에 불러온 다음 값을 얻을 수 있습니다.
iFrame B에서 performance.now(): 5.123ms
iFrame A에서 performance.now(): 10.123ms
루트 문서에서 performance.now(): 15.123ms
불특정 컨텍스트에서 Date.now(): 134639846051ms
표: Date.now()가 1970년 1월 1일부터 시간을 측정한 반면 performance.now()는 문서 탐색을 시작한 시간부터 측정
이러한 설계를 통해 cross-origin iFrame에서 상위 생성 데이터의 손실을 방지할 수 있을 뿐만 아니라, 시작에 비례하여 시간을 측정할 수도 있습니다. 예를 들어 사용자가 하위 문서 내에서 서버가 리소스 요청에 걸리는 시간을 결정하기 위해 리소스 타이밍 인터페이스(고분해능 시간을 사용)를 사용하면 루트 문서에 하위 문서를 추가하여 계정에 적용시킬 필요가 없습니다.
만약 교차 프레임 시간을 비교하고 싶다면 top.performance.now()에 루트 문서의 탐색이 시작되는 시간 값을 요청하면 됩니다. 이 값은 모든 same-origin iFrame과 같은 것입니다.
이 API가 Date.now()에 비해 뛰어난 또 다른 중요한 장점은 performance.now()가 일정하게 증가하여 클럭 스큐(clock skew)를 관리하거나 조정할 필요가 없다는 점입니다. 후속 콜과 performance.now()의 차이는 절대 음수가 될 수 없습니다. 반면에 Date.now()는 아직 이를 보증해 주지 않으며, 데이터 분석을 통해 시간이 음수가 된 사례들이 보고된 바 있습니다.
고분해능 시간은 새로운 아이디어가 얼마나 빠르게 상호 운용성 표준(개발자가 최신 HTML5 지원 브라우저에 의존할 수 있는)이 될 수 있는가를 보여주는 또 다른 훌륭한 예입니다. 이 API를 설계할 수 있도록 도와준 W3C 웹 성능 작업 그룹, 그리고 상호 운용성에 대한 선견지명을 가지고 급속한 시행을 가능하게 한 브라우저 공급업체들에게 감사의 말씀을 드립니다.
감사합니다.
Internet Explorer 프로그램 관리자
Jatinder Mann