웹 페이지에서 추적한 데이터를 서버로 전송하는 방법
어떤 이벤트를 listen 하여 언제 어떻게 보낼 것인가?
바로 이전 글인 웹에서 특정 영역 노출수 및 체류 시간 측정에 이은 포스팅입니다.
1. 목표
Mutation/Intersection Observer 로 측정한 사용자 데이터를 서버로 전송하려고 한다. 추적하려고 하는 이벤트가 일어날 때마다 서버로 전송하는 것은 부하 측면에서 좋지 않으니 사용자가 페이지를 벗어날 때 한 번에 데이터를 전송할 생각이다.
2. ‘beforeunload’ vs ‘pagehide’ 이벤트 비교
위에서 ‘페이지를 벗어날 때’ 라고 표현했는데, 자세히는 페이지 새로고침, 브라우저 탭 닫기, 다른 링크로의 이동 등이 되겠다. 이 때 사용할 수 있는 이벤트가 두 가지 있다. beforeunload 와 pagehide 는 비슷한 듯 조금 다른데 어떤 이벤트를 listen 하는게 좋을까?
2-1. beforeunload
- 발생 시점: 사용자가 현재 페이지를 떠나기 직전 (새로고침-F5, 닫기, 이동 등)
- 주요 목적: 페이지 이탈을 막거나(confirm 모달 표시), 페이지가 unload 되기 전에 데이터를 저장하는 용도
- 특징
preventDefault()를 설정하면 사용자에게 “이 페이지를 떠나시겠습니까?” 같은 경고창이 뜰 수 있음- “떠나기 직전 알림 또는 데이터 저장” 용도에 적합
- 동기적으로만 동작한다고 함
2-2. pagehide
- 발생 시점: 문서가 세션 히스토리에서 숨겨질 때 (다른 페이지로 이동하거나, 새로고침 등으로 unload 직전)
- 특징
beforeunload보다 조금 더 나중에 발생- “페이지가 실제로 숨겨질 때 세션 상태 저장” 용도에 적합
visibilitychange와 달리 페이지가 완전히 언로드될 때에도 발생합
2-3. 호출 순서와 비교
beforeunload→pagehide→visibilitychange(hidden)→unloadpagehide가 조금 더 나중에 호출되는데 사실 큰 차이는 없어보인다.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 데이터 측정 및 저장이 가능하게 됐다. 데이터를 통해 다양한 검증을 해보고 인사이트를 찾아볼 생각이다. 차트도 이리저리 그려보고 하는데 생각처럼 쉽지 않다.