초기 프로젝트 설정: 하네스 시스템 + 설계서 + RE 노하우
- CLAUDE.md: 프로젝트 규칙, 기술 스택, 코딩 규칙, 페이즈 로드맵 - .claude/settings.json: 권한, 강제 훅 (매 프롬프트 설계서 규칙 주입) - .claude/skills/: implement-phase, review-phase, scaffold, test-commit, debug - .claude/agents/: electron-architect, voice-pipeline-expert, ui-specialist - docs/design/00-09: 마스터 아키텍처, 서비스 명세(16개), IPC(113채널), DB스키마, UI컴포넌트, 검증리포트, 외부엔진연동, 갭분석, VoiceMode패턴, 디자인시스템, 히스토리팝업 - docs/phases/1-7+3.5: 전체 구현 페이즈 문서 - docs/re-findings/: Speakly RE 노하우 5개 문서
This commit is contained in:
commit
e24bb8378c
35 changed files with 11452 additions and 0 deletions
148
docs/phases/phase-5.md
Normal file
148
docs/phases/phase-5.md
Normal file
|
|
@ -0,0 +1,148 @@
|
|||
# Phase 5: TTS + 히스토리/사전 DB
|
||||
|
||||
## 목표
|
||||
TTS 엔진을 연동하여 텍스트를 음성으로 재생하고, 히스토리와 사전 DB를 완전 구현하여 사용자 데이터를 체계적으로 관리한다. Dashboard 통계 UI를 완성한다.
|
||||
|
||||
## 태스크
|
||||
|
||||
### 5.1 LocalTTSService 구현
|
||||
- `src/main/services/LocalTTSService.ts`
|
||||
- Piper-TTS 또는 Kokoro sidecar 프로세스 관리 (spawn/kill)
|
||||
- 상태 머신: `Idle → Loading → Speaking → Idle` (서비스 명세 TTSState 참조)
|
||||
- 싱글톤 + EventEmitter 패턴
|
||||
- Sidecar 통신 프로토콜:
|
||||
```
|
||||
Main Process piper-tts sidecar
|
||||
│── stdin: text ────────►│
|
||||
│◄── stdout: WAV data ───│ (또는 PCM 스트리밍)
|
||||
```
|
||||
- 음성 모델 디렉토리 관리 (`userData/tts-models/`)
|
||||
- TTSVoice 목록 조회: id, name, language, gender, sampleRate, downloaded
|
||||
|
||||
### 5.2 TTS 오디오 재생
|
||||
- Node.js 측에서 PCM/WAV 데이터를 renderer로 전달
|
||||
- renderer에서 Web Audio API로 재생
|
||||
- IPC 채널:
|
||||
- `tts:speak` — 텍스트 합성 및 재생 시작
|
||||
- `tts:stop` — 재생 중지
|
||||
- `tts:getVoices` — 사용 가능한 음성 목록
|
||||
- `tts:audioChunk` (main→renderer) — 오디오 청크 스트리밍
|
||||
- `tts:finished` (main→renderer) — 재생 완료
|
||||
- TTSOptions: speed (0.5~2.0), format (pcm/wav)
|
||||
|
||||
### 5.3 TTS 재생 UI
|
||||
- ResultPopupWindow에 재생/중지 버튼 추가
|
||||
- 재생 아이콘 (▶) → 클릭 시 TTS 재생, 아이콘 중지(■)로 변경
|
||||
- 재생 중 상태 표시 (파형 또는 진행 바)
|
||||
- History UI 각 항목에 재생 버튼 추가
|
||||
- ConfigService의 `tts.enabled` 설정에 따라 버튼 표시/숨김
|
||||
|
||||
### 5.4 HistoryService 완전 구현
|
||||
- `src/main/services/HistoryService.ts`
|
||||
- better-sqlite3 + drizzle-orm (DB 스키마: `03-db-and-ui.md` 참조)
|
||||
- CRUD 메서드:
|
||||
- `create(input: CreateHistoryInput): Promise<History>` — nanoid로 ID 생성
|
||||
- `getById(id: string): Promise<History | null>`
|
||||
- `getList(filter: HistoryFilter): Promise<{ entries: History[]; total: number }>` — 페이지네이션
|
||||
- `update(id: string, data: Partial<History>): Promise<void>`
|
||||
- `softDelete(id: string): Promise<void>` — deleted 플래그 설정
|
||||
- `hardDelete(id: string): Promise<void>` — 물리 삭제
|
||||
- `bulkDelete(ids: string[]): Promise<void>`
|
||||
- 검색: originalText, polishedText에 대한 LIKE 검색, 날짜 범위, 모드, 상태 필터
|
||||
- 통계 집계:
|
||||
- `getStats(): Promise<HistoryStats>` — 총 항목, 총 녹음 시간, 언어별 통계 등
|
||||
- stats 테이블 싱글턴 업데이트 (세션 완료 시 자동 갱신)
|
||||
- 연속 사용 일수(streakDays) 계산
|
||||
- 보존 정책:
|
||||
- `cleanupOldEntries()`: retentionDays(30일) 초과 + softDelete된 항목 물리 삭제
|
||||
- 앱 시작 시 + 24시간 주기로 실행
|
||||
- maxEntries 초과 시 오래된 항목부터 softDelete
|
||||
|
||||
### 5.5 DictionaryService 완전 구현
|
||||
- `src/main/services/DictionaryService.ts`
|
||||
- better-sqlite3 + drizzle-orm (DB 스키마: `03-db-and-ui.md` 참조)
|
||||
- CRUD 메서드:
|
||||
- `add(word: string, pronunciation?: string, category?: string): Promise<Dictionary>`
|
||||
- `update(id: string, data: Partial<Dictionary>): Promise<void>`
|
||||
- `delete(id: string): Promise<void>`
|
||||
- `getAll(filter?: DictionaryFilter): Promise<Dictionary[]>`
|
||||
- `search(query: string): Promise<Dictionary[]>` — word 검색
|
||||
- `incrementUsage(id: string): Promise<void>` — usageCount 증가 + lastUsedAt 갱신
|
||||
- 카테고리 관리: `user`, `auto`, `technical`
|
||||
- STT 연동: Whisper initialPrompt에 사전 단어 목록 주입
|
||||
- 전사 시작 전 DictionaryService에서 상위 N개 단어 조회
|
||||
- initialPrompt 형태: `"단어1, 단어2, 단어3"` (Whisper 컨텍스트 힌트)
|
||||
- 사용 횟수 자동 갱신: 전사 결과에 사전 단어가 포함되면 incrementUsage 호출
|
||||
|
||||
### 5.6 History UI (React)
|
||||
- `src/renderer/components/History.tsx`
|
||||
- 목록 표시:
|
||||
- MUI DataGrid 또는 커스텀 리스트
|
||||
- 원본 텍스트, 다듬어진 텍스트, 모드, 상태, 날짜, 녹음 시간 표시
|
||||
- 무한 스크롤 또는 페이지네이션 (기본 50개씩)
|
||||
- 검색: 텍스트 검색 입력 + 필터 (날짜 범위, 모드, 언어)
|
||||
- 항목별 액션:
|
||||
- 복사 (원본/다듬은 텍스트)
|
||||
- 재시도 (같은 텍스트를 다시 LLM 처리)
|
||||
- TTS 재생 (Phase 5.3 연동)
|
||||
- 삭제 (softDelete + 확인 다이얼로그)
|
||||
- IPC 채널:
|
||||
- `history:getList` — 목록 조회
|
||||
- `history:getById` — 상세 조회
|
||||
- `history:delete` — 삭제
|
||||
- `history:bulkDelete` — 일괄 삭제
|
||||
- `history:search` — 검색
|
||||
- `history:getStats` — 통계
|
||||
|
||||
### 5.7 Dictionary UI (React)
|
||||
- `src/renderer/components/Dictionary.tsx`
|
||||
- 단어 목록: word, pronunciation, category, usageCount 표시
|
||||
- 추가: 단어 + 발음 힌트 + 카테고리 입력 다이얼로그
|
||||
- 편집: 인라인 편집 또는 모달
|
||||
- 삭제: 확인 후 삭제
|
||||
- 가져오기/내보내기:
|
||||
- JSON 파일로 내보내기 (`[{ word, pronunciation, category }]`)
|
||||
- JSON 파일에서 가져오기 (중복 word+category 시 스킵 또는 덮어쓰기 옵션)
|
||||
- Electron dialog.showOpenDialog / dialog.showSaveDialog 사용
|
||||
- IPC 채널:
|
||||
- `dictionary:getAll` — 전체 목록
|
||||
- `dictionary:add` — 추가
|
||||
- `dictionary:update` — 수정
|
||||
- `dictionary:delete` — 삭제
|
||||
- `dictionary:import` — 파일에서 가져오기
|
||||
- `dictionary:export` — 파일로 내보내기
|
||||
|
||||
### 5.8 Dashboard 통계 UI 완성
|
||||
- `src/renderer/components/Dashboard.tsx`
|
||||
- 통계 카드:
|
||||
- 총 녹음 시간 (시:분:초 형식)
|
||||
- 총 단어 수
|
||||
- 총 세션 수
|
||||
- 연속 사용 일수 (streakDays)
|
||||
- 최근 7일 / 30일 활동 그래프 (간단한 바 차트, MUI 또는 커스텀 SVG)
|
||||
- 최근 세션 목록 (5~10개, History UI로 이동 링크)
|
||||
- 언어별/모드별 사용 비율 (파이 차트 또는 비율 바)
|
||||
- stats 테이블에서 데이터 조회 + history 테이블에서 최근 데이터 집계
|
||||
|
||||
### 5.9 Drawer 네비게이션 업데이트
|
||||
- Speakly 패턴: MUI Drawer (240px, permanent)
|
||||
- 네비게이션 항목 추가: Dashboard, History, Dictionary
|
||||
- 아이콘 + 텍스트 라벨
|
||||
- 현재 라우트 하이라이트
|
||||
|
||||
## Speakly RE 참조
|
||||
- HistoryService: SQLite 스키마 (history 테이블), CRUD 패턴, 검색 쿼리
|
||||
- DictionaryService: 단어 사전 관리, 카테고리 분류
|
||||
- RecordStatsService: 싱글턴 통계 테이블, 누적 집계 패턴
|
||||
- App.js: MUI Drawer 네비게이션, 라우팅 패턴 (useState 기반)
|
||||
- ResultPopup: 결과 표시 + 액션 버튼 패턴
|
||||
|
||||
## 완료 조건
|
||||
- [ ] TTS로 텍스트 음성 재생 가능
|
||||
- [ ] 재생/중지 버튼 UI 작동
|
||||
- [ ] 히스토리 CRUD + 검색 + 페이지네이션 작동
|
||||
- [ ] 히스토리 보존 정책 (30일 초과 자동 정리) 작동
|
||||
- [ ] 사전 CRUD + 가져오기/내보내기 작동
|
||||
- [ ] 사전 단어가 STT initialPrompt에 주입됨
|
||||
- [ ] Dashboard 통계 카드 및 최근 세션 표시
|
||||
- [ ] Drawer 네비게이션으로 각 화면 이동 가능
|
||||
Loading…
Add table
Add a link
Reference in a new issue