새로운 Lighthouse API를 사용해 사용자 흐름 전반에서 성능과 권장사항을 측정하세요.
Lighthouse는 초기 페이지 로드 중에 성능과 권장사항을 테스트하는 데 유용한 도구입니다. 그러나 기존에는 Lighthouse를 사용하여 다음과 같은 페이지 수명의 다른 측면을 분석하기가 어려웠습니다.
- 캐시가 있는 페이지 로드
- 서비스 워커가 활성화된 페이지
- 잠재적 사용자 상호작용 고려
즉, Lighthouse에서 중요한 정보를 놓칠 수 있습니다. Core Web Vitals는 캐시가 비어 있는 페이지 로드뿐만 아니라 모든 페이지 로드를 기반으로 합니다. 또한 누적 레이아웃 변경 (CLS)과 같은 측정항목은 페이지가 열려 있는 전체 시간 동안 측정할 수 있습니다.
Lighthouse에는 페이지의 전체 기간 중 어느 시점에서든 실험실 테스트를 할 수 있는 새로운 사용자 흐름 API가 있습니다. Puppeteer는 페이지 로드를 스크립트로 작성하고 합성 사용자 상호작용을 트리거하는 데 사용되며 Lighthouse는 여러 가지 방법으로 호출하여 이러한 상호작용 중에 주요 통계를 캡처할 수 있습니다. 즉, 페이지 로드 중에 그리고 페이지와 상호작용하는 동안 성능을 측정할 수 있습니다. 접근성 검사는 초기 뷰뿐만 아니라 결제 흐름 내부에서 실행하여 회귀가 없는지 확인할 수 있습니다.
작동하는 사용자 흐름을 보장하도록 작성된 거의 모든 Puppeteer 스크립트에서 이제 어느 시점에서든 Lighthouse를 삽입하여 전체적으로 성능과 권장사항을 측정할 수 있습니다. 이 튜토리얼에서는 사용자 흐름의 다양한 부분(탐색, 스냅샷, 기간)을 측정할 수 있는 새로운 Lighthouse 모드를 설명합니다.
설정
사용자 흐름 API는 아직 미리보기 버전이지만 현재 Lighthouse에서 사용할 수 있습니다. 아래 데모를 사용해 보려면 Node 버전 14 이상이 필요합니다. 빈 디렉터리를 만들고 다음을 실행합니다.
# Default to ES modules.
echo '{"type": "module"}' > package.json
# Init npm project without the wizard.
npm init -y
# Dependencies for these examples.
npm install lighthouse puppeteer open
탐색
새로운 Lighthouse '탐색' 모드는 사실 지금까지 표준 Lighthouse 동작인 페이지의 콜드 로드 분석에 이름을 붙인 것입니다. 이 모드는 페이지 로드 속도를 모니터링하는 데 사용되지만 사용자 흐름을 통해 새로운 통계를 얻을 수도 있습니다.
페이지 로드를 캡처하는 Lighthouse 스크립트를 작성하려면 다음 단계를 따르세요.
- Puppeteer를 사용하여 브라우저를 엽니다.
- Lighthouse 사용자 흐름을 시작합니다.
- 타겟 URL로 이동합니다.
import fs from 'fs';
import open from 'open';
import puppeteer from 'puppeteer';
import {startFlow} from 'lighthouse/lighthouse-core/fraggle-rock/api.js';
async function captureReport() {
const browser = await puppeteer.launch({headless: false});
const page = await browser.newPage();
const flow = await startFlow(page, {name: 'Single Navigation'});
await flow.navigate('https://web.dev/performance-scoring/');
await browser.close();
const report = await flow.generateReport();
fs.writeFileSync('flow.report.html', report);
open('flow.report.html', {wait: false});
}
captureReport();
가장 간단한 흐름입니다. 보고서를 열면 단일 단계만 포함된 요약 보기가 표시됩니다. 이 단계를 클릭하면 해당 탐색에 대한 기존 Lighthouse 보고서가 표시됩니다.
Lighthouse의 일반적인 방식에 따라 이 페이지는 먼저 모든 캐시 또는 로컬 저장소가 지워진 상태로 로드되지만 사이트를 방문하는 실제 사용자는 비활성 캐시와 활성 캐시가 혼합된 상태로 방문합니다. 따라서 이와 같은 비활성 로드와 아직 활성 상태인 캐시를 사용하여 페이지로 돌아오는 사용자 간에 큰 성능 차이가 발생할 수 있습니다.
웜 로드 캡처
이 스크립트에 두 번째 탐색을 추가하여 Lighthouse가 탐색 시 기본적으로 실행하는 캐시 및 스토리지 삭제를 사용 중지할 수도 있습니다. 다음 예에서는 캐싱의 이점을 확인하기 위해 web.dev 자체의 도움말을 로드합니다.
async function captureReport() {
const browser = await puppeteer.launch({headless: false});
const page = await browser.newPage();
const testUrl = 'https://web.dev/performance-scoring/';
const flow = await startFlow(page, {name: 'Cold and warm navigations'});
await flow.navigate(testUrl, {
stepName: 'Cold navigation'
});
await flow.navigate(testUrl, {
stepName: 'Warm navigation',
configContext: {
settingsOverrides: {disableStorageReset: true},
},
});
await browser.close();
const report = await flow.generateReport();
fs.writeFileSync('flow.report.html', report);
open('flow.report.html', {wait: false});
}
captureReport();
결과 흐름 보고서는 다음과 같습니다.
콜드 로드와 웜 로드를 조합하면 실제 사용자가 경험하는 상황을 더 완전하게 파악할 수 있습니다. 사용자가 한 번의 방문에 여러 페이지를 로드하는 사이트의 경우 현장에서 어떤 경험을 하고 있는지 더 현실적으로 파악할 수 있습니다.
스냅샷
스냅샷은 특정 시점에 Lighthouse 감사를 실행하는 새로운 모드입니다. 일반 Lighthouse 실행과 달리 페이지가 새로고침되지 않습니다. 이를 통해 페이지를 설정하고 드롭다운이 열려 있거나 양식이 부분적으로 작성된 상태와 같이 정확한 상태에서 테스트할 수 있습니다.
이 예에서는 Squoosh 내의 고급 설정에 관한 일부 새 UI가 자동화된 Lighthouse 검사를 통과하는지 확인하려고 한다고 가정해 보겠습니다. 이 설정은 이미지가 로드되고 옵션 메뉴가 확장되어 고급 설정이 표시되는 경우에만 표시됩니다.
이 프로세스는 Puppeteer로 스크립트화할 수 있으며 각 단계에서 Lighthouse 스냅샷을 실제로 찍을 수 있습니다.
async function captureReport() {
const browser = await puppeteer.launch({headless: false});
const page = await browser.newPage();
const flow = await startFlow(page, {name: 'Squoosh snapshots'});
await page.goto('https://squoosh.app/', {waitUntil: 'networkidle0'});
// Wait for first demo-image button, then open it.
const demoImageSelector = 'ul[class*="demos"] button';
await page.waitForSelector(demoImageSelector);
await flow.snapshot({stepName: 'Page loaded'});
await page.click(demoImageSelector);
// Wait for advanced settings button in UI, then open them.
const advancedSettingsSelector = 'form label[class*="option-reveal"]';
await page.waitForSelector(advancedSettingsSelector);
await flow.snapshot({stepName: 'Demo loaded'});
await page.click(advancedSettingsSelector);
await flow.snapshot({stepName: 'Advanced settings opened'});
browser.close();
const report = await flow.generateReport();
fs.writeFileSync('flow.report.html', report);
open('flow.report.html', {wait: false});
}
captureReport();
결과 보고서에 따르면 결과는 전반적으로 양호하지만 수동으로 확인해야 하는 접근성 기준이 있을 수 있습니다.
기간
현장 (예: CrUX)의 성능 결과와 실험실 (예: Lighthouse)의 성능 결과 간에 가장 큰 차이점 중 하나는 사용자 입력이 없다는 점입니다. 이때 타임스팬(마지막 사용자 흐름 모드)이 도움이 될 수 있습니다.
기간은 일정 기간 동안 Lighthouse 감사를 실행하며 탐색이 포함되거나 포함되지 않을 수 있습니다. 이는 상호작용 중에 페이지에서 발생하는 상황을 포착하는 데 유용한 방법입니다. 예를 들어 기본적으로 Lighthouse는 페이지 로드 중에 CLS를 측정하지만 현장에서는 초기 탐색부터 페이지가 닫힐 때까지 CLS가 측정됩니다. 사용자 상호작용이 CLS를 트리거하는 경우 이전에는 Lighthouse에서 이를 포착하고 수정하는 데 도움을 줄 수 없었습니다.
이를 보여주기 위해 다음은 광고 공간이 예약되지 않은 상태에서 스크롤 중에 광고가 기사에 삽입되는 것을 시뮬레이션하는 테스트 사이트입니다. 긴 카드 시리즈에서 슬롯이 뷰포트에 들어올 때 가끔 빨간색 정사각형이 추가됩니다. 이러한 빨간색 정사각형을 위한 공간이 예약되지 않았으므로 그 아래에 있는 카드가 옆으로 이동하여 레이아웃이 전환됩니다.
일반 Lighthouse 탐색의 CLS는 0입니다. 하지만 스크롤하면 페이지에 문제가 있는 레이아웃 전환이 발생하고 CLS 값이 상승합니다.
다음 스크립트는 두 작업이 포함된 사용자 흐름 보고서를 생성하여 차이를 보여줍니다.
async function captureReport() {
const browser = await puppeteer.launch({headless: false});
const page = await browser.newPage();
// Get a session handle to be able to send protocol commands to the page.
const session = await page.target().createCDPSession();
const testUrl = 'https://pie-charmed-treatment.glitch.me/';
const flow = await startFlow(page, {name: 'CLS during navigation and on scroll'});
// Regular Lighthouse navigation.
await flow.navigate(testUrl, {stepName: 'Navigate only'});
// Navigate and scroll timespan.
await flow.startTimespan({stepName: 'Navigate and scroll'});
await page.goto(testUrl, {waitUntil: 'networkidle0'});
// We need the ability to scroll like a user. There's not a direct puppeteer function for this, but we can use the DevTools Protocol and issue a Input.synthesizeScrollGesture event, which has convenient parameters like repetitions and delay to somewhat simulate a more natural scrolling gesture.
// https://chromedevtools.github.io/devtools-protocol/tot/Input/#method-synthesizeScrollGesture
await session.send('Input.synthesizeScrollGesture', {
x: 100,
y: 600,
yDistance: -2500,
speed: 1000,
repeatCount: 2,
repeatDelayMs: 250,
});
await flow.endTimespan();
await browser.close();
const report = await flow.generateReport();
fs.writeFileSync('flow.report.html', report);
open('flow.report.html', {wait: false});
}
captureReport();
이렇게 하면 일반 탐색을 탐색과 스크롤이 모두 포함된 시간 간격과 비교하는 보고서가 생성됩니다.
각 단계를 자세히 살펴보면 탐색 전용 단계의 CLS는 0입니다. 멋진 사이트입니다.
하지만 '탐색 및 스크롤' 단계는 다릅니다. 현재 시간 범위에서 Total Blocking Time(총 차단 시간) 및 Cumulative Layout Shift(레이아웃 변경 횟수)만 사용할 수 있지만 이 페이지의 지연 로드된 콘텐츠로 인해 사이트의 CLS가 확실히 저하됩니다.
이전에는 Lighthouse에서 이 문제가 있는 CLS 동작을 식별할 수 없었지만 실제 사용자의 환경에는 거의 확실히 표시되었습니다. 스크립트 상호작용에 대한 성능 테스트를 실행하면 실험실의 정확성이 크게 향상됩니다.
의견을 구합니다.
Lighthouse의 새로운 사용자 흐름 API는 많은 새로운 작업을 할 수 있지만 사용자가 겪는 시나리오 유형을 측정하는 것은 여전히 복잡할 수 있습니다.
Lighthouse 토론 포럼에서 질문을 하고 Issue Tracker에서 버그나 제안사항을 제출해 주세요.