# 🎙️ 음성 인식 기능 구현 기술 명세

> **작성일**: 2026-02-16 14:39
> **최종 업데이트**: 2026-02-17 15:52
> **상태**: ✅ 구현 완료 + 모바일 통합 + P0 음성 명령 확장 (3→25) 완료

---

## 1. 현황 분석

### ✅ 완료 항목
| 항목 | 이전 상태 | 현재 상태 |
|------|-----------|-----------|
| `useSpeechRecognition.ts` | 미존재 | ✅ Web Speech API 코어 훅 (183줄) |
| `VoiceDictation.tsx` | 미존재 | ✅ 편집 모드 플로팅 FAB (146줄, 모바일 최적화) |
| `useVoiceCommand.ts` | 미존재 | ✅ 음성 명령 5그룹 25개 (P0 확장, 199줄) |
| `VoiceCommandProvider.tsx` | 미존재 | ✅ Context 위임 구조 (전역+페이지별) |
| `VoiceCommandContext.tsx` | 미존재 | ✅ 페이지별 명령 핸들러 등록 Context (NEW) |
| `RecordingConsentModal.tsx` | 미존재 | ✅ 동의 녹취 확인 모달 — 통신비밀보호법 준수 (NEW) |
| `SearchInput.tsx` | 마이크 없음 | ✅ 음성 검색 마이크 버튼 추가 |
| `useVoiceRecorder.ts` | Mock 트랜스크립션 | ✅ 실제 Web Speech API 연동 (126줄) |
| `DocumentClient.tsx` | VoiceDictation 미연결 | ✅ 편집 모드에서 VoiceDictation 활성화 |
| `layout.tsx` | VoiceCommand 미등록 | ✅ VoiceCommandProvider 전역 등록 |

---

## 2. 아키텍처 결정 : 2-Layer 접근

```
┌─────────────────────────────────────────────┐
│  Layer 1: Web Speech API (무료, 즉시 동작)  │
│  ├─ 음성 검색: STT → 검색어 → 매직 검색    │
│  ├─ 음성 받아쓰기: STT → 에디터 커서 삽입   │
│  └─ 음성 명령: 5그룹 25개 (P0 확장)      │
├─────────────────────────────────────────────┤
│  Layer 2: Gemini Live API (BYOK, 고급)      │
│  ├─ 장시간 상담 녹음 + 실시간 STT           │
│  ├─ PII 마스킹 (주민번호, 전화번호)         │
│  └─ AI 요약 + 화자 분리 (향후)              │
└─────────────────────────────────────────────┘
```

### 왜 2-Layer?
| 기준 | Web Speech API | Gemini Live API |
|------|:---:|:---:|
| **비용** | 무료 | BYOK (유료) |
| **응답 속도** | ~200ms | ~500ms~1s |
| **한국어 정확도** | 높음 (Chrome) | 높음 |
| **브라우저 지원** | Chrome/Edge/Safari(14.5+) | 전체 (API 기반) |
| **장시간 녹음** | ❌ (60초 제한) | ✅ |
| **AI 분석** | ❌ | ✅ (요약, PII) |

→ **일상적 음성 입력은 무료 API**, **장시간 상담 기록은 Gemini** 로 역할 분담.

---

## 3. 구현 파일 목록

| 파일 | 유형 | 줄 수 | 설명 |
|------|------|------:|------|
| `hooks/useSpeechRecognition.ts` | NEW | 183 | Web Speech API 래핑 훅 |
| `hooks/useVoiceCommand.ts` | NEW | 108 | 음성 명령 인식기 |
| `components/VoiceDictation.tsx` | NEW | 146 | 받아쓰기 플로팅 FAB (모바일 최적화) |
| `components/VoiceCommandProvider.tsx` | NEW | 31 | 전역 음성 명령 (layout 등록) |
| `components/search/SearchInput.tsx` | MODIFY | — | 마이크 버튼 추가 |
| `hooks/useVoiceRecorder.ts` | MODIFY | 126 | Mock → 실제 Web Speech API |
| `app/docs/[id]/DocumentClient.tsx` | MODIFY | — | VoiceDictation 연결 |
| `app/layout.tsx` | MODIFY | — | VoiceCommandProvider 전역 등록 |

---

## 4. 모바일 최적화

| 항목 | 구현 |
|------|------|
| FAB 터치 타겟 | 56px (모바일) / 48px (데스크톱) — Apple HIG 44pt+ 충족 |
| safe-area | `env(safe-area-inset-bottom)` — 아이폰 하단 제스처 바 대응 |
| 패널 너비 | 모바일: 화면 전체 (`left-2 right-2`), 데스크톱: 320px 고정 |
| 닫기 버튼 | 48px 터치 영역 (`p-2`, `touch-manipulation`) |

---

## 5. 브라우저 호환성

```typescript
// 미지원 감지 로직
const isSupported = typeof window !== 'undefined' && 
  ('SpeechRecognition' in window || 'webkitSpeechRecognition' in window);

// 미지원 시: 마이크 버튼 숨김 + "Chrome에서 사용해 주세요" 안내
```

| 환경 | 지원 | 비고 |
|------|:----:|------|
| Android Chrome | ✅ | 기본 `SpeechRecognition` |
| iOS Safari 14.5+ | ✅ | `webkitSpeechRecognition` |
| PC Chrome/Edge | ✅ | 기본 지원 |
| Firefox | ❌ | Web Speech API 미지원 → 버튼 자동 숨김 |

---

## 6. 보안 고려사항
- Web Speech API: 사용자 음성 데이터가 Google/Apple 서버로 전송됨 (Chrome/Safari STT 특성)
- 상담 녹음 시: 고객 동의 필수 (설계사 자체 판단)
- PII 마스킹: Gemini 텍스트 후처리로 주민번호/전화번호 필터링

---

## 7. 커밋 이력
| 커밋 | 내용 | 변경 |
|------|------|------|
| `97a7e75` | 음성 인식 실제 구현 (코어) | 7 files, +655 lines |
| `f4878a1` | 음성 인식 모바일 통합 | 4 files, +75 lines |
| `58b03cf` | P0 음성 명령 확장 (3→25) + 동의 녹취 모달 | 6 files, +485 lines |
