Skip to content

Commit 68fbac9

Browse files
authored
Merge pull request #1358 from Moadong/feature/#1354-mixpanel-experiment-hook-MOA-763
[feature] AB테스트를 위한 실험 구조 구축
2 parents 709cbf3 + fef5a9b commit 68fbac9

17 files changed

+974
-3
lines changed

.gitignore

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,5 @@
55

66
.env
77

8-
CLAUDE.md
9-
.claude
10-
118
dailyNote/
129

docs/experiments.md

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
# 프론트엔드 실험(A/B Test) 시스템 가이드
2+
3+
## 개요
4+
5+
`frontend/src/experiments/`는 클라이언트 사이드 A/B 실험을 위한 경량 구조다.
6+
외부 서비스 없이 localStorage 기반으로 배리언트를 배정하고, React 훅으로 컴포넌트에서 간편하게 사용할 수 있다.
7+
8+
## 파일 구성
9+
10+
```
11+
frontend/src/experiments/
12+
├── types.ts # 실험 관련 타입 정의
13+
├── definitions.ts # 실험 목록 정의 (여기만 수정하면 됨)
14+
├── ExperimentRepository.ts # 배리언트 배정 및 조회 로직
15+
└── initializeExperiments.ts # 앱 시작 시 일괄 배정
16+
17+
frontend/src/hooks/Experiment/
18+
└── useExperimentVariant.ts # 컴포넌트에서 사용하는 React 훅
19+
```
20+
21+
## 동작 원리
22+
23+
1. **앱 시작 시** `initializeExperiments()``ALL_EXPERIMENTS`를 순회하며 각 실험의 배리언트를 배정한다.
24+
2. 이미 배정된 실험은 재배정하지 않는다. (같은 유저는 항상 같은 배리언트를 본다)
25+
3. 배정 결과는 `localStorage``moadong_experiments` 키에 JSON으로 저장된다.
26+
4. 컴포넌트에서는 `useExperimentVariant` 훅으로 배리언트를 읽어 분기한다.
27+
28+
## 새 실험 추가 방법 (3단계)
29+
30+
### 1단계 — `definitions.ts`에 실험 정의 추가
31+
32+
```typescript
33+
// frontend/src/experiments/definitions.ts
34+
35+
export const myNewExperiment = {
36+
key: "my_new_experiment_v1", // 전역 고유값. 중복 금지
37+
variants: ["A", "B"] as const,
38+
defaultVariant: "A", // 배정 실패 또는 초기화 시 기본값
39+
weights: {
40+
A: 50,
41+
B: 50,
42+
},
43+
} satisfies ExperimentDefinition<"A" | "B">;
44+
45+
// ALL_EXPERIMENTS 배열에도 추가
46+
export const ALL_EXPERIMENTS = [
47+
mainBannerExperiment,
48+
applyButtonCopyExperiment,
49+
myNewExperiment, // ← 여기
50+
] as const;
51+
```
52+
53+
### 2단계 — 컴포넌트에서 배리언트 분기
54+
55+
```typescript
56+
import { useExperimentVariant } from '@/hooks/Experiment/useExperimentVariant';
57+
import { myNewExperiment } from '@/experiments/definitions';
58+
59+
const MyComponent = () => {
60+
const variant = useExperimentVariant(myNewExperiment);
61+
62+
return variant === 'B' ? <NewVersion /> : <DefaultVersion />;
63+
};
64+
```
65+
66+
### 3단계 — Mixpanel 이벤트에 배리언트 속성 포함 (권장)
67+
68+
실험 결과를 분석하려면 이벤트 전송 시 배리언트 값을 속성으로 넘겨야 한다.
69+
70+
```typescript
71+
import { trackEvent } from "@/utils/mixpanel"; // 실제 트래킹 유틸 경로 참고
72+
73+
trackEvent("클릭 이벤트", {
74+
experiment_key: myNewExperiment.key,
75+
experiment_variant: variant,
76+
});
77+
```
78+
79+
## weights(가중치) 설정
80+
81+
`weights`를 생략하면 균등 배분된다.
82+
비율을 조정하고 싶을 때만 명시한다.
83+
84+
```typescript
85+
// 10%만 B를 보는 실험
86+
weights: {
87+
A: 90,
88+
B: 10,
89+
},
90+
```
91+
92+
## 배리언트 초기화 (개발/QA용)
93+
94+
브라우저 콘솔에서 실행하면 배정이 초기화된다.
95+
96+
```javascript
97+
localStorage.removeItem("moadong_experiments");
98+
location.reload();
99+
```
100+
101+
또는 코드에서 직접 호출:
102+
103+
```typescript
104+
import { experimentRepository } from "@/experiments/ExperimentRepository";
105+
experimentRepository.resetAssignments();
106+
```
107+
108+
## key 네이밍 규칙
109+
110+
- 형식: `{실험_대상}_{버전}` (소문자 snake_case)
111+
- 예시: `main_banner_v1`, `apply_button_copy_v1`
112+
- 실험이 종료되고 새로 시작할 때는 버전을 올린다: `main_banner_v2`
113+
- 이미 배포된 key는 절대 재사용하지 않는다. (기존 유저 배정 오염 방지)
114+
115+
## 실험 종료 후 정리
116+
117+
1. `definitions.ts`에서 해당 실험 상수와 `ALL_EXPERIMENTS` 항목을 제거한다.
118+
2. 채택된 배리언트 코드만 남기고 분기 로직을 제거한다.
119+
3. 버려진 배리언트 코드를 삭제한다.
120+
121+
## 현재 운영 중인 실험
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
# Mixpanel MCP 관리자 주간 리포트 고정 프롬프트 세트
2+
3+
## 목적
4+
5+
- 관리자(Admin) 사용 흐름을 주 단위로 모니터링한다.
6+
- 설정/수정 관련 행동 데이터를 표준 템플릿으로 축적한다.
7+
8+
## 운영 원칙
9+
10+
- 기간은 항상 `지난주 (월요일 00:00 ~ 일요일 23:59, KST)`로 고정한다.
11+
- 비교 기준은 항상 `직전 주`로 고정한다.
12+
- 관리자 이벤트에는 "클릭" 위주 이벤트가 많으므로, 저장 성공/실패는 별도 백엔드 로그와 함께 해석한다.
13+
- 결과는 아래 "리포트 템플릿" 순서로 정리한다.
14+
15+
## 고정 프롬프트 8개 (moadong ADMIN_EVENT 치환)
16+
17+
1. `지난주(월~일, Asia/Seoul) 관리자 핵심 KPI를 보여줘. 다음 이벤트를 기준으로 유저 수와 이벤트 수를 각각 보여줘: "로그인페이지 Visited", "로그인 버튼클릭", "사이드바 탭 클릭", "동아리 기본 정보 수정 버튼클릭", "동아리 모집 정보 수정 버튼클릭", "활동 사진 업로드 버튼클릭", "비밀번호 변경 버튼클릭". 직전 주 대비 증감률(%) 포함.`
18+
19+
2. `지난주 관리자 진입 퍼널을 보여줘: "로그인페이지 Visited" -> "로그인 버튼클릭" -> "동아리 기본 정보 수정 페이지 Visited"(또는 다른 관리자 탭 Visited). 단계별 전환율/이탈률과 직전 주 대비 변화를 계산해줘.`
20+
21+
3. `지난주 사이드바 탭 이동 패턴을 분석해줘. "사이드바 탭 클릭" 이벤트의 tab_name 속성 기준으로 탭별 클릭 수, 유저 수, 전주 대비 증감을 표로 보여줘.`
22+
23+
4. `지난주 동아리 기본 정보 수정 관련 행동을 요약해줘: "동아리 기본 정보 수정 버튼클릭", "분류/분과/자유태그 선택 버튼클릭", "자유태그 입력 초기화 버튼클릭", "SNS 링크 입력 초기화 버튼클릭". 이벤트별 유저 수/이벤트 수와 전주 대비 변화 포함.`
24+
25+
5. `지난주 모집 정보 수정 관련 행동을 요약해줘: "동아리 모집 정보 수정 버튼클릭", "상시모집 버튼클릭", "모집 시작 날짜 변경", "모집 종료 날짜 변경", "모집 대상 입력 초기화 버튼클릭", "소개글 미리보기/편집 버튼클릭". 이벤트별 추세와 함께 보여줘.`
26+
27+
6. `지난주 이미지 자산 편집 행동을 비교해줘: "동아리 커버 업로드 버튼클릭", "동아리 커버 초기화 버튼클릭", "동아리 로고 업로드 버튼클릭", "동아리 로고 초기화 버튼클릭", "활동 사진 업로드 버튼클릭", "활동 사진 삭제 버튼클릭". 업로드/초기화/삭제 비율도 계산해줘.`
28+
29+
7. `지난주 계정 보안 관련 행동을 보여줘: "비밀번호 변경 버튼클릭", "새 비밀번호 입력 초기화 버튼클릭", "확인 비밀번호 입력 초기화 버튼클릭". 전주 대비 증감과 이상 패턴(초기화 클릭 과다 등)을 코멘트해줘.`
30+
31+
8. `위 1~7 결과를 바탕으로 이번 주 관리자 UX 개선 액션 3개를 제안해줘. 각 액션마다 목표 KPI, 기대효과, 검증방법(A/B 또는 관찰지표), 우선순위를 포함해줘.`
32+
33+
## 리포트 템플릿 (복붙용)
34+
35+
```md
36+
# 관리자 주간 리포트 (YYYY-W##)
37+
38+
## 1) 한 줄 요약
39+
40+
-
41+
42+
## 2) KPI 스냅샷 (지난주 vs 직전 주)
43+
44+
- 로그인페이지 Visited (users/events):
45+
- 로그인 버튼클릭 (users/events):
46+
- 사이드바 탭 클릭 (users/events):
47+
- 동아리 기본 정보 수정 버튼클릭 (users/events):
48+
- 동아리 모집 정보 수정 버튼클릭 (users/events):
49+
- 활동 사진 업로드 버튼클릭 (users/events):
50+
- 비밀번호 변경 버튼클릭 (users/events):
51+
52+
## 3) 핵심 변화 3가지
53+
54+
1.
55+
2.
56+
3.
57+
58+
## 4) 원인 가설
59+
60+
-
61+
62+
## 5) 이번 주 액션 3개
63+
64+
1. 액션:
65+
목표 KPI:
66+
기대효과:
67+
검증방법:
68+
우선순위:
69+
2. 액션:
70+
목표 KPI:
71+
기대효과:
72+
검증방법:
73+
우선순위:
74+
3. 액션:
75+
목표 KPI:
76+
기대효과:
77+
검증방법:
78+
우선순위:
79+
80+
## 6) 리스크 / 확인 필요
81+
82+
-
83+
```
84+
85+
## 커스터마이즈 체크리스트
86+
87+
- 실제 운영 탭 이름 확인: `사이드바 탭 클릭``tab_name` 속성 값
88+
- 수정 성공 지표 보강 여부 결정: 클릭 이벤트 외 백엔드 성공 로그 연동
89+
- 관리자 계정 식별 기준 확정 (distinct_id 또는 사용자 속성)
90+
- 페이지 체류 지표 활용 여부 결정 (`로그인페이지 Duration`, `동아리 기본 정보 수정 페이지 Duration` 등)
91+
92+
## 실행 순서 권장
93+
94+
1. 프롬프트 1~7 실행 후 사실 데이터 확정
95+
2. 프롬프트 8 실행으로 액션 도출
96+
3. 템플릿에 결과 이관 후 팀 공유

