सदस्यता लें

navigator.sendBeacon vs fetch + keepalive

작성자
현우
작성시각
수정시각
레퍼런스
खाली
사용자가 페이지를 떠날 때마다 백엔드에 몇가지 요청을 보내려고 할 때, 두가지 정도의 접근 방식이 존재한다.
바로 navigator.sendBeacon 또는 fetch + keepalive 방식이다.

두 방식의 트레이드 오프

페이지가 언로드될 때 데이터를 전송하도록 특별히 설계되었다.
우선순위가 낮은 비동기식으로 페이지 언로드 프로세스를 차단하지 않는다. (네트워크 탭의 우선순위 참고)
브라우저는 페이지가 닫힌 후에도 데이터 전송을 완료한다.
간편한 API 인터페이스로 사용할 수 있다.
POST 메서드를 주로 지원하기 때문에, 자동으로 POST 메서드를 사용한다.
응답을 처리할 필요없으며, 단방향 데이터에 이상적이다.

Navigator.sendBeacon의 제약사항

POST 요청만을 지원한다.
응답 내용을 받을 수 없다.
크기 제한이 있다. (크롬의 경우 약 64KB)
사용자 커스텀 헤더 지원을 하지 않는다.

사용 예시

javascriptCopywindow.addEventListener('unload', () => {
  navigator.sendBeacon('/api/log', JSON.stringify({
    event: 'page_exit',
    duration: performance.now()
  }));
});

Fetch + keepalive

Fetch + keepalive의 장점

모든 HTTP 메서드 (GET, POST, PUT 등)을 지원한다.
사용자 커스텀 헤더를 허용한다.
응답 내용에 대한 처리가 가능하다.
데이터 크기에 제한이 없다.
더 유연한 에러 핸들링이 가능하다.

Fetch + keepalive의 제약사항

Navigator.sendBeacon 보다 조금 더 복잡한 구현 요소를 가진다.
수동으로 옵션을 활성화 시켜줘야한다.
Navigator.sendBeacon 에 비해 브라우저 호환성이 약간 낮은 편이다.

사용 예시

javascriptCopywindow.addEventListener('unload', () => {
  fetch('/api/sync', {
    method: 'POST',
    keepalive: true,
    headers: {
      'Content-Type': 'application/json',
      'Authorization': 'Bearer token'
    },
    body: JSON.stringify({
      data: 'important_data'
    })
  });
});

글을 마치며

간단한 분석 및 로깅 시나리오를 위해 navigator.sendBeacon 을 선택하고, 요청에 대한 더 많은 제어가 필요하거나 응답을 처리해야할 경우에는 Fetch + keepalive 전략이 매우 좋은 선택인 것 같다. 중요한 데이터의 경우 페이지 언로드를 기다리지 않고 사용자 상호작용 중 동기화 하는 로직 (로컬 스토리지를 이용하여 Ack 로직과 로드 로직을 만드는 등) 고려하는 편이 좋을 것 같다는 생각이 든다.