Post

웹 페이지에서 추적한 데이터를 서버로 전송하는 방법

어떤 이벤트를 listen 하여 언제 어떻게 보낼 것인가?

웹 페이지에서 추적한 데이터를 서버로 전송하는 방법

바로 이전 글인 웹에서 특정 영역 노출수 및 체류 시간 측정에 이은 포스팅입니다.

1. 목표

Mutation/Intersection Observer 로 측정한 사용자 데이터를 서버로 전송하려고 한다. 추적하려고 하는 이벤트가 일어날 때마다 서버로 전송하는 것은 부하 측면에서 좋지 않으니 사용자가 페이지를 벗어날 때 한 번에 데이터를 전송할 생각이다.

2. ‘beforeunload’ vs ‘pagehide’ 이벤트 비교

위에서 ‘페이지를 벗어날 때’ 라고 표현했는데, 자세히는 페이지 새로고침, 브라우저 탭 닫기, 다른 링크로의 이동 등이 되겠다. 이 때 사용할 수 있는 이벤트가 두 가지 있다. beforeunloadpagehide 는 비슷한 듯 조금 다른데 어떤 이벤트를 listen 하는게 좋을까?

2-1. beforeunload

  • 발생 시점: 사용자가 현재 페이지를 떠나기 직전 (새로고침-F5, 닫기, 이동 등)
  • 주요 목적: 페이지 이탈을 막거나(confirm 모달 표시), 페이지가 unload 되기 전에 데이터를 저장하는 용도
  • 특징
    • preventDefault() 를 설정하면 사용자에게 “이 페이지를 떠나시겠습니까?” 같은 경고창이 뜰 수 있음
    • “떠나기 직전 알림 또는 데이터 저장” 용도에 적합
    • 동기적으로만 동작한다고 함

2-2. pagehide

  • 발생 시점: 문서가 세션 히스토리에서 숨겨질 때 (다른 페이지로 이동하거나, 새로고침 등으로 unload 직전)
  • 특징
    • beforeunload 보다 조금 더 나중에 발생
    • “페이지가 실제로 숨겨질 때 세션 상태 저장” 용도에 적합
    • visibilitychange 와 달리 페이지가 완전히 언로드될 때에도 발생합

2-3. 호출 순서와 비교

  • beforeunloadpagehidevisibilitychange(hidden)unload
  • pagehide 가 조금 더 나중에 호출되는데 사실 큰 차이는 없어보인다. beforeunload 가 일부 모바일 OS 에서 안정적이지 않을 수가 있다고해서 pagehide 로 선택했다.

3. 전송 방법

listen 할 이벤트는 정했고, 이벤트 발생 시 서버로 데이터를 전송하는데 개발자도구 Network 탭을 보니 Status 가 (cancelled) 라고 뜨며 요청이 실패한다..! 서버로 데이터를 보내기 전에 브라우저가 해당 요청을 중간에 취소한 경우를 의미한다고 한다.

기존의 요청은 axios 를 사용하여 서버로 API 요청을 하고 있었는데, 요청이 시작되자마자 브라우저가 페이지를 정리하면서 요청에 대한 응답을 기다리지 않고 즉시 취소시켜버리고 마는 것이다.

3-1. navigator.sendBeacon()

이 메서드는 분석 정보나 진단 데이터를 서버에 보내기 위해 고안됐습니다.

많은 경우, 사이트에서 분석/진단 데이터 전송을 바라는 시점은 사용자가 다른 페이지로 이동할 때처럼 이탈 순간입니다.

MDN 공식 문서에서 발췌

정석적이고 브라우저가 권장하는 방식이라고 한다. sendBeacon() 은 페이지 언로드 시점에도 비동기 요청을 안전하게 보낼 수 있는 API 라서, 다음 페이지에 영향을 끼치지 않는다. 그 외 특성으로는 아래와 같은 것들이 있다.

  • POST 전용으로 GET 요청은 불가능
  • 요청에 대한 응답을 읽을 수 없음 → 단방향 보고용(analytics, 로그 수집 등)에만 적합
  • 용량 제한이 있음 (일반적으로 약 64KB)
  • 너무 큰 데이터나 비정상적인 Content-Type 은 무시될 수 있음
  • CORS 정책을 그대로 따름

3-2. 여전히 canceled status 발생?

Network 탭에 여전히 요청이 실패한 것처럼 붉은색 글씨가 뜨지만 실제로 서버 데이터를 살펴보면 데이터가 이상없이 전송됐음을 확인할 수 있다. Status canceled 는 HTTP 에러 코드가 아니다. 이유를 좀 더 살펴보자.

  • 비동기 백그라운드 전송
    • 브라우저가 페이지 언로드 직전에 데이터를 백그라운드 큐에 넣고, 페이지가 닫힌 뒤에 전송을 완료함
    • 즉, Network 패널이 살아있을 때 브라우저는 이미 탭을 닫고 있으므로, DevTools 입장에서는 “요청이 정상 완료됐는지 알 수 없음” → (canceled) 로 표시함.
  • 공식 문서에서도 명시됨
    • Chrome DevTools 관련 버그 트래커에 실제로 보고되어 있다고 한다.
    • “Beacon requests often appear as (canceled) in the Network panel even though they are successfully sent.”

4. 마무리

이로써 웹 페지이의 analytics 데이터 측정 및 저장이 가능하게 됐다. 데이터를 통해 다양한 검증을 해보고 인사이트를 찾아볼 생각이다. 차트도 이리저리 그려보고 하는데 생각처럼 쉽지 않다.


This post is licensed under CC BY 4.0 by the author.