웹페이지에서는 데이터 (또는 '비콘')를 서버로 다시 전송해야 하는 경우가 많습니다. 예를 들어 사용자의 현재 세션에 대한 분석 데이터를 예로 들 수 있습니다. 개발자는 이때 균형을 유지해야 합니다. 비콘을 전송하기 전에 탭이 닫히거나 사용자가 탐색을 중단한 경우 데이터 누락을 방지하면서 끊임없이 반복될 수 있는 요청을 줄여야 합니다.
기존에는 개발자가 pagehide
및 visibilitychange
이벤트를 사용하여 페이지가 언로드될 때 페이지를 포착한 다음 navigator.sendBeacon()
또는 fetch()
와 keepalive
를 사용하여 데이터를 비콘으로 전송했습니다. 그러나 이 두 이벤트 모두 사용자의 브라우저에 따라 달라지는 어려운 특이 사례가 있으며, 특히 모바일에서는 이벤트가 전혀 도착하지 않는 경우도 있습니다.
fetchLater()
는 이러한 복잡성을 단일 API 호출로 대체하기 위한 제안입니다. 이름에서 알 수 있듯이 페이지가 닫히거나 사용자가 탐색을 종료하더라도 향후 특정 시점에 요청이 이루어지도록 브라우저에 요청합니다.
fetchLater()
는 Chrome에서 오리진 트라이얼을 통해 실제 사용자를 대상으로 테스트할 수 있으며, 이 트라이얼은 2024년 1월에 출시된 버전 121부터 시작되어 2024년 9월 3일까지 진행됩니다.
fetchLater()
API
const fetchLaterResult = fetchLater(request, options);
fetchLater()
는 일반적으로 fetch()
의 인수와 동일한 두 개의 인수를 사용합니다.
request
: 문자열 URL 또는Request
인스턴스입니다.activateAfter
라는 제한 시간으로fetch()
의options
를 확장하는 선택적options
객체
fetchLater()
는 현재 단일 읽기 전용 속성 activated
만 포함하는 FetchLaterResult
를 반환합니다. '나중에'가 지나고 가져오기가 완료되면 이 속성이 true
로 설정됩니다. fetchLater()
요청에 대한 응답은 모두 삭제됩니다.
request
가장 간단한 사용법은 URL 자체입니다.
fetchLater('/endpoint/');
하지만 fetch()
와 마찬가지로 fetchLater()
요청에는 맞춤 헤더, 사용자 인증 정보 동작, POST
본문, AbortController
signal
(취소 가능)를 비롯한 다양한 옵션을 설정할 수 있습니다.
fetchLater('/endpoint/', {
method: 'GET',
cache: 'no-store',
mode: 'same-origin',
headers: {Authorization: 'SUPER_SECRET'},
});
options
options 객체는 제한 시간 activateAfter
으로 fetch()
의 옵션을 확장합니다. 제한 시간 후 또는 페이지가 언로드될 때(둘 중 먼저 오는 경우) 요청을 실행하려는 경우입니다.
이를 통해 데이터를 가져오는 가장 마지막 순간과 더 시기의 적절한 시점 사이에서 균형을 유지할 수 있습니다.
예를 들어 사용자가 일반적으로 하루 종일 열어 두는 앱이 있는 경우, 1시간의 제한 시간을 설정하여 더 세부적인 분석을 수행하는 동시에 1시간이 지나기 전에 사용자가 종료한 경우 비콘을 보장할 수 있습니다. 그러면 다음 1시간 동안의 분석을 위해 새 fetchLater()
를 설정할 수 있습니다.
const hourInMilliseconds = 60 * 60 * 1000;
fetchLater('/endpoint/', {activateAfter: hourInMilliseconds});
사용 예
현장에서 Core Web Vitals를 측정할 때 발생하는 한 가지 문제는 사용자가 실제로 페이지를 나가기 전까지 성능 측정항목이 변경될 수 있다는 점입니다. 예를 들어 언제든지 더 큰 레이아웃 변경이 발생하거나 페이지가 상호작용에 응답하는 데 더 오래 걸릴 수 있습니다.
하지만 페이지 로드 취소 시 버그가 있거나 불완전한 비커닝으로 인해 모든 성능 데이터가 손실되지는 않습니다. fetchLater()
에 적합한 후보입니다.
이 예에서는 web-vitals.js 라이브러리를 사용하여 측정항목을 모니터링하고 fetchLater()
를 사용하여 결과를 애널리틱스 엔드포인트에 보고합니다.
import {onCLS, onINP, onLCP} from 'web-vitals';
const queue = new Set();
let fetchLaterController;
let fetchLaterResult;
function updateQueue(metricUpdate) {
// If there was an already complete request for whatever
// reason, clear out the queue of already-sent updates.
if (fetchLaterResult?.activated) {
queue.clear();
}
queue.add(metricUpdate);
// JSON.stringify used here for simplicity and will likely include
// more data than you need. Replace with a preferred serialization.
const body = JSON.stringify([...queue]);
// Abort any existing `fetchLater()` and schedule a new one with
// the update included.
fetchLaterController?.abort();
fetchLaterController = new AbortController();
fetchLaterResult = fetchLater('/analytics', {
method: 'POST',
body,
signal: fetchLaterController.signal,
activateAfter: 60 * 60 * 1000, // Timeout to ensure timeliness.
});
}
onCLS(updateQueue);
onINP(updateQueue);
onLCP(updateQueue);
측정항목 업데이트가 수신될 때마다 예약된 기존 fetchLater()
가 AbortController
에 의해 취소되고 업데이트가 포함된 새 fetchLater()
가 생성됩니다.
fetchLater()
사용해 보기
앞서 언급한 대로 fetchLater()
는 Chrome 126까지 오리진 트라이얼로 제공됩니다. 출처 실험에 관한 배경 정보는 '출처 실험 시작하기'를 참고하세요.
로컬 테스트의 경우 chrome://flags/#enable-experimental-web-platform-features
의 실험용 웹 플랫폼 기능 플래그를 사용하여 fetchLater
를 사용 설정할 수 있습니다. 명령줄에서 --enable-experimental-web-platform-features
또는 보다 타겟팅된 --enable-features=FetchLaterAPI
플래그를 사용하여 Chrome을 실행하여 사용 설정할 수도 있습니다.
공개 페이지에서 사용하는 경우 전역 fetchLater
가 정의되어 있는지 확인하여 기능을 감지해야 합니다.
if (globalThis.fetchLater) {
// Set up beaconing using fetchLater().
// ...
}
의견
새로운 웹 API를 올바르게 사용하려면 개발자 의견이 필수적이므로 GitHub에서 문제 및 의견을 제출해 주세요.