mirror of
https://github.com/hwanny1128/HGZero.git
synced 2025-12-06 18:26:23 +00:00
- AI 서비스 CORS 설정 업데이트 - 회의 진행 프로토타입 수정 - 빌드 리포트 및 로그 파일 업데이트 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
341 lines
7.3 KiB
Markdown
341 lines
7.3 KiB
Markdown
# AI 제안사항 프론트엔드 연동 가이드 (간소화 버전)
|
|
|
|
## 📋 **개요**
|
|
|
|
백엔드를 간소화하여 **논의사항과 결정사항을 구분하지 않고**, 단일 "AI 제안사항" 배열로 통합 제공합니다.
|
|
|
|
---
|
|
|
|
## 🔄 **변경 사항 요약**
|
|
|
|
### **Before (구분)**
|
|
```json
|
|
{
|
|
"discussionTopics": [
|
|
{ "topic": "보안 요구사항 검토", ... }
|
|
],
|
|
"decisions": [
|
|
{ "content": "React로 개발", ... }
|
|
]
|
|
}
|
|
```
|
|
|
|
### **After (통합)** ✅
|
|
```json
|
|
{
|
|
"suggestions": [
|
|
{
|
|
"id": "sugg-001",
|
|
"content": "신제품의 타겟 고객층을 20-30대로 설정하고...",
|
|
"timestamp": "00:05:23",
|
|
"confidence": 0.92
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 🎨 **프론트엔드 통합 방법**
|
|
|
|
### **1. 05-회의진행.html에 스크립트 추가**
|
|
|
|
기존 `</body>` 태그 직전에 추가:
|
|
|
|
```html
|
|
<!-- AI 제안사항 SSE 연동 -->
|
|
<script src="ai-suggestion-integration.js"></script>
|
|
</body>
|
|
</html>
|
|
```
|
|
|
|
### **2. 전체 플로우**
|
|
|
|
```
|
|
[페이지 로드]
|
|
↓
|
|
SSE 연결
|
|
↓
|
|
[회의 진행 중]
|
|
↓
|
|
AI 분석 완료 시마다
|
|
SSE로 제안사항 전송
|
|
↓
|
|
자동으로 카드 생성
|
|
↓
|
|
[회의 종료]
|
|
↓
|
|
SSE 연결 종료
|
|
```
|
|
|
|
---
|
|
|
|
## 📡 **SSE API 명세**
|
|
|
|
### **엔드포인트**
|
|
```
|
|
GET /api/suggestions/meetings/{meetingId}/stream
|
|
```
|
|
|
|
### **헤더**
|
|
```
|
|
Accept: text/event-stream
|
|
```
|
|
|
|
### **응답 형식**
|
|
```
|
|
event: ai-suggestion
|
|
id: 12345
|
|
data: {"suggestions":[{"id":"sugg-001","content":"...","timestamp":"00:05:23","confidence":0.92}]}
|
|
|
|
event: ai-suggestion
|
|
id: 12346
|
|
data: {"suggestions":[{"id":"sugg-002","content":"...","timestamp":"00:08:45","confidence":0.88}]}
|
|
```
|
|
|
|
---
|
|
|
|
## 🧪 **테스트 방법**
|
|
|
|
### **1. 로컬 테스트 (Mock 데이터)**
|
|
|
|
백엔드가 아직 없어도 테스트 가능:
|
|
|
|
```javascript
|
|
// 테스트용 Mock 데이터 전송
|
|
function testAiSuggestion() {
|
|
const mockSuggestion = {
|
|
suggestions: [
|
|
{
|
|
id: "test-001",
|
|
content: "테스트 제안사항입니다. 이것은 AI가 생성한 제안입니다.",
|
|
timestamp: "00:05:23",
|
|
confidence: 0.95
|
|
}
|
|
]
|
|
};
|
|
|
|
handleAiSuggestions(mockSuggestion);
|
|
}
|
|
|
|
// 콘솔에서 실행
|
|
testAiSuggestion();
|
|
```
|
|
|
|
### **2. curl로 SSE 연결 테스트**
|
|
|
|
```bash
|
|
curl -N -H "Accept: text/event-stream" \
|
|
"http://localhost:8083/api/suggestions/meetings/test-meeting-001/stream"
|
|
```
|
|
|
|
예상 출력:
|
|
```
|
|
event: ai-suggestion
|
|
data: {"suggestions":[...]}
|
|
```
|
|
|
|
### **3. 브라우저 DevTools로 확인**
|
|
|
|
1. **Network 탭** → "EventStream" 필터
|
|
2. `/stream` 엔드포인트 클릭
|
|
3. **Messages** 탭에서 실시간 데이터 확인
|
|
|
|
---
|
|
|
|
## 💻 **JavaScript API 사용법**
|
|
|
|
### **초기화**
|
|
```javascript
|
|
// 자동으로 실행됨 (페이지 로드 시)
|
|
initializeAiSuggestions();
|
|
```
|
|
|
|
### **수동 연결 종료**
|
|
```javascript
|
|
closeAiSuggestions();
|
|
```
|
|
|
|
### **제안사항 수동 추가 (테스트용)**
|
|
```javascript
|
|
addSuggestionCard({
|
|
id: "manual-001",
|
|
content: "수동으로 추가한 제안사항",
|
|
timestamp: "00:10:00",
|
|
confidence: 0.9
|
|
});
|
|
```
|
|
|
|
---
|
|
|
|
## 🎨 **UI 커스터마이징**
|
|
|
|
### **신뢰도 표시 스타일**
|
|
|
|
```css
|
|
/* 05-회의진행.html의 <style> 태그에 추가 */
|
|
.ai-suggestion-confidence {
|
|
margin-top: 8px;
|
|
padding-top: 8px;
|
|
border-top: 1px dashed #E0E0E0;
|
|
}
|
|
|
|
.ai-suggestion-confidence span {
|
|
font-size: 11px;
|
|
color: var(--gray-500);
|
|
}
|
|
```
|
|
|
|
### **신뢰도에 따른 색상 변경**
|
|
|
|
```javascript
|
|
function getConfidenceColor(confidence) {
|
|
if (confidence >= 0.9) return '#4CAF50'; // 녹색 (높음)
|
|
if (confidence >= 0.7) return '#FFC107'; // 노란색 (중간)
|
|
return '#FF9800'; // 주황색 (낮음)
|
|
}
|
|
|
|
// 카드에 적용
|
|
card.innerHTML = `
|
|
...
|
|
<div class="ai-suggestion-confidence">
|
|
<span style="color: ${getConfidenceColor(suggestion.confidence)};">
|
|
신뢰도: ${Math.round(suggestion.confidence * 100)}%
|
|
</span>
|
|
</div>
|
|
`;
|
|
```
|
|
|
|
---
|
|
|
|
## 🔧 **트러블슈팅**
|
|
|
|
### **문제 1: SSE 연결이 안 됨**
|
|
|
|
**증상**:
|
|
```
|
|
EventSource's response has a MIME type ("application/json") that is not "text/event-stream"
|
|
```
|
|
|
|
**해결**:
|
|
- 백엔드에서 `produces = MediaType.TEXT_EVENT_STREAM_VALUE` 확인
|
|
- SuggestionController.java:111 라인 확인
|
|
|
|
### **문제 2: CORS 오류**
|
|
|
|
**증상**:
|
|
```
|
|
Access to XMLHttpRequest has been blocked by CORS policy
|
|
```
|
|
|
|
**해결**:
|
|
```java
|
|
// SecurityConfig.java에 추가
|
|
@Bean
|
|
public CorsConfigurationSource corsConfigurationSource() {
|
|
CorsConfiguration configuration = new CorsConfiguration();
|
|
configuration.setAllowedOrigins(Arrays.asList("http://localhost:*"));
|
|
configuration.setAllowedMethods(Arrays.asList("GET", "POST"));
|
|
configuration.setAllowedHeaders(Arrays.asList("*"));
|
|
|
|
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
|
|
source.registerCorsConfiguration("/api/**", configuration);
|
|
return source;
|
|
}
|
|
```
|
|
|
|
### **문제 3: 제안사항이 화면에 안 나타남**
|
|
|
|
**체크리스트**:
|
|
1. `aiSuggestionList` ID가 HTML에 있는지 확인
|
|
2. 브라우저 콘솔에 에러가 없는지 확인
|
|
3. Network 탭에서 SSE 데이터가 오는지 확인
|
|
4. `handleAiSuggestions` 함수에 `console.log` 추가하여 디버깅
|
|
|
|
---
|
|
|
|
## 📊 **성능 최적화**
|
|
|
|
### **제안사항 개수 제한**
|
|
|
|
너무 많은 카드가 쌓이면 성능 저하:
|
|
|
|
```javascript
|
|
function addSuggestionCard(suggestion) {
|
|
// 카드 추가 로직...
|
|
|
|
// 최대 20개까지만 유지
|
|
const listElement = document.getElementById('aiSuggestionList');
|
|
const cards = listElement.querySelectorAll('.ai-suggestion-card');
|
|
if (cards.length > 20) {
|
|
cards[cards.length - 1].remove(); // 가장 오래된 카드 삭제
|
|
}
|
|
}
|
|
```
|
|
|
|
### **중복 제안사항 필터링**
|
|
|
|
```javascript
|
|
const shownSuggestionIds = new Set();
|
|
|
|
function addSuggestionCard(suggestion) {
|
|
// 이미 표시된 제안사항은 무시
|
|
if (shownSuggestionIds.has(suggestion.id)) {
|
|
console.log('중복 제안사항 무시:', suggestion.id);
|
|
return;
|
|
}
|
|
|
|
shownSuggestionIds.add(suggestion.id);
|
|
|
|
// 카드 추가 로직...
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 🚀 **다음 단계**
|
|
|
|
1. ✅ **SimpleSuggestionDto 생성 완료**
|
|
2. ✅ **RealtimeSuggestionsDto 수정 완료**
|
|
3. ✅ **ClaudeApiClient 프롬프트 간소화 완료**
|
|
4. ✅ **SuggestionService 로직 수정 완료**
|
|
5. ✅ **프론트엔드 연동 코드 작성 완료**
|
|
|
|
### **실제 테스트 준비**
|
|
|
|
1. **백엔드 서버 시작**
|
|
```bash
|
|
cd ai
|
|
./gradlew bootRun
|
|
```
|
|
|
|
2. **프론트엔드 파일 열기**
|
|
```
|
|
design/uiux/prototype/05-회의진행.html
|
|
```
|
|
|
|
3. **브라우저 DevTools 열고 Network 탭 확인**
|
|
|
|
4. **SSE 연결 확인**
|
|
- EventStream 필터 활성화
|
|
- `/stream` 엔드포인트 확인
|
|
|
|
---
|
|
|
|
## 📝 **완료 체크리스트**
|
|
|
|
- [x] SimpleSuggestionDto 생성
|
|
- [x] RealtimeSuggestionsDto 수정
|
|
- [x] ClaudeApiClient 프롬프트 간소화
|
|
- [x] SuggestionService Mock 데이터 수정
|
|
- [x] 프론트엔드 연동 JavaScript 작성
|
|
- [ ] 05-회의진행.html에 스크립트 추가
|
|
- [ ] 로컬 환경에서 테스트
|
|
- [ ] Claude API 실제 연동 테스트
|
|
|
|
---
|
|
|
|
**🎉 간소화 작업 완료!**
|
|
|
|
이제 프론트엔드와 백엔드가 일치합니다. 05-회의진행.html에 스크립트만 추가하면 바로 사용 가능합니다.
|