d3ro-voice/docs/design/06-gap-analysis.md
Yun Chan e24bb8378c 초기 프로젝트 설정: 하네스 시스템 + 설계서 + 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개 문서
2026-04-05 01:03:03 +09:00

17 KiB

06. 갭 분석 리포트

작성일: 2026-04-04 분석 대상: 00-master-architecture.md, 01-service-specifications.md, 02-ipc-and-types.md, 03-db-and-ui.md, CLAUDE.md


1. 설계서 간 불일치/충돌

1.1 서비스 이름 불일치

항목 00 (마스터 아키텍처) 01 (서비스 명세) 02 (IPC 채널) 수정 제안
TTS 서비스 TTSService LocalTTSService (섹션 3) LocalTTSService (tts:* 담당) LocalTTSService로 통일 — 00에서 수정
LLM 서비스 LLMService LocalLLMService (섹션 4) OllamaService (llm:* 담당) LocalLLMService로 통일 — 00, 02에서 수정
STT 서비스 LocalSTTService LocalSTTService LocalSTTService 일치 (OK)

1.2 서비스 개수 불일치

  • 00: 15개 서비스 (명시적 목록: 표 2.1)
  • 01: 10개 서비스만 상세 명세 (AudioCapture, LocalSTT, LocalTTS, LocalLLM, VoiceMode, TextInsert, Hotkey, Config, History, WindowManager)
  • 빠진 서비스 명세: I18nService, LoggerService, DictionaryService, SoundEffectService, CustomInstructionService, AutoLaunchService (6개)
  • 01에만 있는 서비스: WindowManagerService (00의 WindowManager를 서비스로 격상)

수정 제안: 01에 빠진 6개 서비스의 상세 명세를 추가하거나, 별도 문서로 분리

1.3 02의 IPC 채널에서만 등장하는 서비스/네임스페이스

02 IPC 채널 담당 서비스 명 00/01 존재 여부 비고
system:* SystemService, PermissionService 00/01에 없음 00에서 제거된 PermissionService가 02에 부활
stats:* StatsService 00/01에 없음 03의 stats 테이블과 관련되지만 서비스 명세 없음
dictionary:* DictionaryService 00에 있지만 01에 명세 없음

수정 제안:

  • system:* 채널의 담당 서비스를 명확히 정의 (신규 SystemService? 또는 기존 서비스에 분배?)
  • StatsService를 00의 서비스 목록에 추가하거나 HistoryService에 통합 명시
  • 01에 DictionaryService 명세 추가

1.4 IPC 네임스페이스 규칙 불일치

00의 규칙: ${feature}:${action} (예: hotkey:setDictation, history:getRecent, app:getVersion) 02의 실제 채널: hotkey:setDictationShortcut, history:getAll, system:getVersion

00 예시 02 실제 차이
hotkey:setDictation hotkey:setDictationShortcut action 이름 불일치
history:getRecent history:getAll 채널 자체가 다름 (getRecent 없음)
app:getVersion system:getVersion 네임스페이스 다름 (app: vs system:)
dictionary:addWord dictionary:add action 이름 불일치
instruction:* (00에 명시) 02에 없음 CustomInstruction 채널 전체 누락

수정 제안: 00의 5.1절 예시를 02의 실제 채널명과 일치하도록 갱신

1.5 이벤트 타입 이름/구조 불일치 (00/01 vs 02)

항목 00/01 (서비스 이벤트) 02 (IPC 타입) 불일치
에러 타입 ServiceError (01 공통타입) ErrorCode enum (00 §6.2) 01의 ServiceError는 문자열 코드, 00의 ErrorCode는 숫자 enum
AudioDevice { id, name, isDefault } (01) { deviceId, label, isDefault } (02) 필드명 불일치: id/deviceId, name/label
STTModel { id, name, size, language, downloaded } (01) { id, name, sizeBytes, downloaded, languages, accuracy, speed } (02) 02가 더 풍부. language (단일) vs languages (배열) 차이
RecognitionState Idle/Preparing/Ready/Recognizing/Processing/Completing/Completed/Cancelled/Error (01) IDLE/PREPARING/READY/RECOGNIZING/COMPLETING/COMPLETED/CANCELLED/ERROR (02) 01에 Processing 있음, 02에 없음. 케이싱도 다름 (PascalCase vs UPPER_CASE)
VoiceMode Dictation/HandsFree (01, const enum) 'dictation' / 'hands-free' (02, string literal) 타입 표현 방식 차이

