선주 모바일 GA4 측정 설계서
선주앱(RN 셸 + 풀웹뷰) GA4 신규 세팅 절차서입니다.
웹 스트림 · gtag.js 기준이며, 네이티브 SDK는 붙이지 않습니다.
STEP 1 → 10 순서대로 진행하며, 각 단계에 완료 확인 기준이 있습니다.
선주 모바일 GA4 세팅 가이드
- v4.0 · 2026-08-25 · 선주앱 GA4 신규 세팅 기준 (풀웹뷰 · 웹 스트림)
- STEP 1 → 10 순서대로 진행합니다. 각 단계 끝에 완료 확인 기준이 있습니다
- 예상 소요: 콘솔 설정 1시간 + 구현 1~2일 + 검증 반나절
- 앱 빌드·스토어 심사가 필요 없습니다. 웹 번들 배포만으로 측정이 반영됩니다
0. 사전 정보 — 용어와 동작 방식
GA4는 앱에서 발생한 행동을 이벤트 단위로 수집해 리포트로 조회하는 도구입니다. 이 문서에서 쓰는 용어는 아래 6개입니다.
용어
| 용어 | 의미 | 선주앱 적용 |
|---|---|---|
| 속성(Property) | 데이터가 쌓이는 큰 통 | aboutfishing-product (ID 295704822) — 이미 있음, 새로 만들지 마세요 |
| 데이터 스트림(Stream) | 통에 데이터를 붓는 파이프. 앱·웹마다 하나씩 | 선주앱용 웹 스트림을 새로 만듭니다 |
| 이벤트(Event) | "무슨 일이 일어났다" 한 줄 기록 | owner_confirm = 선주가 예약을 확정했다 |
| 파라미터(Parameter) | 그 일에 딸린 상세 정보 | count: 3 = 3건을 확정했다 |
| 커스텀 정의 | 파라미터를 GA 화면에서 볼 수 있게 등록하는 절차 | 등록 안 하면 보내도 안 보입니다 ⚠️ |
| DebugView | 내가 보낸 이벤트가 실시간으로 들어오는지 보는 화면 | 개발 중엔 여기만 봅니다 |
미리 알아둘 GA4 동작 3가지
- 파라미터는 커스텀 정의에 등록해야 리포트에 노출됩니다. 전송만으로는 조회되지 않습니다. (STEP 6)
- GA4 리포트는 24~48시간 지연됩니다. 개발 중 검증은 DebugView(실시간)로 합니다. (STEP 8)
- 이벤트 이름은 한 번 수집되면 삭제할 수 없습니다. 명명 규칙을 먼저 확정하는 이유입니다.
1. 준비물 체크리스트
아래 5개가 선행돼야 합니다.
- [ ] GA 계정 접근 권한 —
hiseo@aboutfishing.kr계정으로 속성aboutfishing-product에 편집자 권한. (개인 gmail로는 안 보입니다. 접속 시 URL 뒤에?authuser=1필요) - [ ] 선주앱 웹 도메인 — 웹뷰가 로드하는 주소. 예:
owner.aboutfishing.kr - [ ] RN 셸의 WebView 설정 파일 접근 — 쿠키·스토리지 옵션 4개를 확인해야 합니다 (STEP 3)
- [ ] 웹 번들 배포 버전을 코드에서 읽을 수 있는지 — 없으면 상수라도 하나 만들어 주세요
- [ ] 로그인 시점에 알 수 있는 값 — 내부 회원 해시 ID, 보유 선박 수, 가입일
Firebase 콘솔·google-services.json·네이티브 SDK는 이번 범위에 없습니다. 선주앱은 RN 셸로 감싼 풀웹뷰라, 측정 코드는 웹 번들에만 들어갑니다.
2. 전체 구조
[RN 셸] ── 웹뷰 하나만 띄움. 측정 코드 없음
│
└─ [웹 번들] gtag.js ──────────▶ [GA4 속성: aboutfishing-product]
track('owner_confirm', {...}) 선주앱 웹 스트림 (새로 만듦)
핵심 규칙: 측정 코드는 웹 번들 한 곳에만 둡니다. RN 셸에는 아무것도 붙이지 않습니다.
선주앱은 RN으로 패킹만 한 풀웹뷰라 네이티브 화면이 없습니다. 셸에 SDK를 붙여도 잡을 게 없고, 웹과 양쪽에서 보내면 동일 행동이 이중 집계됩니다. 사후 보정이 불가능해 데이터를 폐기해야 하므로 경로를 하나로 고정합니다.
이 구조에서 포기하는 것 — 필요해지면 그때 SDK를 추가합니다.
| 못 보는 것 | 대안 |
|---|---|
| 푸시 발송 대비 오픈률 | 딥링크 URL에 UTM을 달면 유입까지는 집계됩니다 |
| 앱 설치·삭제·앱 버전별 지표 | 웹 번들 버전(app_version)으로 배포 전후를 비교합니다 |
| 스토어 획득·설치 어트리뷰션 | 이번 범위 밖 |
STEP 1. 선주앱 웹 스트림 생성 (15분)
선주앱 데이터가 유입될 웹 스트림을 생성하고 측정 ID를 받아옵니다.
- 브라우저에서
analytics.google.com/?authuser=1접속 (반드시?authuser=1) - 좌하단 관리(톱니바퀴) 클릭
- 속성 열에서
aboutfishing-product선택돼 있는지 확인 - 데이터 수집 및 수정 → 데이터 스트림 클릭
- 우상단 스트림 추가 → 웹
- 웹사이트 URL에 선주앱 도메인(예:
owner.aboutfishing.kr), 스트림 이름에선주앱입력 - 향상된 측정 토글을 끈 상태로 만듭니다 (기본값은 켜짐 — 이유는 STEP 2)
- 스트림 만들기 → 화면에 뜨는 측정 ID
G-XXXXXXXXXX를 복사해 둡니다. STEP 3에서 씁니다
⚠️ 손님앱 웹 스트림에 추가하지 않습니다. 반드시 신규 스트림으로 만듭니다. 한 스트림에 섞이면 이후 분리가 불가능합니다.
완료 기준: 데이터 스트림 목록에 선주앱 웹 스트림이 있고, 측정 ID를 확보했습니다.
STEP 2. 기본 설정 변경 (5분)
기본값 3개를 변경합니다. 특히 데이터 보관은 나중에 바꿔도 소급 적용되지 않습니다.
| 설정 위치 | 바꿀 값 | 왜 |
|---|---|---|
| 관리 → 데이터 보관 | 2개월 → 14개월 | 기본값 2개월. 3개월 전 데이터 조회가 불가능해집니다 |
| 관리 → 데이터 수집 → Google 신호 데이터 | 사용 안 함 | 선주는 사업자 계정이라 광고 타겟팅용 수집이 불필요합니다 |
| 스트림 상세 → 향상된 측정 | 전부 끄기 | 아래 설명 |
향상된 측정을 끄는 이유
향상된 측정은 페이지 조회·스크롤·이탈 클릭·파일 다운로드를 GA가 알아서 수집하는 기능입니다. 일반 웹사이트에는 편리하지만 선주앱에는 맞지 않습니다.
- 선주앱은 화면 전환이 URL 변경 없이 일어나는 구조라, 자동 페이지 조회가 실제 화면과 어긋나게 찍힙니다
- 우리가
page_view를 직접 보내므로, 자동 수집이 켜져 있으면 한 화면이 두 번 집계됩니다 - 정산 엑셀은
owner_settlement_excel로 이미 잡으므로 자동 파일 다운로드 수집이 중복입니다
화면 조회를 포함해 전부 코드에서 직접 보냅니다. 경로가 하나여야 숫자를 신뢰할 수 있습니다.
완료 기준: 데이터 보관이 14개월이고, 스트림 상세의 향상된 측정 항목이 전부 꺼져 있습니다.
STEP 3. gtag 연결 + 웹뷰 설정 확인 (20분)
3-1. 웹 번들에 gtag 삽입
index.html 의 <head> 최상단에 넣습니다. STEP 1에서 받은 측정 ID로 G-XXXXXXXXXX 를 교체합니다.
<script async src="https://www.googletagmanager.com/gtag/js?id=G-XXXXXXXXXX"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){ dataLayer.push(arguments); }
gtag('js', new Date());
gtag('config', 'G-XXXXXXXXXX', {
send_page_view: false // 화면 조회는 STEP 5에서 직접 보냅니다
});
</script>
send_page_view: false가 핵심입니다. 빼면 앱 진입 시page_view가 자동으로 한 번 찍히고, STEP 5의 수동 전송과 겹쳐 첫 화면만 두 배로 집계됩니다.
3-2. RN WebView 설정 4개 — 이걸 놓치면 사용자 수가 부풀려집니다
gtag는 방문자 식별자(_ga)를 쿠키와 localStorage에 저장합니다. 웹뷰가 이걸 유지하지 못하면 앱을 켤 때마다 새 사용자로 잡혀서, 실제 선주 200명이 월 사용자 3,000명으로 나옵니다.
react-native-webview 에서 아래 4개를 확인합니다.
<WebView
source={{ uri: 'https://owner.aboutfishing.kr' }}
sharedCookiesEnabled={true} // iOS — 쿠키를 앱 재시작 후에도 유지
thirdPartyCookiesEnabled={true} // Android — 쿠키 저장 허용
domStorageEnabled={true} // Android — localStorage 활성화
incognito={false} // ⚠️ true 면 종료 시 전부 삭제됩니다
javaScriptEnabled={true}
/>
| 옵션 | 없으면 생기는 일 |
|---|---|
sharedCookiesEnabled (iOS) | 앱 재시작마다 새 사용자. iOS 지표만 부풀려집니다 |
thirdPartyCookiesEnabled (Android) | 안드로이드에서 식별자 저장 실패 |
domStorageEnabled (Android) | localStorage 폴백까지 막혀 세션이 매번 끊깁니다 |
incognito={false} | 앱 종료 시 전부 삭제. 재방문 사용자가 0이 됩니다 |
이 4개는 RN 셸 코드를 한 번 수정해야 하므로, 이 단계에서만 앱 빌드가 필요할 수 있습니다. 이미 켜져 있으면 빌드 없이 끝납니다. 이후 이벤트 추가·수정은 전부 웹 배포만으로 반영됩니다.
완료 기준: STEP 8의 DebugView에서 session_start·first_visit 가 확인되고, 앱을 완전히 종료했다 다시 켰을 때 first_visit 가 다시 찍히지 않습니다. (다시 찍히면 3-2 설정 누락)
STEP 4. 이벤트 이름 상수화 (10분)
이벤트명 오타는 GA에서 경고 없이 별도 이벤트로 집계됩니다. owner_confirm 과 owner_comfirm 은 서로 다른 이벤트로 쌓입니다.
// analytics/events.ts — 문자열을 코드에 직접 쓰지 말 것
export const EV = {
CONFIRM : 'owner_confirm',
CANCEL : 'owner_cancel',
PRODUCT_CREATE : 'owner_product_create',
CLOSE_NOW : 'owner_close_now',
SEAT_ADJUST : 'owner_seat_adjust',
BULK_EDIT : 'owner_bulk_edit',
MANUAL_ADD : 'owner_manual_add',
CALL_TAP : 'owner_call_tap',
SETTLEMENT_EXCEL : 'owner_settlement_excel',
FRICTION : 'owner_friction',
} as const;
export const SCREEN = {
HOME : 'OWN_HOME',
PROD_DAILY : 'OWN_PROD_DAILY',
PROD_MASTER : 'OWN_PROD_MASTER',
PROD_CREATE : 'OWN_PROD_CREATE',
RSV_LIST : 'OWN_RSV_LIST',
SETTLE : 'OWN_SETTLE',
FISH : 'OWN_FISH',
} as const;
export const CANCEL_REASON = {
OVERBOOKING : 'overbooking', // 오버부킹
POOR_CATCH : 'poor_catch', // 물때·조황부진
MIN_PAX : 'min_pax_unmet', // 최소인원 미달
BAD_WEATHER : 'bad_weather', // 기상 악화
MAINTENANCE : 'maintenance', // 정비일
HOLIDAY : 'holiday', // 휴무일
} as const;
값에는 한글을 쓰지 않습니다. GA 검색·필터·BigQuery에서 인코딩이 깨집니다. 화면 표기는 한글, 전송값은 영문 슬러그입니다.
STEP 5. 전송 코드 구현 (1~2일)
5-1. 전송 래퍼 (선행 작업)
파일 하나를 만들고, 앱 전체에서 이것만 호출합니다. gtag() 를 코드 곳곳에서 직접 부르지 않습니다.
// analytics/track.ts
type Params = Record<string, string | number>;
declare global { interface Window { gtag?: (...a: any[]) => void } }
// 모든 이벤트에 자동으로 붙는 값
let common: Params = {
app_version: __BUNDLE_VERSION__, // 웹 번들 배포 버전
entry_from : 'tab',
};
export function setEntryFrom(v: string) { common.entry_from = v; }
export function track(name: string, params: Params = {}) {
try {
window.gtag?.('event', name, { ...common, ...params });
} catch (_) {
// 측정이 실패해도 화면은 절대 멈추면 안 됩니다
}
}
export function screen(screenId: string, params: Params = {}) {
track('page_view', { screen_id: screenId, page_title: screenId, ...params });
}
웹 스트림의 화면 조회 표준 이벤트는screen_view가 아니라page_view입니다. 화면 식별은 URL 대신screen_id파라미터로 합니다. 선주앱은 URL이 화면을 정확히 반영하지 않기 때문입니다.
5-2. 공통 파라미터 3개 — 모든 이벤트에 자동으로
개별 이벤트마다 넣지 않고 위 래퍼 한 곳에서 주입합니다.
| 파라미터 | 값 예시 | 용도 |
|---|---|---|
screen_id | OWN_HOME | 발생 화면 식별 |
entry_from | tab / push / deeplink | 유입 경로 분석 |
app_version | 2.14.0 | 배포 전후 비교 (웹 번들 버전) |
이전 설계의 view_layer(네이티브/웹뷰)는 뺐습니다. 전 화면이 웹뷰라 값이 하나뿐이어서 분석에 쓸 수 없습니다.
5-3. user_id + user_property 3개 — 로그인 직후 한 번만
user_id 설정이 이 구조에서 가장 중요합니다. 쿠키가 초기화돼도 같은 사람으로 이어 붙일 수 있는 유일한 수단입니다.
window.gtag?.('config', 'G-XXXXXXXXXX', {
user_id: hashedMemberId, // ⚠️ 전화번호·이메일 절대 금지, 해시만
send_page_view: false,
});
window.gtag?.('set', 'user_properties', {
af_app_role : 'owner',
owner_ship_count_band : '2_3', // 1 / 2_3 / 4_9 / 10p
owner_tenure_band : 'd8_30', // d0_7 / d8_30 / d31_90 / d90p
});
선박 수를 원시값으로 보내면 값 종류가 많아져 GA가 (other) 로 묶습니다. 구간(밴드)으로 전송합니다.
5-4. 화면 조회 — page_view 하나로
화면별 이벤트를 만들지 않습니다. 이벤트는 page_view 하나이고 screen_id 값만 바꿉니다.
screen(SCREEN.HOME); // 홈 진입
screen(SCREEN.PROD_DAILY); // 상품관리 진입
보내는 곳: 라우트가 바뀌는 화면 진입, 전체화면 모달 안 보내는 곳: 바텀시트·토스트·탭 전환 (단 예약자 명단 시트만 예외 — 체류가 길어 화면으로 취급)
5-5. 이벤트 10개 구현
| # | 이벤트 | 전송 시점 | 파라미터 |
|---|---|---|---|
| 1 | owner_confirm | 예약 확정 완료 토스트가 뜰 때 | count(건수) · pax(인원) · hours_since_payment(결제 후 경과 시간) |
| 2 | owner_cancel | 취소 처리 완료 후 | cancel_reason · count · refund_amount · days_to_departure |
| 3 | owner_product_create | 상품 등록 저장 성공 | create_type(daily/master) · is_first_product(1/0) |
| 4 | owner_close_now | 즉시마감 실행 | fill_rate(0.64 = 64% 찼을 때 마감) |
| 5 | owner_seat_adjust | 남은좌석 저장 | before_seat · after_seat |
| 6 | owner_bulk_edit | 일괄수정 저장 | date_count · changed_fields(seat,close) |
| 7 | owner_manual_add | 예약자 직접 추가 완료 | pax |
| 8 | owner_call_tap | 예약자 번호 탭 | number_type(safe/direct) · is_expired(1/0) |
| 9 | owner_settlement_excel | 정산 엑셀 다운로드 클릭 | month(2026-08) |
| 10 | owner_friction | 비활성 버튼 클릭·유효성 오류·권한 차단·API 오류 | friction_type · element · error_code(선택) |
코드 예시
// 1) 확정 완료
track(EV.CONFIRM, {
screen_id: SCREEN.HOME,
count: 3,
pax: 8,
hours_since_payment: 18.5,
});
// 2) 취소 완료
track(EV.CANCEL, {
screen_id: SCREEN.HOME,
cancel_reason: CANCEL_REASON.BAD_WEATHER,
count: 3,
refund_amount: 396000,
days_to_departure: 2,
});
// 10) 마찰 — 사유 미선택 상태로 [확인]을 눌렀을 때
track(EV.FRICTION, {
screen_id: SCREEN.HOME,
friction_type: 'disabled_click',
element: 'btn_cancel_confirm',
});
owner_friction을 단일 이벤트로 두는 이유: 버튼별 이벤트를 만들면 GA 고유 이벤트 한도(500개)를 빠르게 소진합니다. 하나로 수집하고element파라미터로 구분해도 분석 결과는 동일합니다.
5-6. 금지 사항 4가지
| 금지 | 결과 |
|---|---|
| 이름·전화번호·안심번호·이메일·사업자번호를 파라미터에 넣기 | GA 정책 위반으로 데이터 삭제 대상. user_id 에 전화번호 사용도 금지 |
선주앱에서 purchase / booking_purchase 보내기 | 손님앱 매출과 이중 집계돼 전사 GMV가 오염됩니다 |
| RN 셸에 Firebase SDK를 추가로 붙이기 | 동일 행동이 웹·앱 양쪽에서 잡혀 전환수가 2배가 됩니다 |
| 예약번호·타임스탬프·금액 원단위를 파라미터로 보내기 | 값 종류가 폭발해 리포트가 (other) 로 뭉개집니다 |
STEP 6. 커스텀 정의 등록 (10분)
파라미터는 여기에 등록해야 GA 리포트에서 조회됩니다. 전송이 정상이어도 등록이 없으면 값이 보이지 않으므로 누락되기 쉬운 단계입니다.
관리 → 맞춤 정의 → 맞춤 측정기준 만들기 에서 아래 8개를 등록합니다.
| 표시 이름 | 범위 | 이벤트 매개변수 (철자 일치 필수) |
|---|---|---|
| 선주_화면ID | 이벤트 | screen_id |
| 선주_진입경로 | 이벤트 | entry_from |
| 선주_앱버전 | 이벤트 | app_version |
| 선주_취소사유 | 이벤트 | cancel_reason |
| 선주_마찰유형 | 이벤트 | friction_type |
| 선주_역할 | 사용자 | af_app_role |
| 선주_선박수 | 사용자 | owner_ship_count_band |
| 선주_가입경과 | 사용자 | owner_tenure_band |
이어서 맞춤 측정항목(숫자용) 2개도 추가합니다.
| 표시 이름 | 매개변수 | 측정 단위 |
|---|---|---|
| 선주_환불액 | refund_amount | 통화(KRW) |
| 선주_확정소요시간 | hours_since_payment | 표준 |
⚠️ 범위(Scope)를 정확히 선택합니다. 이벤트에 딸린 값은 "이벤트", 사용자에 딸린 값(역할·선박수)은 "사용자"입니다. 잘못 지정하면 값이 매칭되지 않습니다.
완료 기준: 맞춤 정의 목록에 10개 항목(측정기준 8 + 측정항목 2)이 등록돼 있습니다. 데이터는 등록 후 24시간부터 채워집니다.
STEP 7. 주요 이벤트(전환) 표시하기 (2분)
관리 → 이벤트 목록에서 아래 2개의 주요 이벤트로 표시 토글을 켭니다.
owner_confirm— 선주가 돈을 버는 순간owner_product_create— 신규 선주가 첫 관문을 통과하는 순간
이벤트 목록에 해당 이름이 없으면 아직 수집 이력이 없는 것입니다. 앱에서 1회 발생시킨 뒤 하루 후 다시 확인합니다.
STEP 8. DebugView 검증 (반나절)
디버그 모드 활성화
웹 스트림은 adb 명령이 필요 없습니다. 개발 빌드에서 debug_mode 를 켜기만 하면 됩니다.
gtag('config', 'G-XXXXXXXXXX', {
send_page_view: false,
debug_mode: !IS_PRODUCTION, // ⚠️ 운영 빌드에서는 반드시 false
});
운영 빌드에 debug_mode: true 가 남으면 실사용 데이터가 전부 DebugView로 흘러 리포트가 왜곡됩니다. 배포 전 STEP 14에서 다시 확인합니다.
브라우저에서 웹 번들을 직접 열어 검증해도 됩니다. 다만 웹뷰 설정(3-2) 검증만큼은 실제 앱에서 해야 합니다.
확인 위치
GA4 → 좌측 관리 → DebugView (또는 왼쪽 메뉴 하단 DebugView)
체크리스트 7개 — 전부 통과 후 배포
- [ ] 앱을 켰을 때 이벤트가 실시간으로 흘러 들어온다
- [ ] 아무 이벤트나 하나 클릭했을 때 공통 파라미터 3개(
screen_id·entry_from·app_version)가 다 붙어 있다 - [ ] 화면 이동 시
page_view가 1회만 수집된다 (2회면send_page_view: false누락 또는 향상된 측정 미해제) - [ ] 앱을 완전히 종료했다 재실행했을 때
first_visit가 다시 찍히지 않는다 (찍히면 STEP 3-2 웹뷰 설정 누락) - [ ] 로그인 후 이벤트에
user_id가 붙어 있다 - [ ] 취소 실행 시
cancel_reason이 영문 슬러그(bad_weather)로 전송된다 - [ ] 어떤 파라미터에도 이름·전화번호·안심번호가 없고,
purchase가 발생하지 않는다
STEP 9. 배포 후 확인 (D+2)
- 실시간 리포트: 보고서 → 실시간 → 이벤트 이름에
owner_들이 보이는가 - 탐색 분석: 탐색 → 빈 탐색 → 측정기준에
선주_화면ID추가 → 값이 채워지는가 ((not set)이면 STEP 6 등록 누락) (other)행이 생겼는가 — 생겼다면 값 종류가 너무 많은 파라미터가 있다는 뜻. 그 값을 구간으로 바꿔야 합니다- 사용자 수가 실제 선주 수와 자릿수가 맞는가 — 실제의 5배 이상이면 STEP 3-2 웹뷰 쿠키 설정을 다시 확인합니다
STEP 10. 탐색 리포트 생성 (30분)
GA4 기본 보고서는 마케팅 지표 중심이라 선주앱에는 맞지 않습니다. 탐색(Exploration) 에서 아래 5개를 생성해 재사용합니다.
만드는 곳: 좌측 메뉴 탐색 → 빈 탐색 만들기. 왼쪽에세그먼트 / 측정기준 / 측정항목을 추가한 뒤, 가운데탭 설정으로 끌어다 놓는 구조입니다.
리포트 ① 확정 리드타임 — "선주가 얼마나 빨리 확정하는가"
- 기법: 자유 형식
- 행:
선주_선박수(user_property) - 값:
선주_확정소요시간평균 +이벤트 수 - 필터:
이벤트 이름=owner_confirm - 해석: 평균보다 중앙값 감각이 중요합니다. 값이 24를 넘으면 "선주가 하루 넘게 방치하고 있다"는 뜻입니다.
리포트 ② 취소 손실 — "어떤 이유로 돈이 새는가"
- 기법: 자유 형식
- 행:
선주_취소사유 - 값:
이벤트 수,선주_환불액합계 - 필터:
이벤트 이름=owner_cancel - 해석: 건수 1위와 금액 1위가 다를 수 있습니다. 금액 1위부터 잡습니다.
리포트 ③ 온보딩 퍼널 — "신규 선주가 첫 매출까지 오는가"
- 기법: 유입경로 탐색(Funnel)
- 단계: ①
page_view(선주_화면ID=OWN_PROD_CREATE) → ②owner_product_create→ ③owner_confirm - 세그먼트:
선주_가입경과=d0_7 - 해석: 어느 단계에서 절반 이상 빠지는지만 봅니다. 1→2 이탈이면 등록 폼 문제, 2→3 이탈이면 예약이 아예 안 들어온 것(마케팅·노출 문제)입니다.
리포트 ④ 마찰 히트맵 — "어디서 막히는가"
- 기법: 자유 형식
- 행:
선주_화면ID/ 열:선주_마찰유형 - 값:
이벤트 수 - 필터:
이벤트 이름=owner_friction - 해석: 셀 하나가 유독 크면 그 화면의 그 유형이 병목입니다. 개선 티켓은 여기서 나옵니다.
리포트 ⑤ 배포 전후 비교 — "이번 배포가 좋아진 건가"
- 기법: 자유 형식
- 행:
선주_앱버전/ 열:선주_마찰유형 - 값:
사용자당 이벤트 수(총 건수가 아니라 사용자당으로 봐야 트래픽 증감에 속지 않습니다) - 필터:
이벤트 이름=owner_friction - 해석: 새 버전에서 특정 마찰이 늘었으면 그 배포가 원인입니다. 웹 번들은 즉시 롤백이 가능하므로 당일 판단할 수 있습니다. 이 리포트가 풀웹뷰 구조의 가장 큰 이점입니다.
생성한 탐색은 우상단에서 공유합니다. 각자 만들면 지표 정의가 달라져 회의에서 수치가 어긋납니다.
11. 무엇을 보고 무엇을 고치는가
지표와 개선 액션을 연결한 표입니다. 수치 이상 시 의심 항목과 개선 후보를 사전에 정의해 둡니다.
| 볼 숫자 | 어디서 | 나쁘다는 신호 | 의심할 것 | 개선 후보 |
|---|---|---|---|---|
| 확정 리드타임 | 리포트 ① | 24시간 초과 비중이 큼 | 선주가 알림을 못 보거나, 확정을 미룸 | 푸시 재알림, 홈 상단 강조, 결제일시 표기(이번 8/18 반영분)로 방치 인지 |
| 확정 건수 대비 마찰 | ①+④ | OWN_HOME 의 disabled_click 급증 | 확정 버튼 활성 조건이 헷갈림 | 버튼 상태·안내 문구 재설계 |
| 취소 손실액 | 리포트 ② | 특정 사유가 금액 과반 | 사유별로 원인이 다름 | overbooking 이면 좌석 동기화 버그, min_pax_unmet 이면 최소인원 정책·모객 지원, poor_catch 면 상품 편성 |
| 취소 리드타임 | ②의 days_to_departure | 0~1일에 몰림 | 임박 취소 = 손님 피해 큼 | 조기 취소 유도(사전 인원 체크 알림) |
| 온보딩 통과율 | 리포트 ③ | 1→2 단계에서 50% 이상 이탈 | 상품 등록이 어렵다 | 등록 폼 단순화, 첫 상품 온보딩 코치마크 |
| 소진율 | owner_close_now 의 fill_rate | 0.5 미만에서 마감이 잦음 | 빈 배로 출항 중 | 잔여석 프로모션, 마감 전 알림 |
| 기능 채택 | owner_bulk_edit·owner_seat_adjust 사용 선주 비율 | 10% 미만 | 기능을 모르거나 어렵다 | 사용법 영상 진입 개선, 진입 동선 노출 |
| 전화 연결 | owner_call_tap 의 is_expired=1 비율 | 만료 비중이 큼 | 안심번호 만료 기준이 짧다 | 만료 기간 재검토(현재 [미확인]), 만료 표기 개선 |
| 정산 이탈 | owner_settlement_excel 빈도 | 조회 대비 다운로드가 매우 높음 | 앱 안에서 정산을 못 끝냄 | 정산 화면에 필요한 항목 보강 |
| 배포 후 악화 | 리포트 ⑤ | 신버전의 사용자당 마찰이 구버전보다 큼 | 이번 배포가 원인 | 웹 번들 롤백 후 해당 화면 재검토 |
개선건 도출 절차
- 월 1회, 리포트 ④ 마찰 히트맵에서 상위 5칸을 뽑는다
- 각 칸을 "화면 + 마찰 유형 + 건수" 로 티켓 제목을 만든다 — 예:
[OWN_HOME] 비활성 클릭 320건 — 확정 버튼 조건 불명확 - 리포트 ①②③ 중 돈에 직결된 지표 1개와 묶어 우선순위를 매긴다. 마찰 건수만으로 정하면 사소한 것부터 고치게 됩니다
12. 운영 루틴
| 주기 | 시간 | 보는 것 | 산출물 |
|---|---|---|---|
| 주 1회 | 15분 | 확정 리드타임(①) · 취소 손실 상위 사유(②) · 마찰 상위 3칸(④) | 이상치가 있으면 슬랙 공유 |
| 월 1회 | 1시간 | 리포트 ①~⑤ 전부 + 전월 대비 | 개선 티켓 3~5건 발행 |
| 배포 직후 D+2 | 20분 | 새 이벤트가 들어오는지 · (other) 발생 여부 · 리포트 ⑤ 버전 비교 | 태깅 이상 시 즉시 수정 |
| 분기 1회 | 30분 | 12장 "지금은 안 하는 것" 목록 재검토 | 필요한 이벤트만 추가(분기 10개 이내) |
첫 4주는 기준선 수집 기간으로 둡니다. 비교 대상이 없으면 지표의 좋고 나쁨을 판단할 수 없으므로, 4주치가 쌓인 뒤 개선 티켓을 발행합니다.
13. 트러블슈팅
| 증상 | 원인 | 조치 |
|---|---|---|
| DebugView에 아무것도 안 뜬다 | debug_mode 미적용 / 측정 ID 오타 | gtag('config') 의 측정 ID와 debug_mode: true 확인 |
| 이벤트는 보이는데 파라미터가 안 보인다 | 커스텀 정의 미등록 | STEP 6. 등록 후 24시간 필요 |
| 리포트가 텅 비어 있다 | GA4 리포트는 24~48시간 지연 | 개발 중엔 DebugView로만 확인 |
값이 (not set) 으로 나온다 | 파라미터 철자 불일치 | 코드의 철자와 커스텀 정의의 철자를 글자 단위로 대조 |
| 화면 조회가 두 배다 | send_page_view 미설정 | gtag('config') 에 send_page_view: false 추가, 향상된 측정 OFF 확인 |
| 사용자 수가 실제의 몇 배다 | 웹뷰가 쿠키·스토리지를 못 지킴 | STEP 3-2의 RN WebView 옵션 4개 확인. incognito={true} 가 가장 흔한 원인 |
| 재방문 사용자가 0에 가깝다 | 위와 동일 | 앱 재실행 시 first_visit 가 다시 찍히는지 DebugView에서 확인 |
| 로그인해도 사용자가 안 이어진다 | user_id 미설정 | STEP 5-3. 로그인 성공 직후 config 재호출 |
(other) 행이 생겼다 | 파라미터 값 종류 과다 | 원시 ID·금액·타임스탬프를 파라미터에서 빼고 구간으로 |
| 손님앱 매출이 갑자기 늘었다 | 선주앱이 purchase 를 보냄 | 즉시 제거. 이미 들어간 데이터는 되돌릴 수 없음 |
14. 배포 전 최종 체크리스트
- [ ] STEP 1 — 선주앱 전용 웹 스트림 생성 (손님앱 스트림 아님) · 측정 ID 확보
- [ ] STEP 2 — 보관 14개월 · Google 신호 OFF · 향상된 측정 전부 OFF
- [ ] STEP 3 — gtag 삽입(
send_page_view: false) · RN WebView 옵션 4개 확인 - [ ] STEP 4 — 이벤트명·화면ID·취소사유 전부 상수 파일에
- [ ] STEP 5 — 전송 래퍼 · 공통 파라미터 3개 ·
user_id· user_property 3개 ·page_view7개 · 이벤트 10개 - [ ] STEP 6 — 맞춤 측정기준 8개 + 측정항목 2개 등록
- [ ] STEP 7 — 주요 이벤트 2개 표시
- [ ] STEP 8 — DebugView 체크리스트 7개 전부 통과
- [ ] 운영 빌드에
debug_mode: true가 남아 있지 않은가 - [ ] STEP 9 — D+2 확인 일정 잡아두기
- [ ] STEP 10 — 탐색 리포트 5개 생성·공유
15. 이번 범위에서 제외한 항목
아래는 이번 범위에서 의도적으로 제외했습니다.
| 뺀 것 | 다시 넣을 조건 |
|---|---|
| 확정/취소 시작·중단 이벤트 | 확정 전환율이 낮게 나와 원인을 파야 할 때 |
| 조황·공지 관련 이벤트 | page_view 만으로 판단이 안 될 때 |
| 선박ID·업체ID·권한·요금제 | 다척 선주 전용 기능을 만들 때 |
| 화면 폭(320/344/360) 세그먼트 | 폭 관련 이탈이 의심될 때 |
| 첫 예약 수신 | 선주앱 액션이 아니라 클라이언트에서 측정 불가 → 서버에서 Measurement Protocol 로 보내야 함 (백엔드 협의 필요) |
| 푸시 발송·오픈 성과 | 푸시 성과를 GA에서 봐야 할 때. RN 셸에 Firebase SDK 추가 + 앱 스토어 배포가 필요합니다. 그전까지는 딥링크 UTM으로 유입만 봅니다 |
| 앱 설치·삭제·스토어 획득 | 위와 동일 (SDK 필요) |
부록. 용어 정리
- 속성(Property) — 데이터가 쌓이는 통. 우리는
aboutfishing-product하나를 씁니다 - 스트림(Stream) — 통에 붓는 파이프. 앱·웹마다 하나
- 이벤트(Event) — "무슨 일이 있었다" 기록. 이름은 한 번 쓰면 못 지웁니다
- 파라미터(Parameter) — 이벤트에 딸린 상세값
- user_property — 사람에게 붙는 값(역할·선박수). 한 번 설정하면 이후 모든 이벤트에 따라붙습니다
- 맞춤 정의(커스텀 정의) — 파라미터를 리포트에서 조회 가능하게 등록하는 절차
- 주요 이벤트(전환) — 특별히 중요하다고 표시한 이벤트
- DebugView — 실시간 검증 화면. 개발 단계 검증은 여기서 진행
- 측정 ID — 웹 스트림 식별자
G-XXXXXXXXXX. gtag 설정에 넣는 값 send_page_view— gtag가 화면 조회를 자동 전송할지 여부. 우리는 직접 보내므로false(not set)— 값이 안 왔거나 등록이 안 된 상태(other)— 값 종류가 너무 많아 GA가 뭉갠 것
관련 문서
- 기획서(Figma): 파일
KyXXpLN19n1oytwYWHImJq/ 페이지 「클로드 선주 모바일」 - 확정 디자인: 취소 모달
20575:30196·20575:30296/ 홈 결제일시20375:721