Skip to content

데이터 트래킹: 사용자가 애플리케이션에서 무엇을 했는지 기록하기

🎯 이 장에서 다룰 문제

사용자가 애플리케이션 안에서 무엇을 했는지 어떻게 알 수 있을까?

오프라인 카페를 운영한다고 상상해 보세요. 카운터 뒤에 서서 고객 한 명 한 명을 직접 관찰할 수 있습니다. 그들이 들어와서 메뉴를 얼마나 오래 보았는지, 어떤 음료를 주문했는지, 망설이다가 나갔는지까지요.

하지만 "매장"이 모바일 앱이나 웹사이트라면 사용자의 조작을 직접 볼 수 없습니다. 이때 애플리케이션의 핵심 위치에 기록 포인트를 "매립"하여 사용자의 모든 조작을 자동으로 기록하는 기술적 수단이 필요합니다. 이것이 바로 데이터 트래킹(Event Tracking)입니다.

"트래킹"이라는 말은 전문적으로 들리지만, 핵심 아이디어는 매우 간단합니다. 사용자가 조작할 수 있는 곳에 "기록 장치"를 두고, 사용자가 무엇을 했는지 기록하는 것입니다.

이 장에서는 다음 네 단계로 설명합니다:

  1. 수집 방안 선택 — 어디에 기록 장치를 둘지, 어떻게 둘지 결정
  2. 데이터 형식 설계 — 각 기록에 어떤 정보를 포함해야 하는지 결정
  3. 전송과 캐싱 — 사용자의 휴대폰에서 서버로 안전하게 기록 전송
  4. 정제와 적재 — 데이터를 정리하고, 중복과 오류를 제거하여 데이터베이스에 저장

1단계: 수집 방안 선택 — 어디에 기록 장치를 둘 것인가?

목표: 사용자의 조작을 어떤 방식으로 기록할지 결정합니다.

예를 들어: 제품 매니저가 "구매 버튼을 클릭한 사용자가 몇 명인지" 알고 싶어 합니다. 이 질문에 답하려면 개발자가 "구매 버튼" 코드에 기록 로직을 추가해야 합니다 — 사용자가 이 버튼을 클릭할 때마다 자동으로 한 건을 기록하는 것입니다.

하지만 여기에 선택의 문제가 있습니다. 중요한 곳에만 기록 장치를 둘 것인가(예: "구매"와 "가입"만 기록), 아니면 모든 곳에 기록 장치를 둘 것인가(사용자의 모든 클릭, 스와이프, 체류 시간 기록)?

선택에 따라 서로 다른 트래킹 방안이 적용됩니다.

场景:用户在电商 App 点击了「加入购物车」按钮
捕获到的信息代码埋点可视化埋点全埋点
点击了哪个按钮
点击发生的时间
用户停留了多久
商品名称 / 价格
用了哪张优惠券
账户余额
页面滑动轨迹

💡 세 가지 주요 트래킹 방식

업계에서 일반적으로 사용하는 트래킹 방안은 세 가지이며, 각각 장단점이 있습니다:

방식 1: 코드 트래킹(Code Tracking) — 수동 정밀 기록

개발자가 코드에서 수동으로 지정합니다: 사용자가 특정 조작을 수행할 때 한 건의 데이터를 기록합니다.

비유하자면: 카페 계산대에 전담 직원을 배치해 "누가 무엇을 샀는지, 얼마를 지불했는지"만 기록하는 것과 같습니다. 기록 정보가 매우 상세하고 정확합니다.

  • 장점: 매우 상세한 비즈니스 정보를 기록할 수 있습니다 (예: 사용자가 어떤 쿠폰을 사용했는지, 계정 잔액은 얼마인지)
  • 단점: 새로운 기록 포인트를 추가하려면 개발자가 코드를 작성하고, 테스트하고, 새 버전을 배포해야 하므로 프로세스가 깁니다

방식 2: 시각적 트래킹(Visual Tracking) — 클릭 선택 기록

