- 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개 문서
6.9 KiB
6.9 KiB
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 사용
- JSON 파일로 내보내기 (
- 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 네비게이션으로 각 화면 이동 가능