hgzero/develop/dev/dev-frontend-mock-guide.md
Minseo-Jo 9bf3597cec AI 서비스 Python 마이그레이션 및 프론트엔드 연동 문서 추가
주요 변경사항:
- AI 서비스 Java → Python (FastAPI) 완전 마이그레이션
- 포트 변경: 8083 → 8086
- SSE 스트리밍 기능 구현 및 테스트 완료
- Claude API 연동 (claude-3-5-sonnet-20241022)
- Redis 슬라이딩 윈도우 방식 텍스트 축적
- Azure Event Hub 연동 준비 (STT 텍스트 수신)

프론트엔드 연동 지원:
- API 연동 가이드 업데이트 (Python 버전 반영)
- Mock 데이터 개발 가이드 신규 작성
- STT 개발 완료 전까지 Mock 데이터로 UI 개발 가능

기술 스택:
- Python 3.13
- FastAPI 0.104.1
- Anthropic Claude API 0.42.0
- Redis (asyncio) 5.0.1
- Azure Event Hub 5.11.4
- Pydantic 2.10.5

테스트 결과:
-  서비스 시작 정상
-  헬스 체크 성공
-  SSE 스트리밍 동작 확인
-  Redis 연결 정상

다음 단계:
- STT (Azure Speech) 서비스 연동 개발
- Event Hub를 통한 실시간 텍스트 수신
- E2E 통합 테스트 (STT → AI → Frontend)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-27 11:52:30 +09:00

385 lines
9.3 KiB
Markdown