docs/mixpanel-reporting.md

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# Mixpanel 리포팅 문서 인덱스
2+
3+
## 개요
4+
5+
moadong에서 Mixpanel MCP로 주간 리포트를 만들 때 사용하는 문서 모음이다.
6+
7+
## 문서 바로가기
8+
9+
- 사용자(학생) 흐름 리포트: [mixpanel-weekly-report-prompts.md](./mixpanel-weekly-report-prompts.md)
10+
- 관리자(Admin) 흐름 리포트: [mixpanel-admin-weekly-report-prompts.md](./mixpanel-admin-weekly-report-prompts.md)
11+
12+
## 최근 주간 리포트
13+
14+
- 2026-W12 사용자 리포트: [2026-W12-user-mixpanel-report.md](./weekly-reports/2026-W12-user-mixpanel-report.md)
15+
16+
## 주간 실행 순서
17+
18+
1. Mixpanel MCP 연결 상태 확인
19+
- `codex mcp list`
20+
2. 사용자 리포트 실행
21+
- `docs/mixpanel-weekly-report-prompts.md`의 고정 프롬프트 1~8 순서대로 실행
22+
3. 관리자 리포트 실행
23+
- `docs/mixpanel-admin-weekly-report-prompts.md`의 고정 프롬프트 1~8 순서대로 실행
24+
4. 각 템플릿에 결과 이관 후 팀 공유
25+
26+
## 운영 규칙
27+
28+
- 기간 기준 고정: `지난주 (월요일 00:00 ~ 일요일 23:59, KST)`
29+
- 비교 기준 고정: `직전 주`
30+
- 이벤트 누락/속성 불일치 시 추정하지 않고 리스크로 명시
31+
32+
## 업데이트 규칙
33+
34+
- 신규 이벤트 추가 시, 먼저 `frontend/src/constants/eventName.ts`를 기준으로 이벤트명을 확인한다.
35+
- 이벤트/속성 변경 시 사용자 문서와 관리자 문서를 함께 갱신한다.
36+
- 퍼널 정의가 바뀌면 템플릿 KPI 항목도 함께 수정한다.
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
# Mixpanel MCP 주간 리포트 고정 프롬프트 세트
2+
3+
## 목적
4+
5+
- 매주 같은 기준으로 KPI를 조회하고, 비교와 해석을 일관되게 남긴다.
6+
- 리포트 품질을 사람 숙련도에 의존하지 않고 템플릿으로 표준화한다.
7+
8+
## 운영 원칙
9+
10+
- 기간은 항상 `지난주 (월요일 00:00 ~ 일요일 23:59, KST)`로 고정한다.
11+
- 비교 기준은 항상 `직전 주`로 고정한다.
12+
- 지표가 비어 있거나 이벤트명이 불일치하면, 추정하지 말고 누락 항목으로 명시한다.
13+
- 결과는 아래 "리포트 템플릿" 순서로 정리한다.
14+
15+
## 고정 프롬프트 8개 (moadong 이벤트명 1차 치환)
16+
17+
1. `지난주(월~일, Asia/Seoul) 핵심 KPI를 보여줘. 이벤트는 정확히 다음 기준으로 집계해줘: "MainPage Visited"(유저 수), "ClubDetailPage Visited"(유저 수), "ApplicationFormPage Visited"(유저 수), "Application Form Submitted"(이벤트 수/유저 수). 직전 주 대비 증감률(%)도 포함해줘.`
18+
19+
2. `지난주(월~일, Asia/Seoul) 지원 퍼널 전환율을 보여줘: "MainPage Visited" -> "ClubCard Clicked" -> "ClubDetailPage Visited" -> "Club Apply Button Clicked" -> "ApplicationFormPage Visited" -> "Application Form Submitted". 각 단계 전환율/이탈률과 직전 주 대비 변화를 함께 보여줘.`
20+
21+
3. `지난주 "ClubCard Clicked" 사용자 cohort 기준 D1, D7 재방문율을 보여줘. 재방문 기준 이벤트는 "MainPage Visited"로 계산하고, 최근 4주 추세를 표로 정리해줘.`
22+
23+
4. `지난주 유입 채널 성과를 비교해줘. "MainPage Visited"의 referrer 속성 기준으로 채널을 나누고, 각 채널별 "ClubCard Clicked", "Club Apply Button Clicked", "Application Form Submitted" 전환율을 계산해줘.`
24+
25+
5. `지난주 디바이스/플랫폼별 성과를 비교해줘. Mixpanel 기본 디바이스 속성($os, $browser)을 사용해서 "MainPage Visited" -> "Application Form Submitted" 전환율을 iOS/Android/Web 기준으로 정리해줘.`
26+
27+
6. `직전 주 대비 "Application Form Submitted" 변화 원인을 이벤트 기여도로 분해해줘. 후보 이벤트는 "MainPage Visited", "ClubCard Clicked", "Club Apply Button Clicked", "ApplicationFormPage Visited"로 제한하고 증가/감소 기여 Top 5를 해석해줘.`
28+
29+
7. `지난주 이탈 구간을 진단해줘. "Club Apply Button Clicked" 대비 "ApplicationFormPage Visited", "ApplicationFormPage Visited" 대비 "Application Form Submitted" 전환율을 클럽별(club_id 또는 club_name 속성)로 비교해서 하위 10개를 보여줘.`
30+
31+
8. `위 1~7 결과를 기반으로 이번 주 실행 액션 3개를 제안해줘. 각 액션마다 목표 KPI(예: "Application Form Submitted" 유저 수), 기대효과, 검증방법(A/B 또는 관찰지표), 우선순위를 포함해줘.`
32+
33+
## 리포트 템플릿 (복붙용)
34+
35+
```md
36+
# 주간 리포트 (YYYY-W##)
37+
38+
## 1) 한 줄 요약
39+
40+
-
41+
42+
## 2) KPI 스냅샷 (지난주 vs 직전 주)
43+
44+
- MainPage Visited (users):
45+
- ClubDetailPage Visited (users):
46+
- ApplicationFormPage Visited (users):
47+
- Application Form Submitted (events/users):
48+
- D1/D7 재방문율 (ClubCard Clicked cohort):
49+
50+
## 3) 핵심 변화 3가지
51+
52+
1.
53+
2.
54+
3.
55+
56+
## 4) 원인 가설
57+
58+
-
59+
60+
## 5) 이번 주 액션 3개
61+
62+
1. 액션:
63+
목표 KPI:
64+
기대효과:
65+
검증방법:
66+
우선순위:
67+
2. 액션:
68+
목표 KPI:
69+
기대효과:
70+
검증방법:
71+
우선순위:
72+
3. 액션:
73+
목표 KPI:
74+
기대효과:
75+
검증방법:
76+
우선순위:
77+
78+
## 6) 리스크 / 확인 필요
79+
80+
-
81+
```
82+
83+
## 커스터마이즈 체크리스트
84+
85+
- 사용자 핵심 이벤트 확정: `MainPage Visited`, `ClubCard Clicked`, `ClubDetailPage Visited`, `Club Apply Button Clicked`, `ApplicationFormPage Visited`, `Application Form Submitted`
86+
- KPI 정의를 팀 문서와 일치시킴 (예: 제출 KPI를 이벤트 수로 볼지 유저 수로 볼지)
87+
- 채널 분류 기준 확정 (`referrer` 우선, 필요 시 UTM 속성 추가 수집)
88+
- 플랫폼 구분 기준 확정 (`$os`, `$browser` 사용 여부)
89+
- 관리자 리포트를 별도로 운영할지 결정 (`로그인 버튼클릭`, `동아리 모집 정보 수정 버튼클릭` 등 ADMIN_EVENT 기반)
90+
91+
## 실행 순서 권장
92+
93+
1. 프롬프트 1~7 실행 후 사실 데이터 확정
94+
2. 프롬프트 8 실행으로 액션 도출
95+
3. 템플릿에 결과 이관 후 팀 공유

0 commit comments

Comments
 (0)