본문 바로가기

블로그 / 기술

쿠키 없이 붙인 웹 게임 텔레메트리: 무엇을 모으고 무엇을 버렸나

Salmonholic과 AvoidNow에 직접 만든 텔레메트리를 붙였다. 쿠키 없이 로딩 시간과 오류 위주로 모은 방식과 두 게임이 남기는 항목의 차이, 막아 둔 규칙, 그리고 '저장이 멈췄다'는 오탐을 잡은 이야기를 정리했다.

Salmonholic ·· 4분 읽기

Salmonholic 경기 38초 시점, 생존자 10명과 레이저 무기가 보이는 화면

웹 게임을 올리고 나면 제일 답답한 게 “남의 브라우저에서 무슨 일이 일어나는지 모른다”는 점이다. 내 맥에서는 잘 뜨는데 누군가의 폰에서는 검은 화면만 보일 수 있다. 그렇다고 분석 도구를 통째로 붙이면 쿠키 동의 창부터 띄워야 한다. 그래서 Salmonholic과 AvoidNow에는 필요한 숫자만 받는 작은 텔레메트리를 직접 만들었다.

받는 것은 두 종류뿐

게임 페이지의 HTML 셸이 엔진을 띄우면서 두 가지만 보낸다.

종류 담는 내용 제한
로딩 로딩에 걸린 ms, 모바일/데스크톱, 화면 크기, 언어, 망 종류, 빌드 해시 엔진이 뜰 때 1회
오류 JS 오류, 처리 안 된 Promise 거부, 엔진 시작 실패 메시지 300자, 중복 제거, 세션당 5개

이건 AvoidNow 기준이다. AvoidNow는 쿠키, IP, 브라우저 문자열(UA)을 저장하지 않는다. 먼저 만든 Salmonholic은 조금 더 받는다. 경기 결과(순위, 생존 시간, 처치 수)와 서버까지의 지연, UA 필드가 들어가고, IP는 원문 대신 SHA-256 해시의 앞 6바이트만 남긴다. 국가는 Cloudflare가 붙여 주는 헤더에서 읽는다. 두 게임 모두 텔레메트리에 쿠키는 쓰지 않는다.

Godot 기본 로딩 화면, 파란 진행 막대와 GODOT 로고 Godot 기본 셸의 로딩 화면. 이 막대가 얼마나 오래 떠 있는지가 텔레메트리의 첫 번째 숫자다

받는 쪽에서 막아 둔 규칙

받는 곳은 게임 페이지를 서빙하는 Cloudflare Worker의 한 경로다. 아무나 아무 데이터나 밀어 넣지 못하게 규칙을 붙였다.

  • 같은 출처에서 온 요청만 받는다. 출처가 다르거나 없으면 403.
  • 본문이 정해 둔 크기를 넘으면 413, JSON이 아니면 400.
  • 한곳에서 짧은 시간에 너무 많이 보내면 429.
  • 정해 둔 필드 목록 밖의 값은 버린다.

로컬에서 wrangler dev로 이 규칙을 하나씩 두드려 봤다. 같은 출처는 204, 다른 출처는 403, 너무 큰 본문은 413, 한도를 넘긴 요청은 429가 돌아오는 것을 확인했다.

저장은 Workers KV에 한다. Salmonholic은 이벤트 한 건을 키 하나로 두고 30일 뒤 사라지게 했다. AvoidNow는 한 단계 더 줄여서 날짜별 카운터만 올린다. “9월 26일 모바일 로딩 N건”, “이 오류 메시지 해시 N회와 샘플 하나” 같은 식이다. 보존 기간은 90일이다. 개별 사용자의 흔적이 애초에 남지 않는다.

실제로 잡아낸 것

이 텔레메트리 덕에 찾은 문제가 있다. 9월 24일에 아이폰 카카오톡 인앱 브라우저에서 “WebGL 2가 없다”는 오류가 떴다. 오류 기록을 열어 보니 같은 부팅 오류가 이미 7건 쌓여 있었다. 원인은 http로 열린 페이지였다. Godot는 보안 컨텍스트(https)가 아니면 엔진을 띄우지 않는다. Worker에 http → https 리다이렉트를 넣은 커밋이 6fe0575다. 자세한 경위는 Godot 웹 export 글에 있다.

서버 쪽 숫자도 따로 모은다. 9월 26일 커밋 54f3d6f부터 두 방 서버(DO, 서울 VM)가 입장 수와 지연을 유입 경로, 대륙, 국가별로 집계한다. 같은 날 96f0fc7에서는 사람 플레이어의 경기 결과(순위, 생존 시간, 사망 원인, 30초 안에 다시 하기)를 더했다. 이 통계 경로는 토큰이 있어야 열린다.

“저장이 멈췄다”는 오탐

9월 22일 새벽, 점검 도중에 “텔레메트리가 UTC 12시 33분 이후로 저장되지 않는다”는 보고가 올라왔다. 코드를 뒤지기 전에 증거부터 다시 봤다.

확인 방법 결과
wrangler kv key list (옵션 없음) 50건, 마지막 기록 12:33
같은 명령 + --remote 83건, 계속 늘어나는 중
Cloudflare REST API로 직접 조회 83건

wrangler 4의 KV 명령은 기본이 로컬 저장소였다. 옵션 없이 본 50건은 내가 wrangler dev로 테스트하며 쌓은 로컬 데이터였다. 운영 KV는 멀쩡했다. 그 뒤로 운영 문서의 모든 KV 명령에 --remote를 붙였고, Worker 코드 머리 주석에도 같은 경고를 적었다. 코드에는 문제가 없었고, 잘못된 건 보는 방법이었다.

붙이지 않은 것

방문 수 같은 기본 지표는 Cloudflare Web Analytics로 본다. AvoidNow를 올릴 때는 도메인 단위 자동 삽입이 이미 켜져 있어서, 게임 셸에 비콘을 따로 넣지 않았다. 넣으면 같은 방문이 두 번 집계된다. 직접 만든 텔레메트리는 이 도구가 못 보는 것, 즉 엔진 로딩 시간과 게임 안 오류만 맡는다.

한 줄로 정리하면 “사람을 세지 말고 문제를 세자”였다. 로딩이 느린 기기 비율과 오류 메시지 목록만 있어도 고칠 거리는 충분히 나왔다. 서버 구성 전체는 서버 지도 글에 정리했다. 이렇게 지켜보고 있는 두 게임은 Salmonholic과 AvoidNow 페이지에서 해 볼 수 있다.

#텔레메트리#Cloudflare Workers#KV#개인정보#웹 게임 운영

함께 읽으면 좋은 글

전체 글 →