개념
저울이 틀어진 채로 다이어트 결과를 발표하는 일
체중계가 2kg 적게 나오는 줄 모르고 석 달간 식단을 기록했다고 해 보자. 그래프는 예쁘게 내려가고, 기록은 성실하고, 숫자에 거짓도 없다. 그런데 그 숫자를 근거로 건강검진 결과를 설명하면 전부 어긋난다. 문제는 노력이 아니라 저울이다.
시리즈 A의 IR 자료가 정확히 이 구조다. 회사가 투자자에게 제출하는 숫자는 외부 기관이 매긴 점수가 아니라 우리 제품이 스스로 써낸 기록이다. 그 저울 — 이벤트 수집 코드, 회원 상태 테이블, 결제 상태 전이 — 은 전부 개발·QA의 손 안에 있다. 그래서 라운드 1(레슨 1)에서 말한 "증명에 쓰이는 숫자 자체가 제품이 만들어낸 데이터" 라는 문장은 수사가 아니라 업무 분장이다. 저울의 품질은 QA의 일이다.
시리즈 A는 숫자로 통과하는 라운드다
시드까지가 "이 팀이 만들 수 있는가" 였다면 시리즈 A는 "만든 것이 실제로 쓰이는가" 를 묻는다. 그래서 심사 과정의 상당 부분이 지표 검토다. 경험 많은 심사역이 IR 덱에서 가장 먼저 찾는 것은 매출 그래프가 아니라 코호트 리텐션 차트라는 조언이 반복되는 이유이기도 하다 — 성장은 마케팅비로 살 수 있지만 리텐션은 살 수 없기 때문이다.
| 지표 | 뜻 | 자주 쓰는 기준선 |
|---|---|---|
| 코호트 리텐션 | 가입 시점별 집단이 N개월 뒤 남아 있는 비율 | 곡선이 평평해지는(flatten) 구간이 있는가 |
| MRR / ARR | 월·연 반복 매출 | 성장률과 그 지속성 |
| NRR (NDR) | 기존 고객만으로 계산한 매출 유지·확장률 | 100% 초과 여부 |
| 유료 전환율 | 가입 → 결제 전환 | 퍼널 단계별 이탈 지점 |
| CAC / LTV / 페이백 | 획득 비용 대비 생애 가치와 회수 기간 | 단위 경제성의 성립 여부 |
이 레슨은 지표를 잘 만드는 법(그로스의 영역)이 아니라, 그 지표가 사실인지 확인하는 법을 다룬다.
그 숫자는 어디에서 만들어지는가
QA가 개입할 지점을 찾으려면 숫자의 생산 경로를 먼저 그려야 한다.
[사용자 행동]
↓ 클라이언트 이벤트 (웹/앱 SDK)
[이벤트 수집] GA4 · Amplitude · 자체 로그 파이프라인
↓ 적재·가공 (ETL)
[분석 DB / 대시보드]
↑
[운영 DB] 회원·구독·주문 상태 [PG·앱스토어] 결제·환불·정산
↓
[IR 자료의 숫자]투자 자료의 한 칸은 이 경로 전체의 마지막 출력이다. 중간 어디에서든 결함이 있으면 회사는 틀린 숫자로 투자를 받는다. 그리고 그 틀림은 실사 단계(레슨 5)나 투자 후 보고 단계에서 훨씬 비싸게 드러난다.
구간마다 쓸 수 있는 검증 도구가 다르다는 점이 실무적으로 중요하다.
| 구간 | 여기서 생기는 결함 | QA가 쓰는 도구 |
|---|---|---|
| 행동 → 이벤트 전송 | 누락·중복·파라미터 오타 | 개발자 도구 네트워크 탭, SDK 디버그 모드 (모듈 9 레슨 12) |
| 이벤트 → 수집 서버 | 재시도 중복, 오프라인 큐 지연 | 네트워크 차단 후 재연결 시나리오 |
| 수집 → 분석 DB (ETL) | 중복 적재, 타임존 변환, 스키마 변경 | 원천 대비 적재 건수 쿼리 (모듈 61 레슨 2) |
| 운영 DB → 분석 DB | 상태 전이 미전파(탈퇴·환불) | 두 DB 교차 쿼리 |
| PG·앱스토어 → 운영 DB | 결제 실패가 성공으로 기록, 환불 미반영 | 정산 내역 대사 |
| 분석 DB → IR 자료 | 정의 불일치, 수동 가공 | 정의서 대조, 재계산 |
마지막 줄을 빠뜨리기 쉽다. 대시보드 숫자가 맞아도, 그 숫자를 사람이 스프레드시트로 옮기면서 기간을 잘못 잡거나 다른 정의로 합치면 자료에는 틀린 숫자가 들어간다.
지표마다 데이터 경로가 다르다
"지표를 검증한다" 는 말은 너무 넓다. 지표별로 무엇을 세는 분자와 분모가 어디서 오는지를 각각 알아야 테스트를 설계할 수 있다.
| 지표 | 분모 | 분자 | 가장 흔한 틀어짐 | QA의 첫 질문 |
|---|---|---|---|---|
| 코호트 리텐션 | 코호트 가입자 수 (운영 DB) | N개월 뒤 활성 사용자 (이벤트) | 분모·분자가 다른 시스템·다른 타임존 | 가입일 기준과 활성 판정 기준의 시간대가 같은가 |
| 유료 전환율 | 가입자 또는 체험 시작자 | 첫 결제 성공자 (PG) | 무료체험·재결제가 분자에 섞임 | 같은 사용자를 양쪽에서 같은 키로 세는가 |
| MRR / ARR | — | 활성 구독의 월 환산 금액 | 환불·일시정지·할인 쿠폰 미반영 | 해지 예약 상태를 활성으로 세는가 |
| NRR | 기준월 기존 고객 매출 | 같은 고객의 비교월 매출 | 신규 고객이 분자에 혼입 | 고객 식별자가 기간 간 유지되는가 |
| CAC | 신규 고객 수 (제품 데이터) | 마케팅 비용 (재무) | 분모가 부풀면 CAC가 싸 보인다 | 봇·중복 가입이 신규에서 빠지는가 |
| LTV / 페이백 | — | 평균 매출 × 예상 유지 기간 | 리텐션이 틀리면 LTV가 함께 틀린다 | 리텐션 숫자를 먼저 검증했는가 |
마지막 줄이 이 표의 요점이다. 유닛 이코노믹스는 리텐션 위에 쌓아 올린 계산이므로, 리텐션이 10% 부풀면 LTV와 페이백 기간이 동시에 틀어진다. 지표 하나의 오류가 독립적으로 머물지 않는다.
코호트 리텐션 — 분모와 분자가 함께 흔들린다
리텐션은 단순한 나눗셈이지만, 분자와 분모가 서로 다른 시스템에서 온다는 점이 결함의 근원이다.
M3 리텐션 = (가입 3개월 뒤 "활성" 인 사람) ÷ (그 달 가입자 수)
└─ 이벤트 파이프라인 └─ 운영 DB users 테이블
분모가 작아지면 → 리텐션이 높아 보인다
· 월말 가입자가 타임존 때문에 다음 코호트로 밀림
· 비로그인 가입 경로가 users 에 늦게 기록됨
분자가 커지면 → 리텐션이 높아 보인다
· 시스템이 발생시킨 이벤트(토큰 갱신·푸시 수신)를 활성으로 셈
· 탈퇴·휴면 계정이 활성 집계에 남음
· 같은 행동이 두 번 전송됨양쪽 오류가 같은 방향으로 작용한다는 점이 고약하다. 둘 다 리텐션을 높이는 쪽으로 틀어지므로, 오류가 서로 상쇄되기를 기대할 수 없다. 그래서 "활성" 의 정의에서 누가 그 이벤트를 발생시켰는가(사용자인가 시스템인가)를 구분하지 않으면 지표는 거의 반드시 부풀어 오른다.
전환율 — 퍼널의 각 단계가 같은 사용자를 세고 있는가
전환율 결함의 대부분은 계산식이 아니라 식별자에서 나온다.
| 함정 | 증상 | 확인 방법 |
|---|---|---|
| 익명 ID와 로그인 ID가 이어지지 않음 | 방문 → 가입 전환율이 비정상적으로 낮음 | 로그인 직후 익명 ID 병합(identity stitching) 호출 여부 |
| 세션 기준과 사용자 기준 혼용 | 단계별 숫자의 합이 맞지 않음 | 각 단계가 세는 단위를 명시했는가 |
| 앱 재설치·로그아웃 시 ID 재발급 | 신규 사용자 과다, 리텐션 과소 | 디바이스 ID 대신 계정 ID를 쓰는가 |
| 단계 간 기간 창(window) 미정의 | 같은 기간인데 숫자가 다름 | "7일 내 전환" 인가 "기간 내 아무 때나" 인가 |
| A/B 분기 할당 누락 | 실험군 표본비 불일치(SRM) | 할당 이벤트와 노출 이벤트의 건수 비교 (모듈 61 레슨 6) |
세 번째 항목은 특히 모바일에서 조용히 터진다. 앱을 재설치한 기존 사용자가 신규 가입자로 집계되면 CAC 분모가 커져 획득 비용이 실제보다 싸 보이고, 동시에 그 사용자는 원래 코호트에서 사라져 리텐션이 낮아 보인다. 하나의 결함이 두 지표를 반대 방향으로 틀어놓는다.
유닛 이코노믹스 — QA가 가장 늦게 보는 숫자
CAC·LTV·페이백은 재무가 계산한다고 여겨져 QA의 시야에서 빠지기 쉽다. 그런데 그 계산에 들어가는 분모와 기간 가정은 전부 제품 데이터다.
CAC = 마케팅 비용(재무) ÷ 신규 고객 수(제품)
LTV = 평균 월 매출(결제) × 평균 유지 개월(리텐션)
페이백 = CAC ÷ 월 기여 이익
제품 데이터가 틀리면
신규 고객 수 10% 과다 → CAC 약 9% 저평가
리텐션 10%p 과다 → 평균 유지 개월 과다 → LTV 과다
→ LTV/CAC 비율이 실제보다 좋게 보인다투자자가 가장 믿고 싶어 하는 숫자가 가장 부풀기 쉬운 구조라는 점을 기억한다. 이 지점에서 QA가 할 수 있는 가장 값싼 기여는 "신규 고객 수에서 무엇을 제외했는지" 한 줄을 확인하는 것이다.
지표 데이터가 실제로 틀어지는 지점
현장에서 반복적으로 발견되는 유형이다. 기능 테스트와 달리 화면에서는 정상으로 보인다는 점이 공통점이다.
| 유형 | 증상 | 확인 방법 |
|---|---|---|
| 이벤트 중복 전송 | 활성 사용자·클릭 수 과다 | 한 번의 행동으로 발생한 이벤트 수 세기, 재시도 로직 확인 |
| 이벤트 누락 | 전환율이 실제보다 낮음 | 앱 백그라운드 전환·네트워크 끊김 시 큐 적재 여부 |
| 내부·봇 트래픽 혼입 | 신규 가입·조회 수 부풀림 | 사내 IP·테스트 계정·크롤러 제외 규칙 존재 여부 |
| 탈퇴·휴면 처리 누락 | MAU가 줄지 않음 | 탈퇴 계정이 활성 집계에서 빠지는지 |
| 시스템 유발 이벤트 혼입 | 앱을 열지 않은 사용자가 활성 | 토큰 갱신·푸시 수신이 활성 이벤트로 기록되는지 |
| 결제 실패가 성공으로 기록 | 매출·전환율 과다 | PG 응답 코드와 내부 주문 상태의 전이 매핑 |
| 타임존·집계 경계 | 일별 수치가 어긋남 | UTC/KST 혼용, 자정 경계 케이스 |
| 환불·취소 미반영 | 매출 과다 | PG 취소 → 내부 상태 → 분석 DB 반영 지연 |
| 무료체험이 유료로 분류 | 유료 전환율 과다 | 결제 금액 0원 건의 분류 규칙 |
| 정의 불일치 | 부서마다 다른 숫자 | "활성 사용자" 의 정의 문서 존재 여부 |
| 앱 버전별 스키마 차이 | 특정 구간만 데이터 공백 | 구버전 앱의 이벤트 이름·파라미터 |
마지막 두 줄이 가장 자주, 가장 조용히 발생한다. 정의가 다르면 누구도 틀리지 않았는데 숫자가 다르다.
정의가 합의되지 않은 것도 결함이다
이 레슨에서 가장 받아들이기 어려운 관점이다. 코드가 설계대로 동작하는데도 결함으로 다뤄야 하는 경우가 있다 — 그 "설계" 가 부서마다 다를 때다.
| 지표 | 그로스의 정의 | 재무의 정의 | 개발의 구현 | 결과 |
|---|---|---|---|---|
| 활성 사용자 | 앱을 연 사람 | 돈을 낸 사람 | 이벤트가 1건 이상인 ID | 세 숫자가 모두 다르다 |
| 유료 전환 | 체험 시작자 중 결제한 사람 | 결제가 정산까지 완료된 건 | 결제 API 200 응답 | 환불·실패 처리에서 갈린다 |
| 이탈(churn) | 30일 미접속 | 구독 해지 | status != 'active' | 해지 예약 상태의 처리가 다르다 |
| 신규 고객 | 처음 가입한 ID | 처음 결제한 계정 | created_at 이 이번 달 | 재설치·재가입에서 갈린다 |
ISTQB의 결함 정의는 "요구사항과 실제 동작의 차이" 다. 그런데 요구사항이 서로 모순되면 어떤 구현을 하더라도 누군가의 요구사항은 깨진다. 그 상태 자체가 결함이고, 모듈 2(요구사항)에서 배운 모호성·모순 검출이 지표 영역에서 하는 일이 바로 이것이다.
실무에서는 이렇게 보고한다. "활성 사용자 집계가 틀렸습니다" 가 아니라 "활성 사용자의 정의가 세 부서에서 다르게 쓰이고 있고, 대시보드는 그중 어느 것도 아닙니다" 로 쓴다. 전자는 개발 티켓이 되고 후자는 결정 요청이 된다. 지표 정의 결함은 코드로 닫히지 않고 합의로 닫힌다.
지표 정의서 — QA가 만들 수 있는 가장 저렴한 방어선
지표마다 한 장짜리 정의서를 만들고, 그 정의대로 테스트를 설계한다.
지표 : 주간 활성 사용자 (WAU)
정의 : 최근 7일(KST 기준) 내 핵심 행동 1회 이상 수행한 고유 사용자
포함 : 웹·앱 모두, 로그인 사용자
제외 : 탈퇴·휴면 계정, 사내 계정 도메인, 자동화 테스트 계정, 봇 UA,
시스템이 발생시킨 이벤트(토큰 갱신·푸시 수신·백그라운드 동기화)
집계 시점 : 매일 04:00 KST, 전일 자정 기준
원천 : events.core_action 테이블 (dedup key = user_id + event_id)
알려진 한계: 비로그인 사용자는 집계되지 않음
정본 : 불일치 시 운영 DB 를 정본으로 본다 (재무팀 2026-07 합의)"제외" 와 "알려진 한계" 두 줄이 핵심이다. 실사에서 심사역이 묻는 질문의 절반이 이 두 줄에서 나온다.
마지막 "정본" 줄은 나중에 분쟁을 막는다. 숫자가 어긋났을 때 어느 쪽을 믿을지 미리 정해 두지 않으면 매달 같은 논쟁이 반복된다.
쿼리로 교차 검증하기 — QA가 실제로 치는 다섯 개의 질문
SQL을 깊이 알아야 하는 일이 아니다. 아래 다섯 가지 모양만 쓸 수 있으면 지표 결함의 대부분이 잡힌다. (문법은 모듈 9 레슨 5, 응용은 모듈 61 레슨 1·2)
① 중복이 있는가 — 같은 키가 2건 이상 나오는지
SELECT user_id, event_id, COUNT(*)
FROM events.core_action
WHERE event_date = '2026-08-01'
GROUP BY user_id, event_id
HAVING COUNT(*) > 1
② 분모와 분자의 모집단이 같은가 — 활성인데 회원이 아닌 ID
SELECT COUNT(DISTINCT e.user_id)
FROM events.core_action e
LEFT JOIN ops.users u ON u.id = e.user_id
WHERE u.id IS NULL OR u.status IN ('withdrawn', 'dormant')
③ 두 원천의 합계가 맞는가 — 운영 DB 와 분석 DB 의 일별 결제
운영 DB : SELECT paid_date, COUNT(*), SUM(amount) ... GROUP BY paid_date
분석 DB : SELECT date, orders, revenue ... GROUP BY date
→ 두 결과를 날짜로 붙여 차이 컬럼을 만든다
④ 상태 전이가 전파됐는가 — 취소됐는데 매출에 남은 건
SELECT o.id FROM ops.orders o
JOIN analytics.revenue r ON r.order_id = o.id
WHERE o.status = 'canceled'
⑤ 경계가 흔들리는가 — 자정 ±5분 구간의 건수
SELECT COUNT(*) FROM events.core_action
WHERE event_at BETWEEN '2026-08-01 23:55' AND '2026-08-02 00:05'
→ 이 구간 데이터가 어느 날짜로 집계되는지 양쪽 기준으로 확인②와 ④가 비용 대비 효과가 가장 크다. 둘 다 한 번 쓰면 매달 돌릴 수 있고, 결과가 0건이 아니면 그 자체로 결함 증거가 된다. 숫자가 0건이 아닌데 아무도 몰랐다는 사실이 보고서의 가장 강한 문장이 된다.
대사(Reconciliation) — 두 원천을 맞춰보는 테스트
돈과 관련된 숫자는 최소 두 곳에서 독립적으로 세어 맞춰본다.
같은 기간(2026-08) 결제 건수·금액을 세 곳에서 뽑아 비교
① 운영 DB 주문 테이블 : 12,418건 / 184,220,000원
② PG 정산 내역 : 12,418건 / 184,220,000원
③ 분석 DB 매출 지표 : 12,502건 / 185,610,000원 ← 불일치
차이 84건 추적 → 취소 주문이 분석 DB에 재집계됨(상태 변경 이벤트 누락)이 테스트는 모듈 4 레슨 6(마이그레이션·전환 검증)에서 다룬 대사 기법과 같은 구조다. 차이는 목적이다 — 거기서는 이관의 정확성을, 여기서는 회사가 외부에 말하는 숫자의 정확성을 지킨다.
대사는 한 번 하고 끝낼 일이 아니라 주기적으로 돌리고 임계값을 두는 일이다. 차이가 1% 를 넘으면 알림이 오게 해 두면, 다음 스키마 변경이나 상태 추가가 지표를 깨뜨리는 순간을 배포 직후에 알 수 있다. 분기마다 사람이 손으로 맞춰보는 방식은 반드시 한 번 건너뛴다.
이벤트 전송을 눈으로 확인하는 절차
이벤트는 화면에 아무 표시를 남기지 않는다. 그래서 기대 결과에 적지 않으면 영원히 검증되지 않는다. 확인 절차는 짧다.
1. 개발자 도구 네트워크 탭을 열고 분석 SDK 도메인으로 필터
2. 검증할 행동을 "한 번" 수행
3. 나간 요청의 개수 · 이벤트 이름 · 파라미터를 정의서와 대조
4. 같은 행동을 다음 네 조건에서 반복
· 새로고침 직후
· 뒤로가기로 돌아온 뒤
· 네트워크를 끊고 수행 → 재연결
· 구버전 앱 / 다른 브라우저
5. 재연결로 늦게 전송된 이벤트의 타임스탬프가
"행동 시점" 인지 "전송 시점" 인지 확인5번이 틀리면 일별 지표가 조용히 어긋난다. 기능은 멀쩡하고 데이터도 있는데 날짜만 밀린다. 자동화로 묶으려면 모듈 12(API·계약 테스트)의 스키마 검증을 이벤트 스펙에 그대로 적용하면 된다 — 이벤트 스펙은 사실상 클라이언트와 분석 시스템 사이의 계약이다.
| 환경 | 이벤트 확인 방법 | 주의 |
|---|---|---|
| 로컬·개발 | SDK 디버그 모드, 콘솔 로그 | 전송 자체가 꺼져 있을 수 있다 |
| QA·스테이징 | 분석 도구의 디버그 뷰 | 운영 프로젝트로 섞여 들어가지 않는지 |
| 운영 | 실시간 리포트, 네트워크 탭 | 테스트 행동이 지표를 오염시킨다 |
마지막 줄이 함정이다. 운영에서 검증하면 그 검증 자체가 지표를 오염시킨다. 테스트 계정 식별과 제외 규칙이 먼저 있어야 운영 검증이 가능해진다.
사례 — 리텐션 41%가 실제로는 32%였던 3개월
월 9,900원 구독 앱이 시리즈 A를 준비하고 있었다. IR 덱의 핵심 장은 코호트 리텐션 차트였고, 숫자는 M3 리텐션 41%, MAU 48,200 이었다. 곡선이 완만하게 평평해지는 모양이어서 심사역 반응도 좋았다.
문제는 재무팀의 한마디에서 시작됐다. "활성 사용자가 4만 8천인데 유료 구독이 3,100건이면 전환율이 6.4% 인데, 우리 결제 퍼널 전환율은 그보다 훨씬 높게 나왔다." 두 숫자가 동시에 참일 수 없었다.
QA가 운영 DB로 직접 재계산한 결과는 M3 리텐션 32%, 실질 MAU 41,800 이었다. 원인은 하나가 아니라 셋이었다.
| 원인 | 메커니즘 | 영향 |
|---|---|---|
| 시스템 유발 이벤트 | 앱이 백그라운드에서 토큰을 갱신할 때 app_open 을 전송 | 앱을 열지 않은 계정 5,100개 가 활성으로 집계 |
| 탈퇴 전파 누락 | 탈퇴가 운영 DB users.status 만 바꾸고 이벤트 파이프라인에는 신호가 가지 않음 | 탈퇴 후 푸시 수신 이벤트로 활성 유지 1,340개 |
| 타임존 경계 | 코호트 기준일은 가입일(KST), 활성 판정은 이벤트 타임스탬프(UTC) | 월말 가입자 일부가 다음 코호트로 밀려 분모가 작아짐 |
세 번째가 가장 설명하기 어려웠다. 코드에 버그가 없었기 때문이다. 한쪽은 KST로, 다른 쪽은 UTC로 각자 정확하게 동작했다.
바꾼 것은 넷이었다.
| 바꾼 것 | 효과 |
|---|---|
이벤트에 trigger 파라미터 추가 (user / system), 활성 정의에서 system 제외 | 부풀림의 가장 큰 덩어리를 제거 |
| 탈퇴·휴면 상태 변경을 이벤트 스트림으로 전파 | 두 시스템의 회원 상태가 같아짐 |
| 모든 집계의 타임존을 KST로 고정하고 월말·자정 경계 케이스를 회귀에 추가 | 코호트 분모가 안정됨 |
| 운영 DB 대비 분석 DB 주간 대사 배치 + 차이 1% 초과 시 알림 | 다음 스키마 변경 때 배포 주에 발견 |
결과는 숫자가 내려간 것이었다. IR 덱의 41%를 32%로 수정해 다시 제출했다. 밸류에이션 협상에서 불리하게 쓰일 수 있는 수정이었지만, 실사에서 "이 숫자를 어떻게 검증했습니까" 라는 질문이 나왔을 때 정의서와 대사 로그를 그대로 제출할 수 있었다. 라운드는 성사됐고, 심사역이 투자 후 첫 이사회에서 언급한 것은 리텐션 수치가 아니라 "자기 숫자를 먼저 정정한 회사" 라는 점이었다.
여기서 남는 교훈이 셋이다.
- 틀린 숫자를 우리가 먼저 찾는 것과 심사역이 찾는 것의 차이는 숫자의 크기가 아니라 신뢰다. 9%p 하향은 협상 재료지만, 실사에서 발각된 9%p는 모든 다른 숫자까지 의심받게 만든다.
- 시스템이 만든 이벤트는 사용자 행동이 아니다. 활성의 정의에 "누가 발생시켰는가" 가 빠져 있으면 지표는 반드시 한 방향으로 부풀어 오른다.
- 탈퇴는 한 시스템의 상태 변경이 아니라 여러 시스템에 걸친 전파다. 운영 DB만 보고 "탈퇴 처리가 된다" 를 통과시키면 지표에서 그 사용자는 살아 있다.
실무에서 왜 필요한가
틀린 지표는 결함보다 늦게, 더 비싸게 발견된다
기능 결함은 사용자가 신고한다. 지표 결함은 아무도 신고하지 않는다. 발견되는 시점은 대개 다음 세 곳 중 하나다.
- 투자 실사에서 심사역이 두 자료의 숫자가 다른 것을 발견했을 때
- 투자 후 이사회 보고에서 지표가 갑자기 "정정" 될 때
- 그 숫자를 근거로 한 의사결정(대규모 마케팅 집행 등)이 실패한 뒤
세 경우 모두 신뢰의 문제로 번진다. 숫자가 틀렸다는 사실보다, 그 회사가 자기 숫자를 검증하지 않는다는 사실이 더 크게 평가된다.
발견 시점별 가격표
기능 결함에서 익숙한 "왼쪽으로 갈수록 싸다" 는 원리가 지표에서도 같다. 다만 오른쪽 끝의 가격이 훨씬 비싸다.
| 발견 시점 | 치르는 비용 | 복구 가능성 |
|---|---|---|
| 기능 개발 중 (이벤트 스펙 리뷰) | 수정 몇 줄 | 완전 |
| 배포 전 QA (이벤트 전송 확인) | 릴리즈 하루 지연 | 완전 |
| 배포 후 주간 대사에서 | 재집계 배치 1회 | 대개 가능 |
| 분기 보고·IR 자료 준비 중 | 자료 재작성, 내부 신뢰 | 부분적 |
| 투자 실사에서 심사역이 먼저 | 밸류 조정, 추가 자료 요구 | 숫자는 고쳐도 신뢰는 어렵다 |
| 그 숫자로 내린 결정이 실패한 뒤 | 집행한 예산 전액 | 그 기간 데이터는 영구 손실 |
마지막 줄이 핵심이다. 이벤트가 전송되지 않은 기간의 데이터는 소급해서 만들 수 없다. 운영 DB에 원천이 남아 있으면 재집계가 되지만, 클라이언트 이벤트는 그 순간을 놓치면 끝이다. 그래서 지표 QA에서는 복구 불가 영역(클라이언트 이벤트)을 먼저 지킨다.
정본을 정하는 일이 QA의 일이 되는 이유
불일치를 찾는 것보다 어려운 것은 어느 쪽이 맞다고 할지 정하는 일이다. 그리고 이 결정은 QA가 혼자 내릴 수 없다.
| 숫자의 성격 | 통상적인 정본 | 이유 |
|---|---|---|
| 매출·환불·정산 | PG·앱스토어 정산 내역 | 외부 기관이 확정한 금액 |
| 주문·구독 상태 | 운영 DB | 서비스 동작의 근거 |
| 사용자 행동·퍼널 | 이벤트 파이프라인 | 운영 DB에 그 행동이 없다 |
| IR 자료의 숫자 | 정의서에 적힌 원천 | 자료마다 달라지면 안 된다 |
QA가 할 일은 정본을 정하는 것이 아니라 정본이 정해지지 않았다는 사실을 드러내고 결정을 요청하는 것이다. 결함 하나를 닫는 일이 아니라 같은 결함이 반복되지 않게 만드는 일이고, 모듈 6 레슨 3의 "비난이 아니라 정보 전달" 이 여기서는 "판단이 아니라 결정 요청" 의 형태가 된다.
QA가 그로스·데이터 조직과 만나는 지점
시리즈 A 전후로 회사에는 그로스·데이터 담당이 생긴다. 이때 QA의 역할은 지표를 해석하는 것이 아니라 지표 파이프라인을 테스트 대상 시스템으로 보는 것이다. 이벤트 스펙은 API 계약과 같은 성격을 갖고 (모듈 12의 계약 테스트), 스키마 변경은 곧 회귀 위험이다.
역할 분담을 분명히 해 두면 충돌이 줄어든다.
| 질문 | 답하는 사람 |
|---|---|
| 이 지표를 어떻게 올릴까 | 그로스 |
| 이 지표를 무엇으로 정의할까 | 그로스 + 재무 (QA가 문서화를 요구) |
| 이 지표가 정의대로 계산되고 있는가 | QA |
| 원천 데이터가 사실인가 | QA |
| 파이프라인을 어떻게 고칠까 | 데이터 엔지니어 |
릴리즈 체크리스트에 한 줄이 늘어난다
신규 기능을 배포할 때 "이 기능이 지표를 깨뜨리지 않는가" 를 확인하는 항목이 필요하다.
[지표 영향 점검]
- 이 변경으로 이벤트 이름·파라미터가 바뀌는가?
- 기존 대시보드·정의서에 영향이 있는가?
- 구버전 앱 사용자의 이벤트는 어떻게 되는가?
- A/B 테스트 중이라면 분기 할당이 지표에 반영되는가?
- 회원 상태(탈퇴·휴면·정지)를 바꾸는 변경이면 분석 쪽으로 전파되는가?
- 새 결제 수단·쿠폰·부분환불이 매출 집계 규칙에 들어가 있는가?이 여섯 줄은 모듈 9 레슨 8(PR diff에서 리스크 읽기)의 판단을 지표 영역으로
옮긴 것이다. track( 이나 logEvent( 가 포함된 diff는 그 자체로
지표 회귀 후보로 본다.
채용시장에서의 위치
"데이터 QA", "지표 검증", "이벤트 트래킹 QA" 는 시리즈 A~B 기업 공고에서 점점 자주 보이는 표현이다. 분석 도구를 다뤄본 경험보다 정합성을 설계하는 사고가 평가된다.
| 요구사항 표현 | 실제로 보는 것 |
|---|---|
| "데이터 정합성 검증 경험" | 두 원천을 맞춰본 경험, 차이를 추적한 방법 |
| "SQL 활용 가능" | 집계 쿼리로 직접 반례를 찾을 수 있는가 |
| "GA4·Amplitude 이해" | 이벤트 스키마와 사용자 식별 방식의 함정을 아는가 |
| "그로스팀과 협업" | 지표 정의 합의를 끌어낸 경험 |
| "데이터 기반 의사결정 지원" | 숫자를 만든 게 아니라 숫자를 의심해 본 경험 |
모듈 9(개발 기초)의 SQL·로그 읽기와 모듈 12(API·계약 테스트)가 이 직무의 실제 기반이고, 모듈 61(데이터 확인 — SQL·로그·분석)이 이 레슨의 기법을 도구 단위로 다룬다.
질문별로 갈리는 지점
| 질문 | 약한 답 | 강한 답 |
|---|---|---|
| "지표 데이터를 검증한 경험이 있나요?" | "대시보드 숫자를 확인했습니다" | "운영 DB와 분석 DB를 같은 기간으로 각각 집계해 차이를 추적했습니다. 원인은 취소 주문의 상태 전파 누락이었습니다" |
| "이벤트 트래킹은 어떻게 테스트하나요?" | "분석 도구에서 데이터가 들어오는지 봅니다" | "한 번의 행동에 이벤트가 정확히 한 번 나가는지, 오프라인 재전송 시 타임스탬프가 행동 시점인지를 기대 결과로 적습니다" |
| "부서마다 활성 사용자 숫자가 다르면요?" | "데이터팀에 확인을 요청합니다" | "어느 쪽이 틀렸다고 보기 전에 정의가 몇 개 있는지부터 적습니다. 정의가 합의되지 않은 상태 자체를 결함으로 올립니다" |
| "SQL은 어느 수준까지 쓰시나요?" | "SELECT와 JOIN은 가능합니다" | "GROUP BY HAVING으로 중복 키를 찾고, LEFT JOIN IS NULL로 한쪽에만 있는 레코드를 찾는 패턴을 주로 씁니다" |
| "리텐션이 좋아 보이는데 의심해 볼 점은?" | "표본이 작을 수 있습니다" | "분모와 분자가 다른 시스템에서 와서, 시스템 유발 이벤트와 타임존 경계가 둘 다 리텐션을 높이는 방향으로 틀어집니다" |
가장 변별력이 큰 질문
세 번째가 가장 크게 갈린다. "부서마다 숫자가 다르면" 이라는 질문은 기술 역량을 묻는 것처럼 보이지만 실제로는 문제를 어디에 두는 사람인지를 본다. 약한 답은 문제를 데이터팀에 넘긴다. 강한 답은 문제를 조직의 미정의 상태에 둔다. 후자는 시리즈 A 조직에서 실제로 필요한 태도다 — 이 단계의 회사는 정의가 없는 것이 정상이고, 그걸 만들 사람을 뽑는다.
다섯 번째는 지식의 깊이를 가린다. "표본이 작다" 는 교과서적인 답이고 틀리지도 않았다. 그런데 분모와 분자의 출처가 다르다는 구조를 말하는 답은 실제로 리텐션 쿼리를 들여다본 사람만 할 수 있다. 면접관이 데이터에 익숙한 사람이면 이 한 문장으로 대화의 수준이 올라간다.
반대로 두 번째를 도구 이름으로만 답하는 것이 가장 흔한 손실이다. "GA4 디버그 뷰를 씁니다" 는 도구 사용 경험이고, "한 번의 행동에 한 번" "타임스탬프가 행동 시점인가" 는 검증 설계다. 공고에 적힌 도구 이름은 필터이고, 합격을 가르는 것은 뒤쪽이다.