# AI 제안사항 SSE 연동 가이드 ## 📋 개요 실시간 회의 중 AI가 생성한 제안사항을 Server-Sent Events(SSE)를 통해 프론트엔드로 전송하는 기능입니다. ## 🔗 API 정보 ### Endpoint ``` GET http://localhost:8086/api/ai/suggestions/meetings/{meeting_id}/stream ``` ### Parameters - `meeting_id` (path): 회의 ID (예: `test-meeting-001`) ### Response Type - **Content-Type**: `text/event-stream` - **Transfer-Encoding**: chunked - **Cache-Control**: no-cache ## 🎯 동작 방식 ### 1. 데이터 흐름 ``` STT Service → Event Hub → AI Service (Python) ↓ Redis 저장 ↓ 임계값 도달 (3개 세그먼트) ↓ Claude API 분석 ↓ SSE로 프론트엔드 전송 ``` ### 2. 임계값 설정 - **최소 세그먼트**: 3개 - **예상 시간**: 약 15-30초 분량의 대화 - **텍스트 보관**: 최근 5분간 데이터 ### 3. SSE 이벤트 종류 #### ✅ `ping` 이벤트 (Keep-alive) ``` event: ping data: connected ``` - **목적**: SSE 연결 유지 - **주기**: 5초마다 전송 - **처리**: 프론트엔드에서 로그만 출력하고 무시 #### ✅ `ai-suggestion` 이벤트 (AI 제안사항) ``` event: ai-suggestion id: 3 data: {"suggestions":[...]} ``` ## 💻 프론트엔드 구현 ### 참고 파일 ``` /Users/jominseo/HGZero/test-audio/stt-test-wav.html ``` ### 기본 구현 코드 ```javascript const meetingId = 'your-meeting-id'; const aiServiceUrl = 'http://localhost:8086'; let eventSource = null; // SSE 연결 function connectAISuggestions() { const sseUrl = `${aiServiceUrl}/api/ai/suggestions/meetings/${meetingId}/stream`; eventSource = new EventSource(sseUrl); // Keep-alive 핸들러 (로그만 출력) eventSource.addEventListener('ping', (event) => { console.log('Ping received:', event.data); }); // AI 제안사항 핸들러 eventSource.addEventListener('ai-suggestion', (event) => { try { const data = JSON.parse(event.data); displaySuggestions(data); console.log('✅ AI 제안사항 수신:', data.suggestions.length + '개'); } catch (e) { console.error('AI 제안 파싱 실패:', e); } }); // 연결 성공 eventSource.onopen = () => { console.log('✅ AI 제안사항 SSE 연결 성공'); }; // 에러 핸들링 eventSource.onerror = (error) => { const state = eventSource.readyState; console.error('SSE Error:', error, 'State:', state); // CLOSED 상태일 때만 재연결 if (state === EventSource.CLOSED) { console.log('❌ AI 제안사항 SSE 연결 종료'); eventSource.close(); // 5초 후 재연결 setTimeout(() => { console.log('AI SSE 재연결 시도...'); connectAISuggestions(); }, 5000); } }; } // AI 제안사항 표시 function displaySuggestions(data) { if (!data.suggestions || data.suggestions.length === 0) { return; } data.suggestions.forEach(suggestion => { // suggestion 구조: // { // id: "uuid", // content: "제안 내용", // timestamp: "HH:MM:SS", // confidence: 0.85 // } console.log(`[${suggestion.timestamp}] ${suggestion.content}`); console.log(` 신뢰도: ${(suggestion.confidence * 100).toFixed(0)}%`); // UI에 표시하는 로직 추가 // ... }); } // 연결 종료 function disconnectAISuggestions() { if (eventSource) { eventSource.close(); eventSource = null; console.log('✅ AI SSE 연결 종료'); } } ``` ## 🚨 주요 이슈 및 해결방법 ### 1. CORS 오류 **증상** ``` Access to resource has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present ``` **해결** - ✅ 이미 백엔드에서 CORS 헤더 설정 완료 - Python AI Service는 `http://localhost:8888` origin 허용 ### 2. SSE 연결이 즉시 끊어짐 **증상** - `readyState: CLOSED` - 계속 재연결 시도 **원인** - EventSource가 `ping` 이벤트를 처리하지 못함 - Keep-alive 메시지가 없어서 브라우저가 연결 종료로 판단 **해결** ```javascript // ping 이벤트 핸들러 반드시 추가 eventSource.addEventListener('ping', (event) => { console.log('Ping:', event.data); }); ``` ### 3. 데이터가 오지 않음 **원인** - Redis에 텍스트가 충분히 쌓이지 않음 (3개 미만) - STT 서비스가 텍스트를 Event Hub로 전송하지 않음 **확인 방법** ```bash # 터미널에서 직접 테스트 curl -N http://localhost:8086/api/ai/suggestions/meetings/test-meeting-001/stream ``` **해결** - 최소 15-30초 정도 음성 입력 필요 - STT Service와 Event Hub 연결 상태 확인 ### 4. 브라우저 캐시 문제 **증상** - 코드 수정 후에도 이전 동작 반복 **해결** - **Hard Refresh**: `Ctrl+Shift+R` (Windows) / `Cmd+Shift+R` (Mac) - 시크릿 모드 사용 - 개발자 도구 → Network → "Disable cache" 체크 ## 📦 응답 데이터 구조 ### AI 제안사항 응답 ```typescript interface SimpleSuggestion { id: string; // UUID content: string; // 제안 내용 (1-2문장) timestamp: string; // "HH:MM:SS" 형식 confidence: number; // 0.0 ~ 1.0 (신뢰도) } interface RealtimeSuggestionsResponse { suggestions: SimpleSuggestion[]; } ``` ### 예시 ```json { "suggestions": [ { "id": "550e8400-e29b-41d4-a716-446655440000", "content": "OFDM 기술의 신제품 적용 가능성을 검토하고, 기술 사양 및 구현 방안에 대한 상세 분석 보고서를 작성하여 다음 회의 전까지 공유해야 합니다.", "timestamp": "17:01:25", "confidence": 0.88 }, { "id": "73ba9f1e-7793-46a4-bd6a-8dde9db36482", "content": "AICC 구축 협의를 위한 구체적인 일정을 수립하고, 관련 부서 담당자들과 협의 미팅을 조율해야 합니다.", "timestamp": "17:01:25", "confidence": 0.85 } ] } ``` ## 🔧 테스트 방법 ### 1. 로컬 환경 테스트 ```bash # AI Service 실행 확인 curl http://localhost:8086/health # SSE 연결 테스트 (3초 후 자동 종료) timeout 30 curl -N http://localhost:8086/api/ai/suggestions/meetings/test-meeting-001/stream ``` ### 2. 브라우저 테스트 1. `http://localhost:8888/stt-test-wav.html` 접속 2. 개발자 도구(F12) 열기 3. Network 탭에서 `stream` 요청 확인 4. Console 탭에서 "Ping received" 로그 확인 ### 3. 실제 음성 테스트 1. "녹음 시작" 버튼 클릭 2. 15-30초 정도 음성 입력 3. AI 제안사항 표시 확인 ## ⚙️ 환경 설정 ### Backend (Python AI Service) - **Port**: 8086 - **Endpoint**: `/api/ai/suggestions/meetings/{meeting_id}/stream` - **CORS**: `http://localhost:8888` 허용 ### 임계값 설정 ```python # app/config.py min_segments_for_analysis: int = 3 # 3개 세그먼트 text_retention_seconds: int = 300 # 5분 ``` ## 📝 체크리스트 프론트엔드 구현 시 확인 사항: - [ ] `EventSource` 생성 및 연결 - [ ] `ping` 이벤트 핸들러 추가 (필수!) - [ ] `ai-suggestion` 이벤트 핸들러 추가 - [ ] 에러 핸들링 및 재연결 로직 - [ ] 연결 종료 시 리소스 정리 - [ ] UI에 제안사항 표시 로직 - [ ] 브라우저 콘솔에서 ping 로그 확인 - [ ] Hard Refresh로 캐시 제거 ## 🐛 디버깅 팁 ### Console 로그로 상태 확인 ```javascript // 정상 동작 시 5초마다 출력 console.log('Ping received:', 'connected'); console.log('Ping received:', 'alive-3'); ``` ### Network 탭에서 확인 - Status: `200 OK` - Type: `eventsource` - Transfer-Encoding: `chunked` ### 문제 발생 시 확인 1. AI Service 실행 여부: `curl http://localhost:8086/health` 2. CORS 헤더: Network 탭 → Headers → Response Headers 3. 이벤트 수신: EventStream 탭에서 실시간 데이터 확인 ## 📞 문의 문제 발생 시: 1. 브라우저 Console 로그 확인 2. Network 탭의 요청/응답 헤더 확인 3. 백엔드 로그 확인: `tail -f /Users/jominseo/HGZero/ai-python/logs/ai-service.log` --- **작성일**: 2025-10-29 **작성자**: Backend Team (동욱) **참고 파일**: `/Users/jominseo/HGZero/test-audio/stt-test-wav.html`