코드를 작성할 필요가 없습니다. 시스템이 시각화 도구를 제공하여, 운영 담당자가 애플리케이션 인터페이스에서 모니터링할 버튼이나 영역을 "선택"하면 시스템이 자동으로 기록을 시작합니다.

비유하자면: 카페의 CCTV 화면에서 마우스로 "계산대 영역"을 선택하면 시스템이 자동으로 해당 구역의 유동 인구를 집계하기 시작하는 것과 같습니다.

  • 장점: 개발자의 참여 없이 운영 담당자가 직접 구성할 수 있어 효율이 높습니다
  • 단점: "사용자가 무엇을 클릭했는지" 같은 인터페이스 조작만 기록할 수 있고, "주문 금액" 등 심층 비즈니스 데이터는 기록할 수 없습니다

방식 3: 전면 트래킹(Auto Tracking) — 모든 것을 자동 기록

애플리케이션에 SDK(일종의 "도구 패키지")를 통합하면, 사용자의 모든 조작을 자동으로 기록합니다: 모든 클릭, 모든 스와이프, 각 페이지에서의 체류 시간까지요.

비유하자면: 카페의 모든 구석에 CCTV를 설치하여 고객의 일거수일투족을 기록하는 것과 같습니다.

  • 장점: 어떤 조작도 누락하지 않아 커버리지가 가장 포괄적입니다
  • 단점: 데이터량이 매우 많으며, 그중 많은 부분이 무용한 정보(예: 사용자의 무의식적 스와이프)라서 후속 필터링과 정제에 많은 노력이 필요합니다

이 단계 요약: 트래킹 방식을 선택하면 애플리케이션에 "사용자 조작 기록" 능력이 생깁니다.

하지만 새로운 문제가 있습니다: 기록 장치가 사용자의 조작을 포착할 수 있지만, 각 기록 장치가 기록하는 형식이 다르다면(예: 어떤 것은 "사용자ID"라고 쓰고, 어떤 것은 "userID"라고 쓰고, 어떤 것은 아예 기록하지 않음) 나중에 통합 분석이 불가능합니다. 그래서 다음 단계에서는 통일된 기록 형식을 규정해야 합니다.


2단계: 데이터 형식 설계 — 각 기록에는 무엇이 포함되어야 하는가?

전제 조건: 트래킹 방식을 선택했고(예: 코드 트래킹), 애플리케이션이 사용자의 조작을 포착할 수 있습니다.

이 단계 목표: 통일된 "기록 템플릿"을 규정하여 모든 트래킹 기록의 형식이 일관되게 합니다.

왜 통일된 형식이 필요한가? 카페에 직원 3명이 동시에 판매 상황을 기록하는데, 한 명은 "홍길동이 버블티 5,000원 구매", 다른 한 명은 "5,000, 티, 버블", 세 번째는 "버블티 1잔"이라고 적는다고 상상해 보세요. 월말 집계 시 이 기록들은 형식이 완전히 달라 정리하기가 매우 고통스럽습니다. 그래서 각 기록에 반드시 작성해야 할 항목을 규정하는 통일된 "기록표"가 필요합니다.

What"event": "add_to_cart"
Who"user_id": "u_98765"
When"time": "2025-08-12T10:33:09Z"
Where"device": "iPhone 15", "network": "5G"
What"product": "新款手机", "price": 2999
点击上方按钮,观察一条埋点记录是如何被组装出来的

💡 핵심 원리: 4W1H 기록 템플릿

어떤 조작을 기록하든 각 데이터는 다음 다섯 가지 질문에 답해야 합니다(약칭 4W1H):

Who — 누가 했는가?

이 기록이 어느 사용자에 의해 생성되었는지 알아야 합니다.

  • 사용자가 이미 로그인한 상태라면 계정 ID를 사용합니다 (예: user_id: "hong123")
  • 로그인하지 않은 상태라면 기기의 고유 식별자(예: 휴대폰 기기 번호)를 사용합니다. 적어도 "같은 휴대폰에서의 조작"은 구분할 수 있습니다

When — 언제 했는가?

조작이 발생한 정확한 시간을 밀리초 단위로 기록합니다.