수정 제안: 02의 shared/types.ts를 정본(source of truth)으로 하고, 01의 타입을 02에 맞춰 갱신

1.6 DB 스키마 vs HistoryService/IPC 필드 불일치

03 DB history 컬럼 02 HistoryEntry 타입 불일치
original_text originalText OK (camelCase 변환)
polished_text processedText 이름 불일치: polished vs processed
mode (dictation/translate/command) llmAction (refine/translate/...) 의미 불일치: DB의 mode는 녹음 모드, IPC의 llmAction은 LLM 처리 유형
focused_app, focused_app_name, focused_app_window_title targetApp (단일 필드) 세분화 불일치: DB는 3개 필드, IPC는 1개
duration (초, REAL) durationMs (ms) 단위 불일치: 초 vs 밀리초
stt_model, llm_model, stt_latency_ms, llm_latency_ms 해당 필드 없음 02에 누락
error_code, status, audio_local_path, detected_language, mic_device, app_version 해당 필드 없음 02에 누락
해당 컬럼 없음 sessionId 03에 누락 (id가 sessionId와 동일하다는 주석이 있으나 별도 필드는 없음)

수정 제안: 02의 HistoryEntry 타입을 03의 DB 스키마와 1:1 매핑되도록 확장

1.7 Dictionary 스키마 vs IPC 타입 불일치

03 DB dictionary 컬럼 02 DictionaryEntry 타입 불일치
word, pronunciation, category, usage_count from, to, caseSensitive, enabled, useCount 완전히 다른 구조: DB는 "단어+발음" 패턴, IPC는 "교정(from→to)" 패턴

수정 제안: 사전의 목적을 명확히 한 후 어느 한쪽으로 통일. "커스텀 단어 사전"(03)과 "자동 교정 사전"(02)은 다른 기능이므로, 두 테이블이 필요할 수 있음

1.8 IPC 방향 불일치

채널 00 §5.2 예시 02 채널 테이블 불일치
voice:startRecording on (fire-and-forget) handle (요청→응답) 00은 fire-and-forget, 02는 양방향
voice:stopRecording on (fire-and-forget) handle (요청→응답) 동일 불일치

수정 제안: 02의 handle 방식이 더 적절 (sessionId 반환 필요). 00 §5.2를 갱신


2. 빠진 설계 영역

우선순위 High

# 영역 현황 필요한 내용
1 빌드 설정 CLAUDE.md에 electron-vite 언급만 있고, electron.vite.config.ts의 구체적 설정 없음 electron-vite 설정 (main/preload/renderer 엔트리, external 모듈, 네이티브 모듈 처리), tsconfig.json (paths, target, module), vite.config.ts (proxy, define, alias)
2 패키징 설정 00에 electron-builder.yml 파일 트리에 없음 electron-builder.yml (app ID, productName, files, nsis/msi 설정, extraResources: Whisper/Piper 바이너리 번들링, afterSign hook)
3 프로젝트 초기화 CLAUDE.md에 npm run dev 등 명령어만 있음 package.json 의존성 전체 목록, postinstall (네이티브 모듈 리빌드), scripts 정의, electron-rebuild 설정
4 보안 (preload 안전성, IPC 검증) 00에 contextIsolation:true 언급만 있음 preload에서 expose할 채널 화이트리스트, IPC 입력값 검증 (zod schema), webPreferences 전체 설정 (sandbox, webSecurity), CSP 헤더

우선순위 Medium

# 영역 현황 필요한 내용
5 테스트 전략 CLAUDE.md에 vitest 언급만 있음 테스트 피라미드 (단위/통합/E2E 비율), 서비스별 테스트 파일 매핑, mock 전략 (Electron IPC, better-sqlite3, child_process), E2E 프레임워크 선택 (Playwright? Spectron?), CI 파이프라인
6 로깅 전략 00에 LoggerService = electron-log 래퍼 정도만 있음 로그 레벨 정책 (info/warn/error 기준), 로그 파일 위치/로테이션/최대 크기, 카테고리별 로거 (audio, stt, llm, ipc), 민감 정보 마스킹, 디버그 모드 활성화 방법
7 성능 기준 설계서에 타이밍 상수는 있으나 성능 목표 없음 STT 지연 목표 (base 모델 기준 < Xms), LLM 응답 시간 목표, UI 응답 시간 (FID < 100ms), 메모리 사용량 상한, CPU 사용량 기준
8 Sidecar 바이너리 관리 STT/TTS sidecar 언급은 있으나 바이너리 배포 방식 미정의 faster-whisper Python 환경 번들링 (PyInstaller? embedded Python?), Piper 바이너리 배포 방식, 모델 파일 저장 경로 (userData), 버전 관리, 자동 업데이트

