Chrome 102의 DevTools에 새로운 실험용 패널인 성능 통계가 표시됩니다. 이 게시물에서는 새로운 패널을 개발한 이유뿐만 아니라 기술적인 문제와 그 과정에서 내린 결정에 대해서도 설명합니다.

다른 패널을 빌드해야 하는 이유
(아직 확인하지 못하셨다면 성능 통계 패널을 구축하는 이유와 이를 통해 웹사이트 성능에 관한 실행 가능한 통계를 얻는 방법을 설명하는 동영상을 게시했습니다.)
기존 실적 패널은 웹사이트의 모든 데이터를 한곳에서 확인할 수 있는 유용한 리소스이지만, 다소 부담스러울 수 있습니다. 성능 전문가가 아닌 경우 무엇을 찾아야 하는지, 녹화의 어떤 부분이 관련이 있는지 정확히 알기 어렵습니다.
트레이스 타임라인을 확인하고 데이터를 검사할 수 있을 뿐만 아니라 DevTools에서 살펴볼 만한 주요 '통계'로 간주하는 항목의 유용한 목록을 확인할 수 있는 통계 패널을 입력하세요. 인사이트에서는 렌더링 차단 요청, 레이아웃 이동, 긴 작업과 같은 문제를 식별합니다. 이러한 문제는 모두 웹사이트의 페이지 로드 성능, 특히 사이트의 Core Web Vitals (CWV) 점수에 부정적인 영향을 미칠 수 있습니다. 성능 통계에서는 문제 신고와 함께 CWV 점수를 개선하기 위한 실행 가능한 제안을 제공하고 추가 리소스 및 문서 링크를 제공합니다.