# 프론트엔드 Mock 데이터 개발 가이드
**작성일**: 2025-10-27
**대상**: 프론트엔드 개발자 (유진)
**작성자**: AI팀 (서연), 백엔드팀 (준호)
---
## 📋 개요
**현재 상황**: STT 서비스 개발 완료 전까지는 **실제 AI 제안사항이 생성되지 않습니다.**
**해결 방안**: Mock 데이터를 사용하여 프론트엔드 UI를 독립적으로 개발할 수 있습니다.
---
## 🎯 왜 Mock 데이터가 필요한가?
### 실제 데이터 생성 흐름
```
회의 (음성)
STT 서비스 (음성 → 텍스트) ← 아직 개발 중
Redis (텍스트 축적)
AI 서비스 (Claude API 분석)
SSE 스트리밍
프론트엔드
```
**문제점**: STT가 없으면 텍스트가 생성되지 않아 → Redis가 비어있음 → AI 분석이 실행되지 않음
**해결**: Mock 데이터로 **STT 없이도** UI 개발 가능
---
## 💻 Mock 데이터 구현 방법
### 방법 1: 로컬 Mock 함수 (권장)
**장점**: 백엔드 없이 완전 독립 개발 가능
```javascript
/**
* Mock AI 제안사항 생성기
* 실제 AI처럼 5초마다 하나씩 제안사항 발행
*/
function connectMockAISuggestions(meetingId) {
const mockSuggestions = [
{
id: crypto.randomUUID(),
content: "신제품의 타겟 고객층을 20-30대로 설정하고, 모바일 우선 전략을 취하기로 논의 중입니다.",
timestamp: "00:05:23",
confidence: 0.92
},
{
id: crypto.randomUUID(),
content: "개발 일정: 1차 프로토타입은 11월 15일까지 완성, 2차 베타는 12월 1일 론칭",
timestamp: "00:08:45",
confidence: 0.88
},
{
id: crypto.randomUUID(),
content: "마케팅 예산 배분에 대해 SNS 광고 60%, 인플루언서 마케팅 40%로 의견이 나왔으나 추가 검토 필요",
timestamp: "00:12:18",
confidence: 0.85
},
{
id: crypto.randomUUID(),
content: "보안 요구사항 검토가 필요하며, 데이터 암호화 방식에 대한 논의가 진행 중입니다.",
timestamp: "00:15:30",
confidence: 0.90
},
{
id: crypto.randomUUID(),
content: "React로 프론트엔드 개발하기로 결정되었으며, TypeScript 사용을 권장합니다.",
timestamp: "00:18:42",
confidence: 0.93
}
];
let index = 0;
const interval = setInterval(() => {
if (index < mockSuggestions.length) {
// EventSource의 addEventListener('ai-suggestion', ...) 핸들러를 모방
const event = {
data: JSON.stringify({
suggestions: [mockSuggestions[index]]
})
};
// 실제 핸들러 호출
handleAISuggestion(event);
index++;
} else {
clearInterval(interval);
console.log('[MOCK] 모든 Mock 제안사항 발행 완료');
}
}, 5000); // 5초마다 하나씩
console.log('[MOCK] Mock AI 제안사항 연결 시작');
// 정리 함수 반환
return {
close: () => {
clearInterval(interval);
console.log('[MOCK] Mock 연결 종료');
}
};
}
```
### 방법 2: 환경 변수로 전환
```javascript
// 환경 변수로 Mock/Real 모드 전환
const USE_MOCK_AI = process.env.REACT_APP_USE_MOCK_AI === 'true';
function connectAISuggestions(meetingId) {
if (USE_MOCK_AI) {
console.log('[MOCK] Mock 모드로 실행');
return connectMockAISuggestions(meetingId);
} else {
console.log('[REAL] 실제 AI 서비스 연결');
return connectRealAISuggestions(meetingId);
}
}
function connectRealAISuggestions(meetingId) {
const url = `http://localhost:8086/api/v1/ai/suggestions/meetings/${meetingId}/stream`;
const eventSource = new EventSource(url);
eventSource.addEventListener('ai-suggestion', handleAISuggestion);
eventSource.onerror = (error) => {
console.error('[REAL] SSE 연결 오류:', error);
eventSource.close();
};
return eventSource;
}
// 공통 핸들러
function handleAISuggestion(event) {
const data = JSON.parse(event.data);
data.suggestions.forEach(suggestion => {
addSuggestionToUI(suggestion);
});
}
```
---
## 🔧 개발 환경 설정
### `.env.local` 파일
```env
# Mock 모드 사용 (개발 중)
REACT_APP_USE_MOCK_AI=true
# 실제 AI 서비스 URL (STT 완료 후)
REACT_APP_AI_SERVICE_URL=http://localhost:8086
```
### `package.json` 스크립트
```json
{
"scripts": {
"start": "REACT_APP_USE_MOCK_AI=true react-scripts start",
"start:real": "REACT_APP_USE_MOCK_AI=false react-scripts start",
"build": "REACT_APP_USE_MOCK_AI=false react-scripts build"
}
}
```
---
## 🎨 React 전체 예시
```typescript
import { useEffect, useState, useRef } from 'react';
interface Suggestion {
id: string;
content: string;
timestamp: string;
confidence: number;
}
interface MockConnection {
close: () => void;
}
function useMockAISuggestions(meetingId: string) {
const [suggestions, setSuggestions] = useState<Suggestion[]>([]);
const [connected, setConnected] = useState(false);
const connectionRef = useRef<MockConnection | null>(null);
useEffect(() => {
const mockSuggestions: Suggestion[] = [
{
id: crypto.randomUUID(),
content: "신제품의 타겟 고객층을 20-30대로 설정하고...",
timestamp: "00:05:23",
confidence: 0.92
},
// ... 더 많은 Mock 데이터
];
let index = 0;
setConnected(true);
const interval = setInterval(() => {
if (index < mockSuggestions.length) {
setSuggestions(prev => [mockSuggestions[index], ...prev]);
index++;
} else {
clearInterval(interval);
}
}, 5000);
connectionRef.current = {
close: () => {
clearInterval(interval);
setConnected(false);
}
};
return () => {
connectionRef.current?.close();
};
}, [meetingId]);
return { suggestions, connected };
}
function AISuggestionsPanel({ meetingId }: { meetingId: string }) {
const USE_MOCK = process.env.REACT_APP_USE_MOCK_AI === 'true';
const mockData = useMockAISuggestions(meetingId);
const realData = useRealAISuggestions(meetingId); // 실제 SSE 연결
const { suggestions, connected } = USE_MOCK ? mockData : realData;
return (
<div className="ai-panel">
<div className="header">
<h3>AI 제안사항</h3>
<span className={`badge ${connected ? 'connected' : 'disconnected'}`}>
{connected ? (USE_MOCK ? 'Mock 모드' : '연결됨') : '연결 끊김'}
</span>
</div>
<div className="suggestions">
{suggestions.map(s => (
<SuggestionCard key={s.id} suggestion={s} />
))}
</div>
</div>
);
}
```
---
## 🧪 테스트 시나리오
### 1. Mock 모드 테스트
```bash
# Mock 모드로 실행
REACT_APP_USE_MOCK_AI=true npm start
```
**확인 사항**:
- [ ] 5초마다 제안사항이 추가됨
- [ ] 총 5개의 제안사항이 표시됨
- [ ] 타임스탬프, 신뢰도가 정상 표시됨
- [ ] "추가" 버튼 클릭 시 회의록에 추가됨
- [ ] "무시" 버튼 클릭 시 제안사항이 제거됨
### 2. 실제 모드 테스트 (STT 완료 후)
```bash
# AI 서비스 시작
cd ai-python && ./start.sh
# 실제 모드로 실행
REACT_APP_USE_MOCK_AI=false npm start
```
**확인 사항**:
- [ ] SSE 연결이 정상적으로 됨
- [ ] 실제 AI 제안사항이 수신됨
- [ ] 회의 진행에 따라 동적으로 제안사항 생성됨
---
## 📊 Mock vs Real 비교
| 항목 | Mock 모드 | Real 모드 |
|------|----------|----------|
| **백엔드 필요** | 불필요 | 필요 (AI 서비스) |
| **제안 타이밍** | 5초 고정 간격 | 회의 진행에 따라 동적 |
| **제안 개수** | 5개 고정 | 무제한 (회의 종료까지) |
| **데이터 품질** | 하드코딩 샘플 | Claude AI 실제 분석 |
| **네트워크 필요** | 불필요 | 필요 |
| **개발 속도** | 빠름 | 느림 (백엔드 의존) |
---
## ⚠️ 주의사항
### 1. Mock 데이터 관리
```javascript
// ❌ 나쁜 예: 컴포넌트 내부에 하드코딩
function Component() {
const mockData = [/* ... */]; // 재사용 불가
}
// ✅ 좋은 예: 별도 파일로 분리
// src/mocks/aiSuggestions.ts
export const MOCK_AI_SUGGESTIONS = [/* ... */];
```
### 2. 환경 변수 누락 방지
```javascript
// ❌ 나쁜 예: 하드코딩
const USE_MOCK = true;
// ✅ 좋은 예: 환경 변수 + 기본값
const USE_MOCK = process.env.REACT_APP_USE_MOCK_AI !== 'false';
```
### 3. 프로덕션 빌드 시 Mock 제거
```javascript
// ❌ 나쁜 예: 프로덕션에도 Mock 코드 포함
if (USE_MOCK) { /* mock logic */ }
// ✅ 좋은 예: Tree-shaking 가능하도록 작성
if (process.env.NODE_ENV !== 'production' && USE_MOCK) {
/* mock logic */
}
```
---
## 🚀 다음 단계
### Phase 1: Mock으로 UI 개발 (현재)
- ✅ Mock 데이터 함수 구현
- ✅ UI 컴포넌트 개발
- ✅ 사용자 인터랙션 구현
### Phase 2: STT 연동 대기 (진행 중)
- 🔄 Backend에서 STT 개발 중
- 🔄 Event Hub 연동 개발 중
### Phase 3: 실제 연동 (STT 완료 후)
- [ ] Mock → Real 모드 전환
- [ ] 통합 테스트
- [ ] 성능 최적화
---
## 📞 문의
**Mock 데이터 관련**: 프론트엔드팀 (유진)
**STT 개발 현황**: 백엔드팀 (준호)
**AI 서비스**: AI팀 (서연)
---
**최종 업데이트**: 2025-10-27