우선순위 Low

# 영역 현황 필요한 내용
9 접근성 설계서에 언급 없음 키보드 네비게이션 (Tab order, focus trap), aria-label/role, 스크린 리더 호환성, 고대비 모드, 폰트 크기 조정
10 에러 복구 전략 에러 코드 정의는 있으나 복구 흐름 미정의 사이드카 크래시 시 자동 재시작 정책, 네트워크(Ollama) 끊김 시 재연결 로직, DB 손상 시 복구 절차
11 마이그레이션 전략 03에 drizzle-orm migrate 호출만 있음 마이그레이션 파일 생성/관리 방법, 스키마 버전 관리, 하위 호환성 정책
12 국제화(i18n) 상세 00에 I18nService 서비스 목록만 있음 번역 키 관리 방식 (JSON? ts?), 번역 파일 구조, fallback 언어, 날짜/숫자 포맷

3. 실현 가능성 리스크

3.1 faster-whisper sidecar의 실시간성

항목 내용
리스크 01의 설계는 "오디오 버퍼 전체를 한번에 전사"하는 배치 방식. 실시간 스트리밍 전사 불가.
영향도 High — 사용자가 긴 문장을 말할 때 녹음 종료 후 전사 지연이 체감됨
현재 설계 stdin으로 base64 인코딩된 오디오를 보내고 stdout으로 결과 수신 (01 §2 Sidecar 통신 프로토콜)
문제점 (1) base64 인코딩 오버헤드 (~33% 크기 증가), (2) 전체 오디오를 버퍼링 후 전송하므로 first-token latency가 높음, (3) faster-whisper 자체가 파일/버퍼 단위 처리 (진정한 스트리밍 미지원)
대안 (A) WAV 파일 임시 저장 후 파일 경로 전달 (base64 오버헤드 제거), (B) whisper.cpp의 stream 모드 사용 (진정한 실시간), (C) 청크 분할 전사 + 결합 (VAD 기반 세그먼트 단위), (D) faster-whisper의 --live 모드 활용 (커뮤니티 fork)
권장 초기에는 WAV 파일 전달 방식(A)으로 구현. 지연이 문제 시 whisper.cpp stream(B)으로 전환

3.2 uiohook-napi Windows 호환성

항목 내용
리스크 uiohook-napi v1.x는 Electron 33+에서 context-aware 네이티브 모듈로 빌드 필요
영향도 Medium — 빌드 실패 시 핫키 기능 전체 불가
문제점 (1) N-API 버전 호환성 확인 필요, (2) electron-rebuild로 리빌드 시 빌드 도구(MSVC, Python 3) 필요, (3) Windows Defender가 키보드 후킹을 위협으로 감지할 수 있음
대안 (A) Electron의 globalShortcut API (제한적이지만 네이티브 모듈 불필요), (B) iohook (더 오래된 포크, 유지보수 우려), (C) PowerShell 스크립트로 키 후킹 (복잡도 높음)
권장 uiohook-napi를 우선 시도하되, electron-rebuild 설정을 빌드 문서에 명시. globalShortcut은 hold-to-talk 미지원이므로 fallback으로 부적합

3.3 @nut-tree/nut-js 관리자 권한 이슈

항목 내용
리스크 Windows에서 키보드 시뮬레이션(Ctrl+V)에 관리자 권한이 필요할 수 있음
영향도 Medium — UAC 프롬프트 없이 텍스트 삽입 불가 시 핵심 기능 차질
문제점 (1) 일부 앱(관리자 권한으로 실행된 앱)에 키 입력 불가, (2) nut-js v3은 prebuild 바이너리 제공하지만 Electron과의 호환성 미확인, (3) Windows UAC 설정에 따라 동작 불일치
대안 (A) Electron의 clipboard.writeText() + robot.js로 Ctrl+V 시뮬레이션, (B) PowerShell SendKeys, (C) Windows Input Simulator (C++ addon), (D) node-key-sender
권장 nut-js로 우선 구현. 관리자 권한 앱 대상 실패 시 app.setAsDefaultProtocolClient나 매니페스트에 uiAccess: true 설정 검토

3.4 better-sqlite3 + Electron 네이티브 모듈 빌드