이 패널은 실험 단계에 있으며 여러분의 의견을 기다립니다. 버그가 발생하거나 사이트 실적을 개선하는 데 도움이 될 만한 기능 요청이 있으면 알려주세요.
Google에서 실적 통계를 구축한 방법
다른 DevTools와 마찬가지로 TypeScript로 성능 통계를 빌드하고 lit-html로 지원되는 웹 구성요소를 사용하여 사용자 인터페이스를 빌드했습니다. Performance Insights의 차이점은 기본 UI 인터페이스가 HTML canvas 요소이고 타임라인이 이 캔버스에 그려진다는 것입니다. 이 캔버스를 관리하는 데 많은 복잡성이 따릅니다. 올바른 위치에 올바른 세부정보를 그리는 것뿐만 아니라 마우스 이벤트 (예: 사용자가 캔버스를 클릭한 위치)를 관리해야 하기 때문입니다. 그린 이벤트가 클릭되었는지 확인하고 캔버스를 효과적으로 다시 렌더링합니다.
단일 캔버스에 여러 트랙
특정 웹사이트의 경우 렌더링하려는 여러 '트랙'이 있으며 각 트랙은 서로 다른 데이터 카테고리를 나타냅니다. 예를 들어 통계 패널에는 기본적으로 다음 세 가지 트랙이 표시됩니다.
패널에 기능이 계속 추가됨에 따라 더 많은 트랙이 추가될 것으로 예상됩니다.
처음에는 이러한 트랙 각각이 자체 <canvas>를 렌더링하여 기본 뷰가 세로로 쌓인 여러 캔버스 요소가 되도록 했습니다. 이렇게 하면 각 트랙이 격리된 상태로 렌더링될 수 있고 트랙이 경계 밖으로 렌더링될 위험이 없으므로 트랙 수준에서 렌더링이 간소화되지만, 이 접근 방식에는 다음과 같은 두 가지 주요 문제가 있습니다.
canvas 요소는 (다시) 렌더링하는 데 비용이 많이 듭니다. 캔버스가 하나인 경우보다 캔버스가 여러 개인 경우가 더 비용이 많이 듭니다. 캔버스가 더 큰 경우에도 마찬가지입니다.
여러 트랙에 걸쳐 있는 오버레이 (예: FCP 시간과 같은 이벤트를 표시하는 세로선)를 렌더링하는 것은 복잡해집니다. 여러 캔버스에 렌더링하고 모두 함께 렌더링되고 올바르게 정렬되도록 해야 합니다.
전체 UI에 하나의 canvas를 사용하면 각 트랙이 올바른 좌표에서 렌더링되고 다른 트랙으로 오버플로되지 않도록 하는 방법을 파악해야 했습니다. 예를 들어 특정 트랙의 높이가 100px인 경우 높이가 120px인 항목이 렌더링되어 아래 트랙으로 번지도록 허용할 수 없습니다. 이 문제를 해결하기 위해 clip를 사용할 수 있습니다. 각 트랙을 렌더링하기 전에 표시되는 트랙 창을 나타내는 직사각형을 그립니다. 이렇게 하면 이 범위를 벗어나 그려진 모든 경로가 캔버스에 의해 잘립니다.
canvasContext.beginPath();
canvasContext.rect(
trackVisibleWindow.x, trackVisibleWindow.y, trackVisibleWindow.width, trackVisibleWindow.height);
canvasContext.clip();
또한 각 트랙이 세로 위치를 알지 못하도록 했습니다. 각 트랙은 (0, 0)에서 렌더링되는 것처럼 자체적으로 렌더링되어야 하며 전체 트랙 위치를 관리하는 상위 수준 구성요소 (TrackManager)가 있습니다. 이 작업은 지정된 (x, y) 위치만큼 캔버스를 변환하는 translate를 사용하여 실행할 수 있습니다. 예를 들면 다음과 같습니다.
canvasContext.translate(0, 10); // Translate by 10px in the y direction
canvasContext.rect(0, 0, 10, 10); // draw a rectangle at (0, 0) that’s 10px high and wide
rect 코드에서 0, 0을 위치로 설정했지만 적용된 전체 변환으로 인해 직사각형이 0, 10에 렌더링됩니다. 이렇게 하면 (0, 0)에서 렌더링하는 것처럼 트랙을 기반으로 작업할 수 있으며, 트랙 관리자가 각 트랙을 렌더링할 때 트랙을 변환하여 각 트랙이 이전 트랙 아래에 올바르게 렌더링되도록 할 수 있습니다.
트랙 및 하이라이트를 위한 화면 밖 캔버스
캔버스 렌더링은 상대적으로 비용이 많이 들기 때문에 사용자가 인사이트 패널을 사용할 때 패널이 원활하고 반응성이 유지되도록 하고자 합니다. 전체 캔버스를 다시 렌더링해야 하는 경우가 있습니다. 예를 들어 확대/축소 수준을 변경하면 처음부터 다시 시작하여 모든 항목을 다시 렌더링해야 합니다. 캔버스 다시 렌더링은 특히 비용이 많이 듭니다. 작은 부분만 다시 렌더링할 수 없고 전체 캔버스를 지우고 다시 그려야 하기 때문입니다. 도구에서 필요한 최소 작업을 계산하고 모든 항목을 삭제한 후 다시 시작하지 않는 DOM 다시 렌더링과는 다릅니다.
시각적 문제가 발생한 한 영역은 강조 표시였습니다. 창에서 측정항목 위로 마우스를 가져가면 타임라인에서 측정항목이 강조 표시되고, 특정 이벤트의 통계 위로 마우스를 가져가면 해당 이벤트 주위에 파란색 테두리가 그려집니다.
이 기능은 강조 표시를 트리거하는 요소 위로 마우스가 이동하는 것을 감지한 다음 강조 표시를 기본 캔버스에 직접 그리는 방식으로 처음 구현되었습니다. 하이라이트를 삭제해야 할 때 문제가 발생합니다. 모든 것을 다시 그려야 하기 때문입니다. 강조 표시가 있던 영역만 다시 그리는 것은 불가능하지만 (대대적인 아키텍처 변경 없이는) 항목 하나 주변의 파란색 테두리를 삭제하기 위해 캔버스 전체를 다시 그리는 것은 과도한 조치로 느껴졌습니다. 또한 마우스를 여러 항목 위로 빠르게 이동하여 여러 강조 표시를 연속으로 트리거하면 시각적으로 지연되었습니다.
이 문제를 해결하기 위해 UI를 두 개의 오프 스크린 캔버스로 분할했습니다. 트랙이 렌더링되는 'main' 캔버스와 하이라이트가 그려지는 'highlights' 캔버스입니다. 그런 다음 이러한 캔버스를 사용자에게 화면에 표시되는 단일 캔버스에 복사하여 렌더링합니다. 캔버스 컨텍스트에서 drawImage 메서드를 사용할 수 있으며, 이 메서드는 다른 캔버스를 소스로 사용할 수 있습니다.
이렇게 하면 강조 표시를 삭제해도 기본 캔버스가 다시 그려지지 않습니다. 대신 화면 캔버스를 지운 다음 표시되는 캔버스에 기본 캔버스를 복사할 수 있습니다. 캔버스를 복사하는 행위는 비용이 저렴하지만 그림은 비용이 많이 듭니다. 따라서 하이라이트를 별도의 캔버스로 이동하면 하이라이트를 사용 설정 및 사용 중지할 때 비용이 발생하지 않습니다.
포괄적으로 테스트된 트레이스 파싱
처음부터 새로운 기능을 빌드하면 이전에 선택한 기술을 되돌아보고 개선할 수 있습니다. 개선하고 싶었던 점 중 하나는 코드를 거의 완전히 별개의 두 부분으로 명시적으로 분할하는 것이었습니다.
트레이스 파일을 파싱하고 필요한 데이터를 가져옵니다. 트랙 세트를 렌더링합니다.
파싱 (1부)을 UI 작업 (2부)과 분리하여 견고한 파싱 시스템을 구축할 수 있었습니다. 각 트레이스는 다양한 문제를 담당하는 일련의 핸들러를 통해 실행됩니다. LayoutShiftHandler는 레이아웃 변경에 필요한 모든 정보를 계산하고 NetworkRequestsHandler는 네트워크 요청을 가져오는 작업만 처리합니다. 트레이스의 여러 부분을 담당하는 핸들러가 서로 다른 명시적 파싱 단계를 거치는 것도 유용합니다. 트레이스 파싱은 매우 복잡해질 수 있으며 한 번에 한 가지 문제에 집중할 수 있으면 도움이 됩니다.
또한 DevTools에서 녹화하고 저장한 후 테스트 제품군의 일부로 로드하여 트레이스 파싱을 포괄적으로 테스트할 수 있었습니다. 실제 트레이스로 테스트할 수 있고, 쓸모없어질 수 있는 가짜 트레이스 데이터를 대량으로 구축하지 않아도 되므로 좋습니다.
캔버스 UI 스크린샷 테스트
테스트 주제로 돌아와서, 일반적으로 프런트엔드 구성요소를 브라우저에 렌더링하고 예상대로 작동하는지 확인하여 테스트합니다. 클릭 이벤트를 디스패치하여 업데이트를 트리거하고 구성요소가 생성하는 DOM이 올바른지 어설션할 수 있습니다. 이 접근 방식은 잘 작동하지만 캔버스에 렌더링하는 것을 고려할 때는 문제가 있습니다. 캔버스를 검사하고 캔버스에 그려진 내용을 확인할 방법이 없기 때문입니다. 따라서 렌더링한 후 쿼리하는 일반적인 접근 방식은 적합하지 않습니다.
테스트 적용 범위를 확보하기 위해 스크린샷 테스트를 사용했습니다. 각 테스트는 캔버스를 실행하고, 테스트하려는 트랙을 렌더링한 다음 캔버스 요소의 스크린샷을 찍습니다. 그러면 이 스크린샷이 코드베이스에 저장되고 향후 테스트 실행에서는 저장된 스크린샷과 생성된 스크린샷을 비교합니다. 스크린샷이 다르면 테스트가 실패합니다. 또한 렌더링을 의도적으로 변경하여 테스트를 업데이트해야 하는 경우 테스트를 실행하고 스크린샷 업데이트를 강제하는 플래그도 제공합니다.
스크린샷 테스트는 완벽하지 않고 다소 무디기 때문에 더 구체적인 어설션이 아닌 전체 구성요소가 예상대로 렌더링되는지만 테스트할 수 있습니다. 처음에는 모든 단일 구성요소 (HTML 또는 캔버스)가 올바르게 렌더링되도록 스크린샷 테스트를 과도하게 사용했습니다. 이로 인해 테스트 모음이 크게 느려졌으며, 미미하고 거의 관련이 없는 UI 조정 (예: 미묘한 색상 변경 또는 항목 간 여백 추가)으로 인해 여러 스크린샷이 실패하고 업데이트해야 하는 문제가 발생했습니다. 이제 스크린샷 사용을 축소하고 캔버스 기반 구성요소에만 사용하고 있으며, 이 균형이 지금까지는 잘 작동했습니다.
결론
새로운 성능 통계 패널을 구축하는 과정은 팀에게 매우 즐겁고 유익한 경험이었습니다. 트레이스 파일, 캔버스 작업 등 다양한 내용을 배웠습니다. 새 패널을 유용하게 사용하시기 바라며, 의견을 보내주시면 반영하도록 하겠습니다.
Performance Insights 패널에 대해 자세히 알아보려면 성능 통계: 웹사이트 성능에 관한 실행 가능한 통계 얻기를 참고하세요.
미리보기 채널 다운로드
Chrome Canary, Dev 또는 베타를 기본 개발 브라우저로 사용하는 것이 좋습니다. 미리보기 채널을 사용하면 최신 DevTools 기능에 액세스하고, 최신 웹 플랫폼 API를 테스트하고, 사용자가 문제를 발견하기 전에 사이트에서 문제를 찾을 수 있습니다.
Chrome DevTools팀에 문의하기
다음 옵션을 사용하여 새로운 기능, 업데이트 또는 DevTools와 관련된 기타 사항을 논의하세요.
- crbug.com에서 의견 및 기능 요청을 제출합니다.
- DevTools에서 옵션 더보기 > 도움말 > DevTools 문제 신고를 사용하여 DevTools 문제를 알립니다.
- @ChromeDevTools에 트윗합니다.
- 'DevTools의 새로운 기능' YouTube 동영상 또는 'DevTools 팁' YouTube 동영상에 댓글을 남깁니다.