From 397b3ba711dc651b372ecb6f83cd10e7a5ab60b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=B3=B4=EA=B3=A4?= Date: Tue, 10 Feb 2026 09:20:49 +0900 Subject: [PATCH] =?UTF-8?q?docs:=EC=9D=8C=EC=84=B1=EC=9E=85=EB=A0=A5=20STT?= =?UTF-8?q?=20=EA=B0=80=EC=9D=B4=EB=93=9C=20v1.1=20-=20Alpine.js=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84=20=ED=8C=A8=ED=84=B4=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 영업 전략 시나리오 / 매니저 상담 프로세스 STT 개선 내용 반영 - Alpine.js vs React 구현 비교표 - Alpine.js startSpeechRecognition() 코드 + 프리뷰 패널 Blade 코드 - 영업 시나리오 추가 기능 (음성 녹음, 파형 시각화, GCS 백업, 재생) - 데이터 흐름도 (MediaRecorder + STT + 서버 저장) - onend 자동 재시작 패턴 (긴 녹음 대응) - 참조 구현 파일 목록 확장 Co-Authored-By: Claude Opus 4.6 --- features/voice-input-stt-guide.md | 237 +++++++++++++++++++++++++++++- 1 file changed, 230 insertions(+), 7 deletions(-) diff --git a/features/voice-input-stt-guide.md b/features/voice-input-stt-guide.md index 0b204ca..7758475 100644 --- a/features/voice-input-stt-guide.md +++ b/features/voice-input-stt-guide.md @@ -1,9 +1,9 @@ # 음성 입력(STT) 기술 가이드 -> **문서 버전**: 1.0 +> **문서 버전**: 1.1 > **작성일**: 2026-02-10 -> **최초 적용**: 공사현장 사진대지 (`/juil/construction-photos`) -> **대상 프로젝트**: MNG (React 18 + Babel in-browser) +> **적용 페이지**: 공사현장 사진대지, 영업 전략 시나리오, 매니저 상담 프로세스 +> **대상 프로젝트**: MNG (React 18 + Alpine.js) --- @@ -637,9 +637,222 @@ const toggle = useCallback((e) => { 한 페이지에 여러 VoiceInputButton을 배치할 수 있다. 각 인스턴스는 독립적인 `recognitionRef`를 가지므로 충돌하지 않는다. 단, **동시에 2개 이상 녹음은 불가**하다 (브라우저 마이크 제한). 한 버튼이 녹음 중일 때 다른 버튼을 누르면 기존 녹음이 중단된다 (브라우저 동작). +### 9.7 onend 자동 재시작 (긴 녹음) + +`continuous: true`여도 브라우저가 무음 감지 시 자동으로 `onend`를 호출한다. 녹음이 계속 진행 중이라면 `onend`에서 재시작해야 한다. + +```javascript +// Alpine.js 패턴 +recognition.onend = () => { + if (this.isRecording && this.recognition) { + try { this.recognition.start(); } catch (e) {} + } +}; + +// React 패턴 (VoiceInputButton) +// onend에서 logUsage + dismiss 타이머 처리 +recognition.onend = () => { + if (startTimeRef.current) { + logUsage(startTimeRef.current); + startTimeRef.current = null; + } + setRecording(false); + dismissTimerRef.current = setTimeout(() => setFinalizedSegments([]), 2000); +}; +``` + +영업 시나리오는 `onend`에서 재시작하여 긴 상담도 끊김 없이 인식한다. 반면 공사현장 사진대지는 짧은 입력이므로 재시작하지 않는다. + --- -## 10. 향후 확장 가능성 +## 10. Alpine.js 구현 (영업/매니저 시나리오) + +영업 전략 시나리오와 매니저 상담 프로세스는 **Alpine.js + Blade** 기반이다. React 없이 동일한 STT 규칙을 적용한다. + +### 10.1 적용 파일 + +| 파일 | 경로 | 용도 | +|------|------|------| +| voice-recorder.blade.php | `resources/views/sales/modals/voice-recorder.blade.php` | 음성 녹음 + STT 컴포넌트 | +| scenario-modal.blade.php | `resources/views/sales/modals/scenario-modal.blade.php` | 시나리오 모달 (voice-recorder 포함) | +| consultation-log.blade.php | `resources/views/sales/modals/consultation-log.blade.php` | 상담 기록 표시/재생 | + +### 10.2 React vs Alpine.js 차이점 + +| 항목 | React (공사현장 사진대지) | Alpine.js (영업 시나리오) | +|------|--------------------------|--------------------------| +| 상태 관리 | `useState`, `useRef` | `x-data` 속성 | +| 확정 텍스트 | `finalizedSegments` state | `finalizedSegments` 배열 | +| 미확정 텍스트 | `interimText` state | `interimTranscript` | +| 자동 스크롤 | `useEffect` + `previewRef` | `$nextTick()` + `$refs` | +| 반복 렌더링 | `{arr.map((seg, i) => )}` | `