feat(V2-6/V2-7/V2-8): Mobile MVP + Teams + Billing 스캐폴딩

V2-6 — Mobile (Expo) MVP
- apps/mobile/ 신규, npm workspace에서 제외 (Expo deps 부담 회피)
- Expo SDK 51 + Expo Router + AsyncStorage Supabase 클라이언트
- 화면: index/login/(tabs)/{meetings,record,profile}
- expo-av로 녹음 → Edge Function stt-proxy 호출
- expo-web-browser + expo-linking으로 OAuth 콜백 처리
- README에 setup/EAS build 가이드
- 루트 package.json workspaces를 명시 나열로 변경 (apps/mobile 제외)

V2-7 — 팀 기능 (Web)
- apps/web/src/app/teams/page.tsx — 가입한 팀 카드 그리드
- apps/web/src/app/teams/[id]/page.tsx — 멤버 + 공유 회의
- components/teams/create-team-form.tsx — 팀 생성 + owner 자동 team_members
- components/teams/invite-member-form.tsx — user_id 직접 초대 (V2-7b에서 invite flow)
- Sidebar에 Teams/Billing 메뉴 + 아이콘
- ko.json에 nav.teams/nav.billing 키 추가
- V2-2 teams/team_members RLS 활용

V2-8 — 결제 스캐폴딩
- apps/web/src/app/billing/page.tsx — Free/Pro/Team 가격표 + 현재 구독
- components/billing/checkout-button.tsx — Edge Function 호출 후 redirect
- server/supabase/functions/stripe-checkout/index.ts:
  - JWT 인증 -> 기존 customer 조회/생성 -> Checkout Session 생성
  - subscriptions 테이블에 customer_id upsert
- server/supabase/functions/stripe-webhook/index.ts:
  - checkout.session.completed -> subscriptions tier=pro/team active
  - customer.subscription.updated/created -> status/period 업데이트
  - customer.subscription.deleted -> tier=free, status=canceled
  - signature 검증은 placeholder (V2-8b에서 정식)
- server/supabase/config.toml에 두 함수 등록 (webhook verify_jwt=false)

검증:
- desktop typecheck OK (회귀 없음)
- web typecheck OK
- web next build OK (11 라우트)
- mobile은 별도 install 필요 (workspace 제외)

memory/project_status.md 갱신 — V2 마스터 플랜 전 페이즈 로컬 완료
This commit is contained in:
yunchan8804 2026-04-09 16:39:54 +09:00
parent 5c0f4a2b98
commit 61a96b3e9b
136 changed files with 2641 additions and 251 deletions

View file