여기에 한 가지 세부 사항이 있습니다: 해외 사용자가 있는 애플리케이션의 경우 서울 시간 오후 3시와 뉴욕 시간 오후 3시는 실제로 13시간 차이가 납니다. 혼란을 피하기 위해 모든 시간을 UTC 표준 시간(즉, "세계 통일 시간")으로 변환합니다.

Where & How — 어떤 환경에서 했는가?

이 부분은 사용자가 조작할 때의 기기 및 네트워크 환경을 기록하며, 공통 속성이라고 부릅니다. "공통"이라고 하는 이유는 사용자가 어떤 조작을 하든 이 정보가 자동으로 첨부되기 때문입니다. 예를 들어:

  • 기기 모델: iPhone 15 / 갤럭시 S24
  • 네트워크 유형: WiFi / 5G / 4G
  • 앱 버전 번호: v1.2.3
  • 운영 체제: iOS 18 / Android 15

이 정보의 가치는 특정 기기에서만 나타나는 버그를 발견했을 때 공통 속성이 문제를 빠르게 파악하는 데 도움이 된다는 것입니다.

What — 구체적으로 무엇을 했는가?

이 부분은 조작의 구체적 비즈니스 세부 사항을 기록하며, 커스텀 속성이라고 부릅니다. 조작마다 다른 정보를 기록해야 합니다. 예를 들어:

  • 사용자가 "장바구니에 추가" 클릭: 상품명, 상품 가격, 수량 기록 필요
  • 사용자가 결제 완료: 주문 금액, 결제 수단, 쿠폰 번호 기록 필요

이 단계 요약: 4W1H 템플릿을 통해 사용자의 모든 조작을 형식이 통일된 데이터 기록으로 변환합니다. 기술적 구현에서 이 기록은 보통 JSON 형식으로 저장됩니다(JSON은 범용 데이터 형식으로, 위의 인터랙티브 컴포넌트에서 그 모습을 확인할 수 있습니다).

하지만 또 다른 문제가 있습니다: 데이터 형식은 통일되었지만, 사용자 수가 많은 경우(예: 프로모션 기간에는 초당 수만 건의 기록이 생성됨) 휴대폰에서 기록이 생길 때마다 즉시 전송하는 것은 불가능합니다 — 배터리와 데이터를 많이 소모하고 서버도 감당하지 못합니다. 그래서 다음 단계에서는 더 똑똑한 전송 방식을 설계해야 합니다.


3단계: 전송과 캐싱 — 어떻게 데이터를 안전하게 서버로 보낼 것인가?

전제 조건: 사용자의 모든 조작이 형식이 통일된 JSON 데이터로 기록되었습니다.

이 단계 목표: 이 데이터를 사용자의 휴대폰(또는 브라우저)에서 서버로 안정적으로 전송합니다. 네트워크 상태가 좋지 않은 경우에도 데이터를 잃지 않습니다.

왜 바로 전송할 수 없는가? 기록이 생성될 때마다 즉시 네트워크 요청을 보내는 것은 편지를 쓸 때마다 우체국에 달려가는 것과 같습니다 — 비효율적입니다. 더 합리적인 방법은 편지를 모아 한 번에 보내는 것입니다.

📱
手机
📦
打包
🌐
发送
🚦
排队
🗄️
入库
产生数据攒一批网络传输消息队列数据仓库

💡 핵심 원리: 데이터 전송의 3중 보장

데이터가 사용자의 휴대폰에서 서버까지 가려면 효율적이면서도 데이터를 잃지 않도록 3중 보장 메커니즘이 필요합니다:

첫 번째: 모아서 보내기(배치 집계)

SDK(트래킹 도구 패키지)는 기록이 생성될 때마다 전송하지 않고, 먼저 휴대폰 메모리에 임시 보관합니다. 일정 수량(예: 30건)이 모이거나, 일정 시간(예: 5초)이 지나면 이 배치를 패키징하여 한 번에 전송합니다.

택배에 비유하면: 물건을 하나 살 때마다 택배를 보내는 것이 아니라 몇 개를 모아 함께 보내면 시간과 노력이 절약됩니다. 휴대폰의 경우 이렇게 하면 네트워크 요청 횟수를 줄여 배터리와 데이터를 절약할 수 있습니다.

