fetchLater API 오리진 트라이얼

Brendan Kenny
Brendan Kenny

웹페이지에서는 데이터 (또는 '비콘')를 서버로 다시 전송해야 하는 경우가 많습니다. 예를 들어 사용자의 현재 세션에 대한 분석 데이터를 예로 들 수 있습니다. 개발자는 이때 균형을 유지해야 합니다. 비콘을 전송하기 전에 탭이 닫히거나 사용자가 탐색을 중단한 경우 데이터 누락을 방지하면서 끊임없이 반복될 수 있는 요청을 줄여야 합니다.

기존에는 개발자가 pagehidevisibilitychange 이벤트를 사용하여 페이지가 언로드될 때 페이지를 포착한 다음 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에서 문제 및 의견을 제출해 주세요.

추가 정보