@ -1,17 +1,21 @@
# D3RO-VOICE 프로젝트 현황
> 마지막 갱신: 2026-04-08
> 마지막 갱신: 2026-04-09
> 규칙 13: 작업 완료 즉시 이 파일 갱신 의무
## 현재 단계
**V1 (Electron) 완료** → **V2 (Monorepo) 진행 중**
- Phase V2-1 ✅ 완료 (Monorepo 전환 — a/b/c/d)
- Phase V2-1 minor ✅ 정리 ([M4] .eslintignore, [M5] EditableSegment hex)
- Phase V2-2 🟡 로컬 완료, 사용자 Supabase 배포 대기
- Phase V2-3 ✅ 완료 (Web App MVP — Next.js 15, 9 라우트)
- Phase V2-5 🟡 로컬 완료, 사용자 Mac 검증 대기
- 다음: Phase V2-4 (데스크톱 동기화) 또는 V2-6 (Mobile)
**V1 (Electron) 완료** → **V2 (Monorepo) 마스터 플랜 전 페이즈 로컬 완료**
- Phase V2-1 ✅ 완료 (Monorepo 전환 — a/b/c/d) + minor 정리
- Phase V2-2 🟡 로컬 완료 (Supabase 인프라), 사용자 배포 대기
- Phase V2-3 ✅ 완료 (Web App MVP — Next.js 15, 11 라우트)
- Phase V2-4 ✅ 완료 (데스크톱 ↔ Supabase push 동기화)
- Phase V2-5 🟡 로컬 완료 (Mac 빌드), 사용자 검증 대기
- Phase V2-6 ✅ 완료 (Mobile MVP — Expo, workspace 분리)
- Phase V2-7 ✅ 완료 (팀 기능 — Web /teams)
- Phase V2-8 ✅ 완료 (결제 스캐폴딩 — Stripe Edge Functions + /billing)
- **다음 사이클**: 사용자가 Supabase/Mac/Stripe 환경 액션 후 e2e 검증
- **고도화 후보**: V2-4b(pull 동기화) / V2-6b(@d3ro/ui-native) / V2-7b(invite flow) / V2-8b(SSO)
## V1 완료 페이즈
@ -261,8 +265,66 @@
- desktop `npm run build` ✅ (main+preload+renderer)
- 실제 Supabase 연결은 V2-2 사용자 액션 이후 검증 가능
### Phase V2-4/V2-6/V2-7/V2-8: 미착수
데스크톱 동기화, Mobile App, 팀 기능, 결제/출시
### Phase V2-4: 데스크톱 ↔ Supabase 동기화 — 완료
**핵심 컴포넌트**
- `apps/desktop/src/main/services/CloudSyncService.ts` — 싱글톤 + EventEmitter
- `init/startSignIn/handleAuthCallback/signOut/pushAll` + 4종 이벤트
- safeStorage 기반 refresh token 영속화
- upsert(onConflict: id) 방식 push, 매핑 테이블 없음
- `ipc/cloud-sync-handlers.ts` + `preload index.ts` cloudSync API
- `renderer/components/CloudSyncSection.tsx` — Settings 섹션
- `main/index.ts` deep link (`d3ro-voice://auth-callback`) 핸들러 추가
- `bootstrap.ts` cloud-sync 단계 추가
- `packages/core/src/ipc-channels.ts` CLOUD_SYNC 11종 채널
- `packages/core/types.ts` AppConfig + ConfigService defaults에 supabaseUrl/supabaseAnonKey/cloudSyncLastAt + hfToken/diarizationEnabled (Phase 15.5 누락분 보충)
**설계 결정**
- Local-first push only (V2-4b에서 pull 추가)
- 마지막 동기화 epoch ms 기준 변경분만 전송
- nanoid PK를 PostgreSQL text로 그대로 upsert
- macOS open-url + Windows second-instance argv 방식 deep link
### Phase V2-6: Mobile MVP — 완료
**구조** (`apps/mobile/`, npm workspace에서 **제외**)
- Expo SDK 51 + React Native + Expo Router
- `lib/supabase.ts` (AsyncStorage), `lib/auth-context.tsx`
- `app/_layout.tsx`, `app/index.tsx`, `app/login.tsx`
- `app/(tabs)/{_layout, meetings, record, profile}.tsx`
- `expo-av`로 녹음 → stt-proxy 호출
- `README.md` + setup 가이드
**설계 결정**
- workspace 제외 (Expo native deps 부담 회피)
- MUI 미사용, 인라인 RN 스타일 (V2-6b에서 `@d3ro/ui-native` 분리)
- Deep link `scheme: 'd3ro-voice'`
### Phase V2-7: 팀 기능 (Web) — 완료
- `apps/web/src/app/teams/page.tsx` — 가입한 팀 카드 그리드
- `apps/web/src/app/teams/[id]/page.tsx` — 팀 상세 (멤버 + 공유 회의)
- `components/teams/create-team-form.tsx` — 팀 생성 + owner 자동 등록
- `components/teams/invite-member-form.tsx` — user_id 직접 입력 (V2-7b에서 정식 invite flow)
- Sidebar에 Teams/Billing 메뉴 + ko.json 새 키
- V2-2의 teams/team_members RLS 활용
### Phase V2-8: 결제 스캐폴딩 — 완료
- `apps/web/src/app/billing/page.tsx` — Free/Pro/Team 가격표 + 현재 티어
- `components/billing/checkout-button.tsx` — Edge Function 호출
- `server/supabase/functions/stripe-checkout/index.ts` — JWT 인증, customer 조회/생성, Checkout Session
- `server/supabase/functions/stripe-webhook/index.ts` — checkout.session.completed, subscription.* 이벤트 → subscriptions 업데이트
- `config.toml`에 두 함수 등록 (webhook verify_jwt=false)
**사용자 액션 필요**
- `STRIPE_SECRET_KEY` / `STRIPE_PRICE_PRO` / `STRIPE_PRICE_TEAM` / `STRIPE_WEBHOOK_SECRET` 설정
- Stripe 대시보드에서 product + price 생성
**미구현 (V2-8b)**
- Webhook signature 정식 검증 (현재 placeholder)
- Customer Portal
- Per-seat billing
## 알려진 차단/이슈