Long Animation Frames API (LoAF)를 활용하고 스마트 양보 전략을 채택하여 Taboola가 광고 실적을 저해하지 않으면서 게시자의 웹사이트 응답성을 개선한 방법
다음 페인트에 대한 상호작용 (INP)은 사용자 입력에 대한 웹사이트의 응답성을 평가하는 측정항목입니다. INP는 사용자가 클릭, 탭, 입력과 같은 상호작용을 시작한 시점부터 시각적 피드백이 표시되는 시점까지의 시간을 측정합니다. INP는 2024년 3월에 최초 입력 반응 시간 (FID)을 대체하여 Core Web Vital 역할을 하게 됩니다.
Taboola는 공개 웹에서 초당 500,000개의 추천을 제공하는 세계 최고의 콘텐츠 탐색 플랫폼입니다. 이러한 추천을 통해 Taboola의 9,000개 독점 게시자 파트너는 시청자로부터 수익을 창출하고 시청자의 참여를 유도할 수 있습니다. 게시자는 JavaScript를 사용하여 페이지에 추천을 렌더링합니다.
서드 파티 JavaScript는 페이지가 사용자 입력에 빠르게 응답하는 기능에 영향을 줄 수 있으므로 Taboola는 JavaScript 파일 크기와 실행 시간을 줄이는 데 많은 투자를 해왔습니다. Taboola는 INP에 미치는 영향을 최소화하기 위해 전체 렌더링 엔진을 재설계하고 추상화 없이 브라우저 API를 직접 사용해 왔습니다.
이 사례 연구에서는 새로운 Long Animation Frames (LoAF) API를 사용하여 페이지 응답성에 미치는 영향을 측정하고 사용자 환경을 개선하기 위해 구체적인 최적화를 적용한 Taboola의 여정을 다룹니다.
INP의 프록시로서의 TBT
총 차단 시간 (TBT)은 실험실 기반 측정항목으로, 페이지 응답성에 영향을 미칠 수 있을 만큼 기본 스레드가 차단된 위치를 식별합니다. INP와 같은 응답성을 측정하는 필드 측정항목은 TBT가 높을 때 영향을 받을 수 있습니다. 애니 설리번의 모바일 기기에서 TBT와 INP 간의 상관관계에 관한 조사에 따르면 기본 스레드 차단 시간이 최소화되면 사이트가 좋은 INP 점수를 달성할 가능성이 더 높습니다.
이 상관관계와 높은 TBT에 대한 Taboola 게시자의 우려로 인해 Taboola는 이 측정항목에 대한 기여도를 최소화하는 데 집중했습니다.
RELEASE.js와 같은 스크립트가 기본 스레드를 691밀리초 동안 차단합니다.
Taboola는 INP의 프록시 측정항목으로 TBT를 사용하여 JavaScript 실행 시간을 모니터링하고 최적화하여 Core Web Vitals에 미치는 잠재적 영향을 제한하기 시작했습니다. 다음과 같은 작업을 시작했습니다.
- Long Tasks API를 사용하여 필드에서 문제가 있는 스크립트를 식별하고 최적화합니다.
- PageSpeed Insights API를 사용하여 매일 10,000~15,000개의 URL을 평가하여 TBT 기여도를 추정합니다.
하지만 Taboola는 이러한 도구로 TBT를 분석하는 데 몇 가지 제한사항이 있음을 확인했습니다.
- Long Tasks API는 작업을 출처 도메인이나 특정 스크립트에 귀속시킬 수 없으므로 긴 작업의 소스를 식별하기가 더 어렵습니다.
- Long Tasks API는 렌더링 지연을 유발할 수 있는 작업과 레이아웃 변경사항의 조합이 아닌 긴 작업만 식별합니다.
이러한 문제를 해결하기 위해 Taboola는 사용자 입력 응답성에 미치는 실제 영향을 더 잘 이해하기 위해 Long Animation Frames (LoAF) API 오리진 트라이얼에 참여했습니다. 오리진 트라이얼을 통해 새로운 기능 또는 실험용 기능을 이용할 수 있으며, 개발자는 사용자가 한정 기간 동안 사용해 볼 수 있는 새로운 기능을 테스트할 수 있습니다.
이 과제에서 가장 어려웠던 점은 광고 KPI(핵심성과지표)를 저해하거나 게시자의 리소스 지연을 유발하지 않고 INP를 성공적으로 개선하는 것이었습니다.
LoAF를 사용하여 INP 영향 평가
렌더링 업데이트가 50밀리초를 초과하여 지연되면 긴 애니메이션 프레임이 발생합니다. Taboola는 긴 작업뿐만 아니라 느린 사용자 인터페이스 업데이트의 원인을 파악하여 필드에서 페이지 응답성에 미치는 영향을 분석할 수 있었습니다. Taboola는 LoAF를 관찰하여 다음을 수행할 수 있었습니다.
- 특정 Taboola 작업에 속성 항목을 지정합니다.
- 프로덕션에 배포되기 전에 특정 기능의 성능 문제를 관찰합니다.
- 집계된 데이터를 수집하여 A/B 테스트에서 여러 코드 버전을 비교하고 주요 성공 측정항목을 보고합니다.
다음 JavaScript는 Taboola의 영향을 격리하기 위해 LoAF를 수집하는 데 프로덕션에서 사용되는 단순화된 버전입니다.
function loafEntryAnalysis (entry) {
if (entry.blockingDuration === 0) {
return;
}
let taboolaIsMajor = false;
const hasInteraction = entry.firstUIEventTimestamp > 0;
let taboolaDuration = 0;
const nonTaboolaLoafReport = {};
const taboolaLoafReport = {};
entry.scripts.forEach((script) => {
const taboolaScriptBlockingDuration = handleLongAnimationFrameScript(script, taboolaLoafReport, nonTaboolaLoafReport);
taboolaDuration += taboolaScriptBlockingDuration;
if (taboolaScriptBlockingDuration > 0 || taboolaDuration > entry.duration / 2) {
taboolaIsMajor = true;
}
});
generateToboolaLoafReport(taboolaLoafReport, nonTaboolaLoafReport, hasInteraction, taboolaIsMajor);
if (hasInteraction) {
const global = _longAnimationFramesReport.global;
global.inpBlockingDuration = Math.max(global.inpBlockingDuration, entry.blockingDuration);
if (taboolaIsMajor) {
global.taboolaInpBlockingDuration = Math.max(global.taboolaInpBlockingDuration, entry.blockingDuration);
}
}
}
const observer = new PerformanceObserver(list => {
for (const entry of list.getEntries()) {
loafEntryAnalysis(entry);
}
});
observer.observe({ type: 'long-animation-frame', buffered: true });
loafEntryAnalysis함수를 사용하여 Taboola가 주요 기여자인 항목을 식별할 수 있었습니다.- 전체 스크립트 시간의 절반 이상이 Taboola에 의해 발생하거나 Taboola 스크립트가 실행되는 데 50밀리초 이상 걸리는 경우 Taboola가 주요 기여자로 간주됩니다.
- 긴 애니메이션 프레임으로 인해 사용자 상호작용이 지연되면
firstUIEventTimeStamp가 생성됩니다. 가장 긴 차단 기간이 전체 INP 점수로 간주됩니다. Taboola가 Taboola INP 점수를 계산하기 위해firstUIEventTimeStamp를 트리거한 시점도 확인할 수 있습니다.
LoAF로 수집된 데이터를 통해 Taboola는 양보 기회를 적용할 수 있는 영역을 식별하는 다음 기여 분석 표를 만들었습니다.
TRECS 엔진: 새로운 수익 창출 전략
Taboola는 LoAF를 사용하여 스크립트 최적화 기회를 더 잘 파악하는 것 외에도 자바스크립트 실행 및 차단 시간을 크게 최소화하기 위해 전체 렌더링 엔진을 재설계했습니다.
TRECS (Taboola Recommendations Extensible Client Service)는 Taboola의 추천을 로드하는 데 필요한 필수 파일의 수와 크기를 줄이면서 클라이언트 측 렌더링과 게시자의 현재 JS 코드를 유지합니다.
LoAF를 사용하여 렌더링 차단 작업을 식별하면 '성능 페이더'가 scheduler.postTask()를 사용하여 기본 스레드에 양보하기 전에 이러한 작업을 분리할 수 있습니다. 이 설계는 기본 스레드를 차지할 수 있는 기존 작업과 관계없이 업데이트 렌더링과 같은 중요한 사용자 대상 작업을 최대한 빨리 실행할 수 있도록 합니다.
다음은 'Performance Fader' 작업 러너의 JS 스니펫입니다.
/**
* Send a task to run using the Fader. The task will run using the browser Scheduler, by the configuration settings, or immediately.
* @param task
* @param isBlocker
*/
function sendTaskToFader (task, isBlocker = true) {
const publisherFaderChoice = fillOptimizationGlobals(); // Loading publisher choice
const applyYielding = publisherFaderChoice === OptimizationFaderType.Responsiveness;
if (applyYielding) {
return runAsPostTask(task, isBlocker);
}
return runImmediately(task);
}
/**
* Yielding method using scheduler.postTask and falling back to setTimeout when it's not availabe based on the publisher choice
*/
function runAsPostTask (task, isBlocker = true) {
if ('scheduler' in window && 'postTask' in scheduler) {
const priority = isBlocker ? 'user-blocking': 'background';
return window?.scheduler?.postTask(task, { priority });
}
const publisherChoiceEnableFallback = fillPublisherChoices();
if (publisherChoiceEnableFallback) {
return new Promise(resolve => {
window.setTimeout(() => {
resolve(task());
}, 0);
});
}
return runImmediately(task);
}
sendTaskToFader 함수는 다음을 수행합니다.
runAsPostTask를 사용합니다.runAsPostTask는 내부적으로scheduler.postTask()를 사용하거나 (API를 사용할 수 있는 경우)setTimeout로 대체됩니다.- 이 함수는 긴 애니메이션 프레임과 INP를 유발하는 코드 섹션에서 함수 호출을 래핑합니다. 이 코드는 이러한 코드 섹션을 더 짧은 작업으로 분할하여 INP를 줄입니다.
비즈니스 측정항목
Taboola는 LoAF 덕분에 INP에 미치는 영향을 더 잘 이해할 수 있었습니다. 또한 이 도구는 새로운 TRECS 엔진의 일부로 사용할 수 있는 스크립트 최적화 기회를 강조했습니다.
TRECS와 Performance Fader의 영향을 파악하기 위해 Taboola는 게시자 파트너 패널에서 스크립트가 생성되지 않는 기존 엔진을 대상으로 INP를 측정하는 A/B 테스트를 진행했습니다.
다음 표는 Taboola 네트워크에 있는 4개의 익명 게시자의 75번째 백분위수에서 INP 결과를 밀리초로 보여줍니다.
다행히 테스트 패널에서 TRECS와 Performance Fader를 사용 설정했을 때 광고 클릭률 및 1,000회 노출당 수익 (RPM)과 같은 비즈니스 측정항목은 부정적인 영향을 받지 않았습니다. 광고 KPI에 예상대로 부정적인 결과 없이 INP가 긍정적으로 개선됨에 따라 Taboola는 제품에 대한 게시자의 인식을 점진적으로 개선할 것입니다.
앞서 언급한 동일한 고객에 대한 또 다른 Lighthouse 실행에서는 새 엔진을 사용할 때 Taboola의 기본 스레드 차단 시간이 크게 개선된 것으로 나타났습니다.
RELEASE.js와 같은 스크립트가 TBT를 485ms (-70%) 줄이는 데 도움이 되었습니다.
이를 통해 LoAF를 사용하여 INP의 원인을 파악하고 성능 페이더를 사용하여 후속 양보 기법을 배포하면 Taboola 파트너가 광고 및 페이지 성능에서 최대한의 성공을 거둘 수 있습니다.
결론
INP 최적화는 특히 파트너 웹사이트에서 서드 파티 스크립트를 사용하는 경우 복잡한 프로세스입니다. 최적화를 시작하기 전에 INP를 특정 스크립트에 귀속시키면 추측과 다른 사이트 성능 측정항목에 대한 잠재적 손상을 방지할 수 있습니다.LoAF API는 특히 삽입된 서드 파티가 페이지에 있는 다른 기술의 간섭을 없애면서 특정 SDK 개선 기회를 정확히 파악할 수 있도록 하여 INP 문제를 식별하고 해결하는 데 유용한 도구로 입증되었습니다.
scheduler.postTask() 사용과 같은 적절한 양보 전략과 함께 사용하면 LoAF를 통해 페이지 응답성 저하의 원인을 관찰하고 이해할 수 있으며, 이를 통해 웹사이트의 INP를 개선하는 데 필요한 정보를 얻을 수 있습니다.
이 작업에 기여해 주신 Google의 Gilberto Cocchi, Noam Rosenthal, Rick Viscomi, Taboola의 엔지니어링 및 제품팀의 Dedi Hakak, Anat Dagan, Omri Ariav에게 특별히 감사드립니다.