두 번째: 오프라인에서도 안전(로컬 저장)

엘리베이터나 지하철 터널에서 휴대폰은 자주 네트워크 신호를 잃습니다. 데이터가 메모리에만 있으면 사용자가 앱을 닫을 때 데이터가 사라집니다.

그래서 SDK는 아직 전송하지 못한 데이터를 휴대폰의 로컬 저장소에 보관합니다(편지를 서랍에 먼저 넣어두는 것과 유사). 네트워크가 복구되면 자동으로 이 데이터를 재전송합니다. 이렇게 하면 사용자가 일시적으로 오프라인이 되어도 데이터가 손실되지 않습니다.

세 번째: 서버 과부하 방지(메시지 큐)

데이터가 서버에 도착한 후 바로 데이터베이스에 기록되는 것은 아닙니다. 왜요? 프로모션 등 피크 시간에는 초당 수만 건의 데이터가 한꺼번에 몰려올 수 있어, 데이터베이스가 이를 직접 처리하면 다운될 수 있기 때문입니다.

해결책은 중간에 "버퍼 영역"을 추가하는 것입니다. 기술적으로 메시지 큐(대표적 도구로 Kafka)라고 부릅니다. 식당의 번호표 대기 시스템과 같은 역할을 합니다: 피크 시간에는 고객(데이터)이 먼저 줄을 서서 기다리고, 주방(데이터베이스)이 자신의 속도에 맞춰 하나씩 처리하며, 한꺼번에 몰려드는 주문에 압도당하지 않습니다.

이 단계 요약: "모아서 보내기 → 오프라인 로컬 저장 → 메시지 큐 버퍼링"의 3중 보장을 통해 데이터가 안전하게 서버에 도착했습니다.

하지만 한 가지 문제가 더 있습니다: 네트워크가 끊겼다가 재연결되면 데이터가 자동으로 재전송되므로, 같은 기록이 두 번 전송될 수 있습니다. 이를 처리하지 않고 그대로 데이터베이스에 저장하면 데이터가 중복됩니다(예: 10만 원짜리 주문이 두 건으로 기록되면 매출이 부풀려집니다). 그래서 다음 단계에서는 데이터를 "정제"해야 합니다.


4단계: 정제와 적재 — 데이터를 정리하고 "더러운 데이터" 제거

전제 조건: 데이터가 전송 파이프라인을 통해 안전하게 서버에 도착했습니다.

이 단계 목표: 데이터가 공식적으로 데이터베이스에 저장되기 전에 "건강 검진"을 실시합니다 — 중복을 제거하고, 형식에 문제가 있는 것을 수정하여, 최종적으로 저장되는 데이터가 깨끗하고 정확하도록 합니다.

왜 정제가 필요한가? 택배 한 상자를 받은 후 확인하는 것과 같습니다: 중복 배송은 없는지? 잘못 배송된 것은 없는지? 포장이 훼손된 것은 없는지? 데이터도 마찬가지로 데이터베이스에 저장하기 전에 먼저 확인하고 정리해야 합니다.

이 과정은 기술적으로 ETL이라고 부르며, 세 영어 단어의 약자입니다:

  • Extract(추출): 메시지 큐에서 데이터를 꺼냄
  • Transform(변환): 데이터 형식을 확인하고 수정
  • Load(적재): 정제된 데이터를 데이터베이스에 기록
原始数据(服务器收到的)
id-001 userId: "zhang" add_to_cart ¥2999
id-001 userId: "zhang" add_to_cart ¥2999重复
id-002 user_id: "li" click_buy ¥0
id-003 userId: "wang" pay 1970-01-01时间异常
id-004 user_id: "zhao" click_buy ¥599
ETL 清洗
清洗后(写入数据仓库的)
id-001 user_id: "zhang" add_to_cart ¥2999
id-002 user_id: "li" click_buy ¥0
id-004 user_id: "zhao" click_buy ¥599

💡 핵심 원리: 데이터 정제의 두 가지 핵심 동작

