앱을 쓰다가 나가는 사람이 어느 단계에서 나가는지 보고 싶었습니다.
로그는 넣어둔 게 있었습니다. 화면이 바뀔 때마다 기록이 남게 해놨고, 주요 동작마다 이벤트도 붙여놨습니다.
그런데 이탈 분석을 하려고 앉으니 답할 수가 없었습니다. 기록이 없어서가 아니라, 기록이 있는 곳과 제가 물어볼 수 있는 곳이 달라서였습니다.
이탈 분석이 막힌 곳은 기록이 아니라 조회였습니다
이탈 분석을 하려면 사용자가 지나간 자리를 알아야 하는데, 제 앱은 화면이 바뀔 때마다 screen_view 를 남기고 있었습니다.
그게 Firebase Analytics 와 Mixpanel 두 군데로 갑니다.
둘 다 웹 대시보드에서 눈으로 보는 도구입니다. 제가 쓰는 분석 스크립트에서는 그 데이터를 불러올 수 없습니다.
그래서 지금까지 퍼널 리포트는 다른 방법으로 만들고 있었습니다. 데이터베이스를 직접 읽어서, 문서가 있는지 없는지로 셌습니다.
꿈을 만들었으면 문서가 하나 생기니까 “만들었다” 를 알 수 있습니다. 할 일을 만들었으면 또 하나 생기니까 그것도 압니다.
문제는 문서가 안 생기는 행동입니다.
화면을 열어보고 아무것도 안 하고 나간 사람은 아무 흔적도 남기지 않습니다. 그러니 데이터베이스만 봐서는 “꿈이 없다” 까지만 알 수 있습니다.
꿈 만들기 화면을 본 적이 없어서 없는 것인지, 보고 닫아서 없는 것인지 구분이 안 됩니다.
이 둘은 고쳐야 할 게 정반대입니다. 앞이면 그 화면까지 가는 길을 고쳐야 하고, 뒤면 그 화면의 문구나 버튼을 고쳐야 합니다.
몇 달 동안 이 둘을 한 덩어리로 보고 있었습니다.
이벤트 34개 중 10개는 한 번도 불린 적이 없었습니다
계측을 손보기 전에 지금 뭐가 있는지부터 셌습니다.
이벤트 이름을 타입으로 선언해두는 구조라, 선언된 목록과 실제로 호출하는 코드를 각각 뽑아 비교했습니다.
선언된 이벤트 34개
실제로 부르는 것 25개
한 번도 안 불리는 것 10개
목록에는 있는데 코드 어디에서도 호출하지 않는 이름이 열 개였습니다. 버튼을 지우면서 이벤트만 남겨둔 것들입니다.
이게 왜 나쁘냐면, 대시보드에서 그 이름으로 검색하면 아무 오류 없이 0이 나오기 때문입니다.
“이 기능은 아무도 안 쓰는구나” 로 읽힙니다. 실제로는 측정을 안 하고 있었을 뿐인데요.
결국 데이터베이스에 발자국을 남기기로 했습니다
방법을 두 가지 놓고 골랐습니다.
첫째는 대시보드 도구에서 데이터를 내보내는 API 를 붙이는 것입니다. 둘째는 내가 읽을 수 있는 곳, 그러니까 이미 쓰는 데이터베이스에 최소한만 남기는 것입니다.
둘째를 골랐습니다. 어차피 알고 싶은 건 “어디까지 갔나” 하나라서요.
그래서 사용자 문서에 단계별로 처음 도달한 시각만 남깁니다.
signup 가입
dream_modal 꿈 만들기 화면을 봤다
dream_created 꿈을 만들었다
timeblock 하루 탭에 도착했다
todo_added 할 일을 하나 만들었다
todo_completed 할 일을 하나 끝냈다
여섯 개고, 한 단계당 한 번만 씁니다. 사용자 한 명이 평생 여섯 번 쓰는 셈이라 비용은 없다고 봐도 됩니다.
몇 번 눌렀는지는 안 셉니다. 그건 원래 쓰던 도구가 이미 하고 있고, 여기서 알고 싶은 건 순서와 도달 여부뿐입니다.
가장 중요한 건 두 번째 줄입니다.
화면을 봤다는 사실을 따로 남기면, 아까 구분이 안 되던 두 종류가 갈립니다. 화면을 보고 안 만든 사람은 문구 문제고, 화면을 본 적이 없는 사람은 경로 문제입니다.
만들다가 거짓말을 하나 만들 뻔했습니다
처음 설계에는 단계가 여덟 개였습니다. 앞에 두 개가 더 있었습니다.
app_open 앱을 열었다
hero_done 첫 소개 화면을 넘겼다
signup 가입
...
시작점이 있어야 그림이 완성되니까요.
그런데 코드를 쓰다 보니 둘 다 남길 데가 없었습니다.
소개 화면은 로그인 전입니다. 사용자 계정이 아직 없으니 “이 사람이 여기까지 왔다” 를 적을 문서 자체가 없습니다.
앱을 연 순간도 마찬가지입니다.
그래서 편법을 썼습니다.
가입 처리를 하는 그 자리에서 app_open 도 같이 찍었습니다.
계정이 생기는 첫 순간이니 거기가 제일 앞이라고 생각했습니다.
돌려보고 나서야 이상한 걸 알았습니다.
app_open 과 signup 이 같은 순간에 찍히니까, 리포트에서 그 단계가 항상 100% 통과로 나옵니다.
앞으로도 영원히 그럴 겁니다.
리포트를 보는 사람은 “앱을 연 사람은 전부 가입까지 하는구나” 로 읽습니다. 실제로는 그 구간을 아예 재지 않았을 뿐인데요.
없는 정보보다 나쁩니다. 비어 있으면 없다는 걸 알지만, 100% 는 잰 것처럼 보이니까요.
두 단계를 지웠습니다. 지금 리포트의 첫 줄은 가입이고, 그 앞은 못 잰다고 문서에 적어뒀습니다.
재보니 예상하지 않은 자리가 제일 컸습니다
새 계측이 아직 사용자에게 안 나갔으니, 그동안은 문서에 남은 시각으로 흐름을 복원해봤습니다.
최근 30일에 가입한 43명입니다.
| 어디서 멈췄나 | 인원 |
|---|---|
| 꿈 0개 | 19명 |
| 꿈만 만들고 할 일 0개 | 18명 |
| 할 일은 만들었는데 완료 0 | 3명 |
| 완료까지 감 | 3명 |
가운데 줄이 제가 못 보던 자리입니다.
꿈을 만든 24명 중 18명이 할 일을 하나도 안 만들었습니다. 기존 리포트는 “첫 꿈 만들기” 다음이 바로 “첫 완료” 라, 그 사이가 통째로 비어 있었습니다.
하나 더 있습니다. 43명 중 31명이 문서 기준 2분 안에 활동이 끝났습니다. 8초, 40초, 51초 이런 값들입니다.
이건 쓰다가 막혀서 나간 게 아니라 한 번 훑고 나간 모양입니다. 같은 이탈이라도 대응이 다릅니다.
정리하면 두 가지입니다
기록을 남기는 것과 질문에 답할 수 있는 것은 다른 일입니다. 데이터가 내가 못 가는 곳에 쌓이고 있으면, 그 계측은 있으나 마나입니다. 계측을 늘리기 전에 그걸 어디서 읽을 건지부터 정하는 게 순서였습니다.
그리고 항상 100% 로 나오는 단계는 지표가 아닙니다. 그건 재지 않았다는 뜻이고, 리포트에 넣으면 읽는 사람을 속입니다. 차라리 그 줄을 빼고 “여기는 못 잰다” 고 적는 편이 정직합니다.
같은 종류의 실수를 전에도 한 번 했습니다. 검사가 통과한 게 아니라 아무것도 안 걸린 것이었던 이야기인데, 그때도 초록불이 정보가 아니었습니다.
어디까지 확인한 것인지
2026년 8월 24일에 잰 값이고, Expo SDK 56 · React Native 0.85 앱에서 Firebase Analytics 와 Mixpanel 을 함께 쓰는 구성 기준입니다. 사용자 43명은 표본이 작아서 비율보다는 순서를 보는 용도로만 썼습니다.
새 계측은 방금 배포했고 아직 데이터가 없습니다. 그러니 이 방식이 실제로 두 종류의 이탈을 갈라주는지는 아직 모릅니다. 숫자가 나오면 그때 다시 쓰겠습니다.