항목 내용
리스크 better-sqlite3는 C++ 네이티브 모듈로 Electron 버전과 Node.js ABI 불일치 시 빌드 실패
영향도 High — DB 초기화 실패 시 앱 전체 불가 (critical step)
문제점 (1) electron-rebuild가 필요하지만 MSVC 빌드 도구 필수, (2) Electron 33의 Node.js 버전과 better-sqlite3 prebuild 버전 일치 여부 불확실, (3) asar 패키징 시 .node 파일 제외 필요
대안 (A) @neondatabase/sql.js (WASM 기반, 빌드 불필요하지만 성능 저하), (B) sql.js (WASM), (C) drizzle-orm/libsql (libsql WASM 바인딩)
권장 better-sqlite3 유지. electron-builder extraFiles에 .node 파일 포함, postinstallelectron-rebuild 스크립트 추가. package.json에 "build": { "asarUnpack": ["**/better-sqlite3/**"] } 설정

3.5 electron-vite vs vite-plugin-electron

항목 내용
리스크 선택 근거가 문서화되지 않음
영향도 Low — 둘 다 성숙한 도구이며 전환 비용은 초기에 낮음
비교 electron-vite: 공식 Electron 지원 느낌, main/preload/renderer 분리 빌드 기본 지원, 네이티브 모듈 external 자동 처리. vite-plugin-electron: 더 가벼움, Vite 생태계 플러그인, 커스터마이징 유연.
권장 CLAUDE.md에 electron-vite 명시됨. 선택 근거를 설계 문서에 한 줄 추가: "electron-vite 채택 — main/preload/renderer 3-entry 빌드 기본 지원, 네이티브 모듈 external 자동 처리"

4. 보강 권장사항 (액션 아이템)

4.1 설계서 수정 (기존 문서)

# 대상 문서 액션 우선순위
A1 00-master-architecture.md 서비스명 통일: TTSServiceLocalTTSService, LLMServiceLocalLLMService High
A2 00-master-architecture.md §5.1 IPC 예시를 02의 실제 채널명과 동기화 Medium
A3 00-master-architecture.md §5.2 voice:startRecording/stopRecording의 방향을 handle로 수정 Medium
A4 01-service-specifications.md 누락된 6개 서비스 명세 추가 (I18n, Logger, Dictionary, SoundEffect, CustomInstruction, AutoLaunch) High
A5 01-service-specifications.md 01의 타입 정의를 02와 통일 (AudioDevice, STTModel, RecognitionState 등) High
A6 02-ipc-and-types.md instruction:* (CustomInstruction) IPC 채널 추가 Medium
A7 02-ipc-and-types.md HistoryEntry 타입을 03 DB 스키마와 매핑되도록 확장 High
A8 02-ipc-and-types.md DictionaryEntry 타입과 03 DB dictionary 스키마 불일치 해결 High
A9 02-ipc-and-types.md SystemService, StatsService를 00 서비스 목록에 반영하거나, 기존 서비스에 역할 배분 Medium
A10 03-db-and-ui.md polished_textprocessed_text로 변경 (또는 02 타입을 polishedText로 변경) Medium
A11 03-db-and-ui.md duration 단위를 ms (INTEGER)로 통일 (02의 durationMs와 일치) Medium

4.2 신규 설계 문서 작성

# 문서명 내용 우선순위
B1 04-build-and-packaging.md electron-vite 설정, tsconfig, electron-builder.yml, 네이티브 모듈 빌드 설정, extraResources (sidecar 바이너리), scripts 정의, CI/CD 파이프라인 High
B2 05-testing-strategy.md 테스트 프레임워크 (vitest), 서비스별 테스트 파일, mock 전략, E2E 전략, 커버리지 목표 Medium
B3 07-sidecar-management.md faster-whisper/Piper 바이너리 배포, Python 환경 관리, 모델 저장 경로, 버전 관리, 헬스체크 상세, 크래시 복구 High
B4 08-security-checklist.md preload 화이트리스트, IPC 입력 검증 (zod), webPreferences, CSP, sandbox 설정, 외부 URL 열기 제한 Medium

4.3 CLAUDE.md 보강

# 액션 우선순위
C1 electron-vite 선택 근거 한 줄 추가 Low
C2 네이티브 모듈 리빌드 명령어 (npx electron-rebuild) 추가 Medium
C3 환경 요구사항 추가: Node.js 버전, Python 버전 (faster-whisper용), MSVC Build Tools Medium

5. 요약 매트릭스

카테고리 High Medium Low 합계
설계서 간 불일치 4 5 0 9
빠진 설계 영역 4 4 4 12
실현 가능성 리스크 2 2 1 5
보강 액션 아이템 7 9 2 18