동작 1: 중복 제거 — 중복 기록 제거

앞서 언급했듯 네트워크 재연결 후 SDK가 데이터를 자동 재전송하여 같은 기록이 여러 번 전송될 수 있습니다. 어떻게 중복을 식별할까요?

방법은 간단합니다: 클라이언트에서 데이터를 패키징할 때 각 기록에 전 세계적으로 유일한 번호를 할당합니다(dedup_id라고 하며, 택배 송장 번호와 유사). 서버는 데이터를 저장하기 전에 이 번호가 이미 존재하는지 확인합니다 — 이미 존재한다면 중복 데이터이므로 바로 폐기합니다.

동작 2: 검증과 형식 통일 — 비표준 기록 수정

애플리케이션은 계속 버전이 업데이트되며, 버전마다 트래킹 코드에 미세한 차이가 있을 수 있습니다. 예를 들어:

  • 구버전은 사용자 ID 필드를 userId로 명명했지만, 신버전은 user_id로 변경
  • 일부 기록의 타임스탬프가 분명히 비합리적(예: 1970년으로 표시)
  • 일부 필드의 값을 인식할 수 없음

이 단계에서 시스템은 변환 규칙을 작성하여 이러한 문제를 통일적으로 처리합니다. 필드명이 일치하지 않는 것은 통일하고, 타임스탬프가 비정상인 기록은 폐기하며, 인식할 수 없는 값은 unknown으로 표시합니다.

이 단계 요약: 중복 제거와 형식 검증 후, 데이터는 깨끗하고 통일된 형태로 데이터 웨어하우스(대량의 데이터를 저장하고 분석하는 데 특화된 데이터베이스로, ClickHouse, Hive 등이 대표적)에 기록됩니다. 데이터 분석가는 SQL 문으로 이 데이터를 직접 조회하여 신뢰할 수 있는 분석 결과를 얻을 수 있습니다.


전체 프로세스 되돌아보기

다음은 데이터 트래킹의 수집부터 적재까지 4단계 프로세스 요약입니다:

단계수행 내용획득 결과남은 문제
1. 수집 방안 선택어떤 방식으로 사용자 조작을 기록할지 결정애플리케이션에 기록 능력 부여각 기록 장치의 데이터 형식이 비표준적
2. 데이터 형식 설계4W1H 템플릿으로 기록 형식 통일모든 기록이 표준 JSON사용자가 많을 때 건별 전송으로 감당 불가
3. 전송과 캐싱배치 전송, 오프라인 저장, 큐 버퍼링데이터가 안전하게 서버에 도착재시도로 인한 데이터 중복 가능
4. 정제와 적재중복 제거, 검증, 형식 통일✅ 깨끗한 데이터가 데이터 웨어하우스에 저장

맺음말

사용자가 애플리케이션에서 버튼을 클릭할 때, 겉으로는 순간적인 동작일 뿐입니다. 하지만 그 이면에서는 완전한 데이터 파이프라인이 이미 가동되고 있습니다:

  1. 트래킹 코드가 이 클릭을 포착하고 4W1H 템플릿에 따라 표준 기록을 생성합니다
  2. 기록이 휴대폰에 임시 보관되었다가 충분히 모이면 서버로 일괄 전송됩니다
  3. 서버는 메시지 큐를 통해 안정적으로 수신하고, 중복 제거와 형식 검증을 거칩니다
  4. 마침내 깨끗하고 정확한 데이터가 데이터 웨어하우스에 기록됩니다

이것이 데이터 트래킹의 전체 과정입니다. 사용자의 흩어져 있고 보이지 않는 조작 행위를 조회하고 분석할 수 있는 구조화된 데이터로 변환합니다. 제품 매니저는 어떤 기능을 사용자가 좋아하는지, 어디서 이탈하는지 파악할 수 있고, 운영 담당자는 이벤트 효과를 평가할 수 있으며, 개발자는 문제가 어느 버전에서 발생했는지 파악할 수 있습니다.

이 "수집 → 모델링 → 전송 → 정제" 체계는 데이터 기반 의사결정의 기반 인프라입니다.