목차
출퇴근 영어 회화 앱 — 개발 계획서 v0.1
작성일: 2026-09-10 · 기준 문서: PRD v0.1 표기: [결정] 확정 · [제안] 검토 필요 · [확인 필요] 정보 요청 개발 방식: 구현은 Claude(Claude Code), 리뷰·실기기 테스트·배포 승인은 오너(개발자)
1. 변경 사항 요약
- [결정] Expo → React Native CLI (bare) + TypeScript
- [제안] 이에 따라 "웹으로 먼저 검증" 단계를 없애고, 처음부터 네이티브로 개발 → TestFlight / Play 내부 테스트로 검증
- 이유: Expo 없이 웹 빌드를 유지하려면 react-native-web 설정 비용이 크고, 오히려 네이티브로 가면 핵심 기능인 걷기 모드를 검증 단계부터 제대로 테스트할 수 있다.
- 웹 버전은 필요해지면 랜딩·체험용으로 별도 검토한다.
2. MVP 범위
PRD의 P0 전체 + 걷기 모드의 네이티브 기능 일부를 MVP에 포함한다.
| 기능 | MVP | 비고 |
|---|---|---|
| 온보딩 (출퇴근 정보, 레벨, 여행 목표) | ✅ | |
| 데일리 루틴 자동 생성 | ✅ | |
| 지하철 모드 (카드·대화·퀴즈) | ✅ | |
| 오프라인 다운로드·동기화 | ✅ | |
| 걷기 모드: 백그라운드 재생 + 이어폰 제어 | ✅ | 네이티브 전환으로 MVP 포함 |
| 걷기 모드: 따라 말하기 + 인식 피드백 | ✅ | 화면 켜진 상태 기준 |
| 걷기 모드: 화면 잠금 상태 녹음·인식 | ⏳ 2단계 | 기술 검증(스파이크) 후 결정 |
| 스트릭·여행 D-day 진행도 | ✅ | |
| 푸시 알림 | ⏳ 2단계 | |
| AI 롤플레이 | ⏳ 3단계 |
3. 기술 스택 [제안]
라이브러리는 착수 시점에 New Architecture 호환 여부, 최근 유지보수 상태, 최신 RN 버전 지원을 확인한 뒤 확정한다.
| 영역 | 선택 | 선택 이유 |
|---|---|---|
| 프레임워크 | React Native CLI (최신 안정 버전), TypeScript strict | 결정 사항 |
| 네비게이션 | React Navigation (native-stack) | 사실상 표준 |
| 서버 상태 | TanStack Query | 캐싱·재시도·오프라인 대응 |
| 클라이언트 상태 | Zustand | 가볍고 보일러플레이트 적음 |
| 로컬 저장 (KV) | react-native-mmkv | 설정·세션·진행 상태 등 빠른 저장 |
| 로컬 DB | op-sqlite | 오프라인 콘텐츠·학습 기록 |
| 파일 다운로드 | react-native-blob-util | 음성 파일 백그라운드 다운로드 |
| 오디오 재생 | react-native-track-player | 백그라운드 재생, 잠금 화면·이어폰 리모트 컨트롤 |
| 녹음 | 녹음 라이브러리 1종 (후보 비교 후 확정) | 따라 말하기 녹음 |
| 음성 인식 | 네이티브 STT (iOS Speech / Android SpeechRecognizer) 브리지 | 온디바이스 우선, 무료 |
| 백엔드 | Supabase (Auth, Postgres, Storage) | 인증·DB·파일을 한 곳에서 |
| TTS (콘텐츠 제작용) | 클라우드 TTS 1종 [확인 필요] | 음성은 사전 생성 후 배포 |
| 분석 | PostHog 또는 Firebase Analytics | 리텐션·퍼널 지표 |
| 에러 모니터링 | Sentry | 크래시·네이티브 오류 추적 |
| 테스트 | Jest, React Native Testing Library, Maestro | 단위·컴포넌트·E2E |
| CI/CD | GitHub Actions + Fastlane | 빌드·TestFlight·Play 업로드 자동화 |
4. 아키텍처
4.1 원칙
- 오프라인 우선: 화면은 항상 로컬 DB를 읽는다. 서버는 동기화 대상일 뿐이다.
- 오디오는 앱 전체에서 단일 서비스: 재생·녹음·인식은
audio모듈 하나가 담당하고 화면은 상태만 구독한다. - 기능 단위 폴더 구조: Claude가 기능 하나를 독립적으로 작업·리뷰할 수 있게 한다.
4.2 폴더 구조
src/
app/ # 네비게이션, 프로바이더, 앱 진입점
features/
onboarding/
routine/ # 루틴 생성 로직 + 오늘 화면
subway/ # 지하철 모드 (카드·대화·퀴즈)
walking/ # 걷기 모드 (오디오 플로우)
progress/ # 스트릭, 여행 진행도
services/
audio/ # TrackPlayer, 녹음, STT 래퍼
sync/ # 콘텐츠 다운로드, 기록 업로드
db/ # op-sqlite 스키마, 마이그레이션, 쿼리
api/ # Supabase 클라이언트
analytics/
shared/
ui/ # 공통 컴포넌트, 디자인 토큰
utils/
native/ # 커스텀 네이티브 모듈 (필요 시 STT 브리지 등)
scripts/
content/ # 콘텐츠 생성·검증·TTS 변환·업로드 스크립트
4.3 데이터 흐름
[Supabase] ── 콘텐츠 패키지(JSON + 음성) ──▶ [다운로드 큐] ──▶ [로컬 DB + 파일]
│
[화면·오디오]
│
[Supabase] ◀── 학습 기록 배치 업로드 ── [미전송 기록 큐] ◀────────┘
- 콘텐츠는 레슨 단위 패키지(JSON 1개 + mp3 여러 개)로 배포하고 버전 번호로 갱신 여부를 판단한다.
- 학습 기록은 로컬에 먼저 쓰고, 네트워크 복구 시 배치로 업로드한다. 충돌 시 "완료 상태는 되돌리지 않는다" 규칙.
5. 데이터 모델
PRD 8장 초안을 기준으로 서버(Supabase)와 로컬(SQLite)을 나눈다.
| 테이블 | 서버 | 로컬 | 비고 |
|---|---|---|---|
| users / profiles | ✅ | 일부 캐시 | 출퇴근 정보, 레벨 |
| travel_goals | ✅ | ✅ | |
| courses / situations / lessons | ✅ | ✅ | 읽기 전용, 패키지로 내려받음 |
| expressions / dialogues / quiz_items | ✅ | ✅ | 음성은 파일 경로로 저장 |
| progress | ✅ | ✅ | 로컬 우선 기록 |
| speaking_logs | ✅ | ✅ | 녹음 원본은 서버 전송 안 함 [제안] |
| daily_routines | ✅ | ✅ | 로컬에서 생성, 서버엔 기록용 |
| sync_queue | — | ✅ | 미전송 기록 |
- Supabase는 RLS(행 수준 보안)로 사용자 본인 기록만 접근 가능하게 설정한다.
- 콘텐츠 테이블은 모든 로그인 사용자 읽기 전용.
6. 핵심 기술 과제
각 과제는 해당 마일스톤 시작 전에 1~2일 스파이크(기술 검증)로 먼저 확인한다.
6.1 백그라운드 오디오 (iOS·Android)
- iOS: Background Modes의 Audio 활성화, 오디오 세션 카테고리 설정(재생 전용 / 재생+녹음 전환)
- Android: 포그라운드 서비스 + 미디어 알림
- 통화·다른 앱 재생 등 인터럽트 처리: 일시정지 후 자동 재개 여부 정책 필요
6.2 이어폰·잠금 화면 리모트 컨트롤
- 사용 가능한 이벤트: 재생/일시정지, 다음, 이전 (기기·이어폰마다 차이 있음)
- 매핑 [제안]: 재생/일시정지 = 멈춤·계속, 다음 = "알아요, 넘기기", 이전 = "다시 듣기"
- 더블탭 같은 커스텀 제스처는 기기 의존성이 커서 MVP에서 제외
6.3 따라 말하기 인식
- 흐름: 원어민 음성 재생 → 비프음 → 녹음·인식(최대 N초) → 목표 문장과 비교 → 음성 피드백
- 판정: 단어 일치율 기반, 관대하게 (시도 자체를 칭찬하는 방향)
- iOS 온디바이스 인식은 언어·기기별 지원 여부 확인 필요, 미지원 시 네트워크 인식으로 폴백
- 재생과 녹음 사이 오디오 세션 전환 시 끊김·지연 확인
6.4 화면 잠금 상태 녹음 (2단계, 스파이크만 MVP 중)
- iOS·Android 모두 백그라운드 마이크 사용은 정책·기술 제약이 있음
- MVP 기간 중 가능 범위를 검증하고, 불가 시 대안(짧게 화면 켜기 알림 등)을 결정한다
6.5 루틴 생성 알고리즘
- 입력: 탑승 시간, 도보 시간, 레벨, 여행 목표(선택), 진행 상황
- 레슨 요소별 예상 소요 시간을 상수로 두고 시간에 맞게 채우는 방식 (예: 표현 카드 1개 = 약 1분)
- 여행 목표: 남은 출퇴근 횟수 ÷ 남은 상황 수로 페이스 계산, 부족하면 복습 비중 축소
- 순수 함수로 작성해 단위 테스트로 검증
6.6 오프라인 다운로드
- 트리거: 앱 실행 시, Wi-Fi 연결 시, 전날 밤 [제안]
- 항상 "오늘 + 내일" 분량 보관, 7일 지난 음성 파일 정리
7. 마일스톤 [제안]
기간은 오너가 리뷰·실기기 테스트에 쓸 수 있는 시간에 따라 조정 [확인 필요]
| 마일스톤 | 기간 | 산출물 | 완료 기준 |
|---|---|---|---|
| M0. 환경 세팅 | 1주 | RN 프로젝트, 린트·포맷, CI, Supabase 프로젝트, 디자인 토큰, CLAUDE.md | iOS·Android 실기기에서 빈 앱 실행, CI 통과 |
| M1. 스파이크 | 1주 | 백그라운드 재생·리모트 컨트롤·녹음+STT 전환 검증 앱 | 걸으면서 잠금 화면 재생, 이어폰 버튼 동작 확인 |
| M2. 콘텐츠 파이프라인 | 1주 | DB 스키마, 콘텐츠 JSON 형식, TTS 변환·업로드 스크립트, 샘플 10개 상황 | 스크립트 1회 실행으로 레슨 패키지 배포 |
| M3. 온보딩·루틴 | 1주 | 온보딩 화면, 루틴 생성 로직, 오늘 화면 | 입력값에 따라 루틴이 달라지고 테스트 통과 |
| M4. 지하철 모드 | 2주 | 표현 카드, 대화, 퀴즈, 중단 복구 | 레슨 1개를 한 손으로 끝까지 진행 가능 |
| M5. 오프라인·동기화 | 1주 | 다운로드 큐, 로컬 DB, 기록 업로드 | 비행기 모드에서 레슨 완료 → 복구 후 서버 반영 |
| M6. 걷기 모드 | 2주 | 오디오 플로우, 따라 말하기, 음성 피드백, 이어폰 제어 | 화면 안 보고 걷기 루틴 완료 가능 |
| M7. 기록·분석·안정화 | 1주 | 스트릭, 여행 진행도, 분석 이벤트, Sentry | 핵심 이벤트 수집 확인, 크래시 없음 |
| M8. 베타 | 2주 | TestFlight / Play 내부 테스트 배포 | 테스터 20~30명 2주 사용, 지표 수집 |
MVP 합계: 약 12주 (베타 포함)
이후
- 2단계: 잠금 화면 녹음(검증 결과에 따라), 푸시 알림, 스토어 정식 출시
- 3단계: AI 롤플레이, 노선 연동, 여행 모드 고도화
8. Claude와의 작업 방식
역할 분담
| Claude | 오너 |
|---|---|
| 코드 작성, 테스트 작성, 리팩토링 | 요구사항 확정, 코드 리뷰 |
| 콘텐츠 초안·스크립트 작성 | 실기기 테스트 (특히 오디오·이어폰·지하철 환경) |
| 문서(CLAUDE.md, README) 유지 | 계정·키 관리, 스토어 배포 승인 |
규칙 [제안]
- 저장소 루트에 CLAUDE.md: 스택, 폴더 구조, 코딩 규칙, 명령어, 금지 사항(예: 비밀 키 커밋 금지)
- 작업 단위 = 이슈 1개 = PR 1개, 한 PR은 한 기능·300줄 내외
- 모든 PR은 타입 체크·린트·테스트 통과 후 리뷰 요청
- 네이티브 설정 변경(Info.plist, AndroidManifest, Podfile, Gradle)은 PR 설명에 변경 이유 명시
- 브랜치:
main보호,feat/*,fix/*
한계 인지
- Claude는 실기기에서 직접 실행·청취할 수 없으므로 오디오·이어폰·백그라운드 동작은 반드시 오너가 실기기로 검증
- iOS 빌드·서명은 Mac + Xcode 환경 필요
9. 테스트 전략
- 단위: 루틴 생성, 여행 페이스 계산, 발음 판정, 동기화 충돌 규칙
- 컴포넌트: 지하철 모드 카드·퀴즈 상호작용
- E2E (Maestro): 온보딩 → 루틴 → 레슨 완료 핵심 경로
- 실기기 체크리스트 (수동):
- 화면 잠금 후 재생 유지 / 이어폰 버튼 3종 동작
- 통화 수신 → 종료 후 재개
- 블루투스 이어폰 연결 끊김·재연결
- 비행기 모드(터널 가정)에서 레슨 진행
- 지하철 소음 환경에서 인식률
- 배터리 소모 (30분 걷기 모드)
10. 배포
- iOS: Apple Developer 계정, TestFlight 내부·외부 테스트
- Android: Google Play Console, 내부 테스트 트랙
- Fastlane으로 빌드·업로드 자동화, 버전은 태그 기반
- 심사 대비: 백그라운드 오디오 사용 사유, 마이크·음성 인식 권한 안내 문구를 명확히 작성
- 개인정보처리방침 페이지 필요 (음성 데이터 처리 방식 명시)
11. 리스크
| 리스크 | 영향 | 대응 |
|---|---|---|
| RN 버전 업·New Architecture와 라이브러리 비호환 | 일정 지연 | M0에서 핵심 라이브러리 호환 확인, 버전 고정 |
| 백그라운드 녹음 불가 | 걷기 모드 경험 축소 | M1 스파이크로 조기 확인, 대안 UX 준비 |
| 온디바이스 STT 품질·지원 기기 편차 | 피드백 신뢰도 저하 | 관대한 판정, 네트워크 인식 폴백 |
| 네이티브 이슈를 Claude가 실기기 없이 디버깅 | 반복 비용 증가 | 오너가 로그·재현 절차 공유, Sentry 활용 |
| 콘텐츠 제작이 개발보다 늦어짐 | 베타 지연 | M2 이후 콘텐츠 제작을 개발과 병행 |
12. 착수 전 확인 필요
- [ ] 개발 환경: Mac 보유 여부 (iOS 빌드 필수)
- [ ] 테스트 기기: 보유 중인 iPhone·Android 기종, 사용하는 이어폰
- [ ] 우선 플랫폼: iOS·Android 동시 vs 한쪽 먼저
- [ ] 최소 지원 OS 버전
- [ ] 계정: Apple Developer, Google Play Console, Supabase, GitHub
- [ ] TTS 서비스 선택과 월 예산
- [ ] 주당 리뷰·테스트 가능 시간 (마일스톤 기간 조정용)