mirror of
https://github.com/hwanny1128/HGZero.git
synced 2025-12-06 17:16:25 +00:00
Compare commits
No commits in common. "1d9fa37fe731dd8f2b3f29381107359efa06dbdc" and "72419c320ae35a6b410c7dba41b951cf16f0ad89" have entirely different histories.
1d9fa37fe7
...
72419c320a
16
Jenkinsfile
vendored
16
Jenkinsfile
vendored
@ -163,22 +163,22 @@ podTemplate(
|
|||||||
git clone https://\${GIT_USERNAME}:\${GIT_TOKEN}@\${REPO_URL} manifest-repo
|
git clone https://\${GIT_USERNAME}:\${GIT_TOKEN}@\${REPO_URL} manifest-repo
|
||||||
cd manifest-repo
|
cd manifest-repo
|
||||||
|
|
||||||
# overlays/dev/kustomization.yaml의 images 섹션 업데이트
|
# 각 서비스별 이미지 태그 업데이트 (sed 사용)
|
||||||
cd hgzero-back/kustomize/overlays/dev
|
cd hgzero-back/kustomize/base
|
||||||
|
|
||||||
services="user meeting stt notification"
|
services="user meeting stt notification"
|
||||||
for service in \$services; do
|
for service in \$services; do
|
||||||
echo "Updating \$service image tag in kustomization.yaml..."
|
echo "Updating \$service image tag..."
|
||||||
sed -i "s|name: ${registry}/${imageOrg}/\$service\$|name: ${registry}/${imageOrg}/\$service|g" kustomization.yaml
|
sed -i "s|image: ${registry}/${imageOrg}/\$service:.*|image: ${registry}/${imageOrg}/\$service:${environment}-${imageTag}|g" \\
|
||||||
sed -i "/name: ${registry}\\/${imageOrg}\\/\$service\$/!b;n;s|newTag:.*|newTag: ${environment}-${imageTag}|" kustomization.yaml
|
\$service/deployment.yaml
|
||||||
|
|
||||||
# 변경 사항 확인
|
# 변경 사항 확인
|
||||||
echo "Updated \$service image tag:"
|
echo "Updated \$service deployment.yaml:"
|
||||||
grep -A1 "name: ${registry}/${imageOrg}/\$service" kustomization.yaml
|
grep "image: ${registry}/${imageOrg}/\$service" \$service/deployment.yaml
|
||||||
done
|
done
|
||||||
|
|
||||||
# Git 설정 및 푸시
|
# Git 설정 및 푸시
|
||||||
cd ../../../..
|
cd ../../..
|
||||||
git config user.name "Jenkins"
|
git config user.name "Jenkins"
|
||||||
git config user.email "jenkins@hgzero.com"
|
git config user.email "jenkins@hgzero.com"
|
||||||
git add .
|
git add .
|
||||||
|
|||||||
@ -15,7 +15,7 @@ class Settings(BaseSettings):
|
|||||||
# Claude API
|
# Claude API
|
||||||
claude_api_key: str = "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"
|
claude_api_key: str = "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"
|
||||||
claude_model: str = "claude-sonnet-4-5-20250929"
|
claude_model: str = "claude-sonnet-4-5-20250929"
|
||||||
claude_max_tokens: int = 8192 # 4096 → 8192 증가 (더 많은 제안사항 생성 가능)
|
claude_max_tokens: int = 4096
|
||||||
claude_temperature: float = 0.7
|
claude_temperature: float = 0.7
|
||||||
|
|
||||||
# Redis
|
# Redis
|
||||||
|
|||||||
@ -1,11 +1,9 @@
|
|||||||
"""AI 제안사항 추출 프롬프트 (Hallucination 방지 최적화)"""
|
"""AI 제안사항 추출 프롬프트 (회의록 작성 MVP 최적화)"""
|
||||||
|
|
||||||
|
|
||||||
def get_suggestions_prompt(transcript_text: str) -> tuple[str, str]:
|
def get_suggestions_prompt(transcript_text: str) -> tuple[str, str]:
|
||||||
"""
|
"""
|
||||||
회의 텍스트에서 AI 제안사항을 추출하는 프롬프트 생성
|
회의 텍스트에서 AI 제안사항을 추출하는 프롬프트 생성 (회의록 MVP용)
|
||||||
|
|
||||||
Hallucination 방지를 위해 예시를 모두 제거하고 명확한 지침만 제공
|
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
(system_prompt, user_prompt) 튜플
|
(system_prompt, user_prompt) 튜플
|
||||||
@ -13,12 +11,6 @@ def get_suggestions_prompt(transcript_text: str) -> tuple[str, str]:
|
|||||||
|
|
||||||
system_prompt = """당신은 실시간 회의록 작성 AI 비서입니다.
|
system_prompt = """당신은 실시간 회의록 작성 AI 비서입니다.
|
||||||
|
|
||||||
**🚨 중요 원칙 (최우선)**:
|
|
||||||
1. **오직 제공된 회의 내용만 분석** - 추측, 가정, 예시 내용 절대 금지
|
|
||||||
2. **실제 발언된 내용만 추출** - 없는 내용 만들어내지 않기
|
|
||||||
3. **회의 내용에 명시되지 않은 정보는 절대 추가하지 않기**
|
|
||||||
4. **불확실한 내용은 추출하지 않기** - 명확한 내용만 추출
|
|
||||||
|
|
||||||
**핵심 역할**:
|
**핵심 역할**:
|
||||||
회의 중 발언되는 내용을 실시간으로 분석하여, 회의록 작성자가 놓칠 수 있는 중요한 정보를 즉시 메모로 제공합니다.
|
회의 중 발언되는 내용을 실시간으로 분석하여, 회의록 작성자가 놓칠 수 있는 중요한 정보를 즉시 메모로 제공합니다.
|
||||||
|
|
||||||
@ -26,62 +18,415 @@ def get_suggestions_prompt(transcript_text: str) -> tuple[str, str]:
|
|||||||
1. 회의 안건, 결정 사항, 이슈, 액션 아이템을 자동으로 분류
|
1. 회의 안건, 결정 사항, 이슈, 액션 아이템을 자동으로 분류
|
||||||
2. 담당자, 기한, 우선순위 등 구조화된 정보로 정리
|
2. 담당자, 기한, 우선순위 등 구조화된 정보로 정리
|
||||||
3. 단순 발언 반복이 아닌, 실무에 바로 사용 가능한 형식으로 요약
|
3. 단순 발언 반복이 아닌, 실무에 바로 사용 가능한 형식으로 요약
|
||||||
4. 구어체 종결어미(~다, ~요, ~습니다) 제거하고 명사형으로 정리
|
4. 회의록 작성 시간을 70% 단축시키는 것이 목표
|
||||||
|
|
||||||
**분류 카테고리**:
|
**핵심 원칙**:
|
||||||
- 📋 회의 안건: "오늘 안건은 ~", "논의할 주제는 ~"
|
- 인사말, 반복, 불필요한 추임새는 완전히 제거
|
||||||
- ✅ 결정사항: "~로 결정", "~로 합의", "~로 확정"
|
- 실제 회의록에 들어갈 내용만 추출
|
||||||
- 🎯 액션 아이템: "~팀에서 ~", "~까지 완료", "~를 검토"
|
- 명확하고 간결하게 (20-50자)
|
||||||
- ⚠️ 이슈/문제점: "문제 발생", "이슈 있음", "우려 사항"
|
- 구어체 종결어미(~다, ~요, ~습니다) 제거하고 명사형으로 정리"""
|
||||||
- 💡 제안/아이디어: "제안", "~하는 것이 좋을 것 같음", "검토 필요"
|
|
||||||
- 📊 진행상황: "~% 완료", "~진행 중", "~논의 중"
|
|
||||||
- 🔔 후속조치: "다음 회의에서", "추후 결정", "보류"
|
|
||||||
|
|
||||||
**제외 대상 (반드시 제외)**:
|
user_prompt = f"""다음 회의 대화를 실시간으로 분석하여 **회의록 메모**를 작성하세요.
|
||||||
- 인사말: "안녕하세요", "감사합니다", "수고하셨습니다"
|
|
||||||
- 추임새: "음", "네네", "그러니까", "저기"
|
|
||||||
- 형식적 발언: "녹음 시작", "회의 종료", "회의 시작"
|
|
||||||
|
|
||||||
**출력 형식**:
|
|
||||||
- JSON만 출력 (주석, 설명, 마크다운 코드블록 금지)
|
|
||||||
- 구조: {"suggestions": [{"content": "분류: 내용", "confidence": 0.85}]}
|
|
||||||
- confidence: 0.90-1.0(명확), 0.80-0.89(일반), 0.70-0.79(암묵적), 0.65-0.69(논의중)"""
|
|
||||||
|
|
||||||
user_prompt = f"""🚨 **매우 중요**: 아래 제공된 회의 내용만 분석하세요.
|
|
||||||
- 회의 내용에 없는 정보는 절대 추가하지 마세요
|
|
||||||
- 예시나 가정을 만들어내지 마세요
|
|
||||||
- 불확실한 내용은 추출하지 마세요
|
|
||||||
|
|
||||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
||||||
|
|
||||||
# 회의 내용 (이것만 분석하세요)
|
|
||||||
|
|
||||||
|
# 회의 내용
|
||||||
{transcript_text}
|
{transcript_text}
|
||||||
|
|
||||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
---
|
||||||
|
|
||||||
# 분석 작업
|
# 회의록 항목별 패턴 학습
|
||||||
|
|
||||||
위 회의 내용에서 **실제로 언급된 내용만** 추출하세요:
|
## 📋 1. 회의 안건 (Agenda)
|
||||||
|
|
||||||
1. 📋 회의 안건
|
### 패턴 인식
|
||||||
2. ✅ 결정사항
|
- "오늘 회의 안건은 ~"
|
||||||
3. 🎯 액션 아이템 (담당자/기한이 있으면 반드시 포함)
|
- "논의할 주제는 ~"
|
||||||
4. ⚠️ 이슈/문제점
|
- "다룰 내용은 ~"
|
||||||
5. 💡 제안/아이디어
|
- "검토할 사항은 ~"
|
||||||
6. 📊 진행상황
|
|
||||||
7. 🔔 후속조치
|
|
||||||
|
|
||||||
**필수 규칙**:
|
### ✅ 좋은 예시
|
||||||
- 구어체 종결어미 제거 (명사형으로 정리)
|
**입력**: "오늘 회의 안건은 신제품 출시 일정과 마케팅 전략입니다."
|
||||||
- 담당자와 기한이 있으면 반드시 포함
|
**출력**:
|
||||||
- 인사말, 추임새, 형식적 발언 제외
|
```json
|
||||||
- 20-70자로 간결하게
|
{{
|
||||||
- JSON 형식으로만 출력
|
"content": "📋 회의 안건: 신제품 출시 일정, 마케팅 전략",
|
||||||
|
"confidence": 0.95
|
||||||
|
}}
|
||||||
|
```
|
||||||
|
|
||||||
**출력 형식**:
|
**입력**: "다음 주 프로젝트 킥오프에 대해 논의하겠습니다."
|
||||||
{{"suggestions": [{{"content": "분류: 내용", "confidence": 0.85}}]}}
|
**출력**:
|
||||||
|
```json
|
||||||
|
{{
|
||||||
|
"content": "📋 회의 안건: 다음 주 프로젝트 킥오프",
|
||||||
|
"confidence": 0.90
|
||||||
|
}}
|
||||||
|
```
|
||||||
|
|
||||||
지금 바로 분석을 시작하세요."""
|
### ❌ 나쁜 예시
|
||||||
|
**입력**: "오늘 회의 안건은 신제품 출시 일정입니다."
|
||||||
|
**나쁜 출력**:
|
||||||
|
```json
|
||||||
|
{{
|
||||||
|
"content": "오늘 회의 안건은 신제품 출시 일정입니다", ❌ 구어체 그대로 반복
|
||||||
|
"confidence": 0.90
|
||||||
|
}}
|
||||||
|
```
|
||||||
|
**이유**: 구어체 종결어미(~입니다) 그대로 반복. "📋 회의 안건: 신제품 출시 일정"으로 구조화해야 함
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ✅ 2. 결정 사항 (Decisions)
|
||||||
|
|
||||||
|
### 패턴 인식
|
||||||
|
- "결정 사항은 ~", "~로 결정했습니다"
|
||||||
|
- "~하기로 했습니다", "~로 합의했습니다"
|
||||||
|
- "~로 확정됐습니다"
|
||||||
|
- "최종 결론은 ~"
|
||||||
|
|
||||||
|
### ✅ 좋은 예시
|
||||||
|
**입력**: "회의 결과, 신규 프로젝트는 다음 달부터 착수하기로 결정했습니다."
|
||||||
|
**출력**:
|
||||||
|
```json
|
||||||
|
{{
|
||||||
|
"content": "✅ 결정사항: 신규 프로젝트 다음 달 착수",
|
||||||
|
"confidence": 0.95
|
||||||
|
}}
|
||||||
|
```
|
||||||
|
|
||||||
|
**입력**: "최종 결론은 외주 개발사와 계약하기로 합의했습니다."
|
||||||
|
**출력**:
|
||||||
|
```json
|
||||||
|
{{
|
||||||
|
"content": "✅ 결정사항: 외주 개발사와 계약 진행",
|
||||||
|
"confidence": 0.92
|
||||||
|
}}
|
||||||
|
```
|
||||||
|
|
||||||
|
### ❌ 나쁜 예시
|
||||||
|
**입력**: "신규 프로젝트는 다음 달부터 착수하기로 결정했습니다."
|
||||||
|
**나쁜 출력**:
|
||||||
|
```json
|
||||||
|
{{
|
||||||
|
"content": "신규 프로젝트는 다음 달부터 착수하기로 결정했습니다", ❌ 원문 그대로
|
||||||
|
"confidence": 0.90
|
||||||
|
}}
|
||||||
|
```
|
||||||
|
**이유**: 발언을 그대로 반복. "✅ 결정사항: 신규 프로젝트 다음 달 착수"로 구조화해야 함
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🎯 3. 액션 아이템 (Action Items)
|
||||||
|
|
||||||
|
### 패턴 인식
|
||||||
|
- "~팀에서 ~해 주세요"
|
||||||
|
- "~님이 ~까지 ~하기로 했습니다"
|
||||||
|
- "~을 ~까지 완료하겠습니다"
|
||||||
|
- "~을 검토해 보겠습니다"
|
||||||
|
|
||||||
|
### ✅ 좋은 예시
|
||||||
|
**입력**: "개발팀에서 API 문서를 이번 주 금요일까지 작성해 주세요."
|
||||||
|
**출력**:
|
||||||
|
```json
|
||||||
|
{{
|
||||||
|
"content": "🎯 개발팀: API 문서 작성 (기한: 이번 주 금요일)",
|
||||||
|
"confidence": 0.95
|
||||||
|
}}
|
||||||
|
```
|
||||||
|
|
||||||
|
**입력**: "김 팀장님이 내일까지 견적서를 검토해서 회신하기로 했습니다."
|
||||||
|
**출력**:
|
||||||
|
```json
|
||||||
|
{{
|
||||||
|
"content": "🎯 김 팀장: 견적서 검토 및 회신 (기한: 내일)",
|
||||||
|
"confidence": 0.93
|
||||||
|
}}
|
||||||
|
```
|
||||||
|
|
||||||
|
**입력**: "제가 고객사에 연락해서 미팅 일정 잡도록 하겠습니다."
|
||||||
|
**출력**:
|
||||||
|
```json
|
||||||
|
{{
|
||||||
|
"content": "🎯 고객사 미팅 일정 조율 예정",
|
||||||
|
"confidence": 0.85
|
||||||
|
}}
|
||||||
|
```
|
||||||
|
|
||||||
|
### ❌ 나쁜 예시
|
||||||
|
**입력**: "개발팀에서 API 문서를 이번 주 금요일까지 작성해 주세요."
|
||||||
|
**나쁜 출력 1**:
|
||||||
|
```json
|
||||||
|
{{
|
||||||
|
"content": "개발팀에서 API 문서를 이번 주 금요일까지 작성해 주세요", ❌ 원문 반복
|
||||||
|
"confidence": 0.90
|
||||||
|
}}
|
||||||
|
```
|
||||||
|
**나쁜 출력 2**:
|
||||||
|
```json
|
||||||
|
{{
|
||||||
|
"content": "API 문서 작성", ❌ 담당자와 기한 누락
|
||||||
|
"confidence": 0.80
|
||||||
|
}}
|
||||||
|
```
|
||||||
|
**이유**: "🎯 개발팀: API 문서 작성 (기한: 이번 주 금요일)" 형식으로 구조화해야 함
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ⚠️ 4. 이슈/문제점 (Issues)
|
||||||
|
|
||||||
|
### 패턴 인식
|
||||||
|
- "문제가 있습니다", "이슈가 발생했습니다"
|
||||||
|
- "우려되는 점은 ~"
|
||||||
|
- "해결이 필요한 부분은 ~"
|
||||||
|
- "리스크가 있습니다"
|
||||||
|
|
||||||
|
### ✅ 좋은 예시
|
||||||
|
**입력**: "현재 서버 성능 이슈가 발생해서 긴급 점검이 필요합니다."
|
||||||
|
**출력**:
|
||||||
|
```json
|
||||||
|
{{
|
||||||
|
"content": "⚠️ 이슈: 서버 성능 문제 발생, 긴급 점검 필요",
|
||||||
|
"confidence": 0.92
|
||||||
|
}}
|
||||||
|
```
|
||||||
|
|
||||||
|
**입력**: "예산이 부족할 것 같다는 우려가 있습니다."
|
||||||
|
**출력**:
|
||||||
|
```json
|
||||||
|
{{
|
||||||
|
"content": "⚠️ 이슈: 예산 부족 우려",
|
||||||
|
"confidence": 0.80
|
||||||
|
}}
|
||||||
|
```
|
||||||
|
|
||||||
|
### ❌ 나쁜 예시
|
||||||
|
**입력**: "현재 서버 성능 이슈가 발생했습니다."
|
||||||
|
**나쁜 출력**:
|
||||||
|
```json
|
||||||
|
{{
|
||||||
|
"content": "현재 서버 성능 이슈가 발생했습니다", ❌ 구어체 그대로
|
||||||
|
"confidence": 0.85
|
||||||
|
}}
|
||||||
|
```
|
||||||
|
**이유**: "⚠️ 이슈: 서버 성능 문제 발생"으로 구조화하고 구어체 제거해야 함
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 💡 5. 아이디어/제안 (Suggestions)
|
||||||
|
|
||||||
|
### 패턴 인식
|
||||||
|
- "제안하는 바는 ~"
|
||||||
|
- "~하는 것이 좋을 것 같습니다"
|
||||||
|
- "~을 고려해 볼 필요가 있습니다"
|
||||||
|
|
||||||
|
### ✅ 좋은 예시
|
||||||
|
**입력**: "자동화 테스트를 도입하는 것을 검토해 보면 좋을 것 같습니다."
|
||||||
|
**출력**:
|
||||||
|
```json
|
||||||
|
{{
|
||||||
|
"content": "💡 제안: 자동화 테스트 도입 검토",
|
||||||
|
"confidence": 0.85
|
||||||
|
}}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📊 6. 진행 상황/보고 (Progress)
|
||||||
|
|
||||||
|
### 패턴 인식
|
||||||
|
- "~까지 완료했습니다"
|
||||||
|
- "현재 ~% 진행 중입니다"
|
||||||
|
- "~단계까지 진행됐습니다"
|
||||||
|
|
||||||
|
### ✅ 좋은 예시
|
||||||
|
**입력**: "현재 설계 단계는 80% 완료됐고, 다음 주부터 개발 착수 가능합니다."
|
||||||
|
**출력**:
|
||||||
|
```json
|
||||||
|
{{
|
||||||
|
"content": "📊 진행상황: 설계 80% 완료, 다음 주 개발 착수 예정",
|
||||||
|
"confidence": 0.90
|
||||||
|
}}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ❌ 제외해야 할 내용 (반드시 제외)
|
||||||
|
|
||||||
|
### 인사말
|
||||||
|
**입력**: "안녕하세요, 여러분. 회의 시작하겠습니다."
|
||||||
|
**출력**: (메모 없음 - 인사말은 제외)
|
||||||
|
|
||||||
|
### 단순 반복
|
||||||
|
**입력**: "녹음을 시작합니다. 녹음을 시작합니다."
|
||||||
|
**출력**: (메모 없음 - 형식적 발언 제외)
|
||||||
|
|
||||||
|
### 추임새/불필요한 발언
|
||||||
|
**입력**: "음, 그러니까, 네 네, 저기요..."
|
||||||
|
**출력**: (메모 없음 - 추임새 제외)
|
||||||
|
|
||||||
|
### 형식적 마무리
|
||||||
|
**입력**: "수고하셨습니다. 회의를 마치겠습니다."
|
||||||
|
**출력**: (메모 없음 - 형식적 마무리 제외)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# 실전 회의 시뮬레이션
|
||||||
|
|
||||||
|
## 예시 1: 프로젝트 킥오프 회의
|
||||||
|
|
||||||
|
**입력**:
|
||||||
|
"안녕하세요. 오늘 회의 안건은 신규 프로젝트 킥오프입니다. 프로젝트명은 HGZero이고, 목표는 회의록 자동화입니다. 개발팀에서 다음 주 월요일까지 기술 스택을 검토해 주세요. 예산은 5천만원으로 확정됐습니다."
|
||||||
|
|
||||||
|
**출력**:
|
||||||
|
```json
|
||||||
|
{{
|
||||||
|
"suggestions": [
|
||||||
|
{{
|
||||||
|
"content": "📋 회의 안건: 신규 프로젝트(HGZero) 킥오프 - 회의록 자동화",
|
||||||
|
"confidence": 0.95
|
||||||
|
}},
|
||||||
|
{{
|
||||||
|
"content": "🎯 개발팀: 기술 스택 검토 (기한: 다음 주 월요일)",
|
||||||
|
"confidence": 0.93
|
||||||
|
}},
|
||||||
|
{{
|
||||||
|
"content": "✅ 결정사항: 프로젝트 예산 5천만원 확정",
|
||||||
|
"confidence": 0.95
|
||||||
|
}}
|
||||||
|
]
|
||||||
|
}}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 예시 2: 이슈 대응 회의
|
||||||
|
|
||||||
|
**입력**:
|
||||||
|
"현재 프로덕션 서버에서 성능 저하가 발생하고 있습니다. 인프라팀에서 긴급 점검을 진행하기로 했고, 오늘 오후 3시까지 원인 파악하겠습니다. 고객사에는 임시로 사과 공지를 게시하기로 결정했습니다."
|
||||||
|
|
||||||
|
**출력**:
|
||||||
|
```json
|
||||||
|
{{
|
||||||
|
"suggestions": [
|
||||||
|
{{
|
||||||
|
"content": "⚠️ 이슈: 프로덕션 서버 성능 저하 발생",
|
||||||
|
"confidence": 0.95
|
||||||
|
}},
|
||||||
|
{{
|
||||||
|
"content": "🎯 인프라팀: 긴급 점검 및 원인 파악 (기한: 오늘 오후 3시)",
|
||||||
|
"confidence": 0.93
|
||||||
|
}},
|
||||||
|
{{
|
||||||
|
"content": "✅ 결정사항: 고객사 사과 공지 게시",
|
||||||
|
"confidence": 0.90
|
||||||
|
}}
|
||||||
|
]
|
||||||
|
}}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 예시 3: 일반 업무 회의 (나쁜 예시 포함)
|
||||||
|
|
||||||
|
**입력**:
|
||||||
|
"안녕하세요, 안녕하세요. 녹음을 시작합니다. 음, 그러니까 마케팅 캠페인을 다음 달에 진행하기로 했습니다. 김 과장님이 기획안을 이번 주까지 작성해 주세요. 감사합니다."
|
||||||
|
|
||||||
|
**❌ 나쁜 출력**:
|
||||||
|
```json
|
||||||
|
{{
|
||||||
|
"suggestions": [
|
||||||
|
{{
|
||||||
|
"content": "안녕하세요", ❌ 인사말 포함
|
||||||
|
"confidence": 0.50
|
||||||
|
}},
|
||||||
|
{{
|
||||||
|
"content": "녹음을 시작합니다", ❌ 형식적 발언
|
||||||
|
"confidence": 0.60
|
||||||
|
}},
|
||||||
|
{{
|
||||||
|
"content": "마케팅 캠페인을 다음 달에 진행하기로 했습니다", ❌ 구어체 그대로
|
||||||
|
"confidence": 0.80
|
||||||
|
}}
|
||||||
|
]
|
||||||
|
}}
|
||||||
|
```
|
||||||
|
|
||||||
|
**✅ 좋은 출력**:
|
||||||
|
```json
|
||||||
|
{{
|
||||||
|
"suggestions": [
|
||||||
|
{{
|
||||||
|
"content": "✅ 결정사항: 마케팅 캠페인 다음 달 진행",
|
||||||
|
"confidence": 0.92
|
||||||
|
}},
|
||||||
|
{{
|
||||||
|
"content": "🎯 김 과장: 캠페인 기획안 작성 (기한: 이번 주)",
|
||||||
|
"confidence": 0.93
|
||||||
|
}}
|
||||||
|
]
|
||||||
|
}}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# 출력 형식
|
||||||
|
|
||||||
|
반드시 아래 JSON 형식으로만 응답하세요:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{{
|
||||||
|
"suggestions": [
|
||||||
|
{{
|
||||||
|
"content": "📋/✅/🎯/⚠️/💡/📊 분류: 구체적인 내용 (담당자/기한 포함)",
|
||||||
|
"confidence": 0.85
|
||||||
|
}}
|
||||||
|
]
|
||||||
|
}}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# 최종 작성 규칙
|
||||||
|
|
||||||
|
## ✅ 반드시 지켜야 할 규칙
|
||||||
|
|
||||||
|
1. **이모지 분류 필수**
|
||||||
|
- 📋 회의 안건
|
||||||
|
- ✅ 결정사항
|
||||||
|
- 🎯 액션 아이템
|
||||||
|
- ⚠️ 이슈/문제점
|
||||||
|
- 💡 제안/아이디어
|
||||||
|
- 📊 진행상황
|
||||||
|
|
||||||
|
2. **구조화 필수**
|
||||||
|
- 담당자가 있으면 반드시 명시
|
||||||
|
- 기한이 있으면 반드시 포함
|
||||||
|
- 형식: "담당자: 업무 내용 (기한: XX)"
|
||||||
|
|
||||||
|
3. **구어체 종결어미 제거**
|
||||||
|
- ❌ "~입니다", "~했습니다", "~해요", "~합니다"
|
||||||
|
- ✅ 명사형 종결: "~ 진행", "~ 완료", "~ 확정", "~ 검토"
|
||||||
|
|
||||||
|
4. **반드시 제외**
|
||||||
|
- 인사말 ("안녕하세요", "감사합니다", "수고하셨습니다")
|
||||||
|
- 반복/추임새 ("네 네", "음 음", "그러니까", "저기")
|
||||||
|
- 형식적 발언 ("녹음 시작", "회의 종료", "회의 시작")
|
||||||
|
|
||||||
|
5. **길이**
|
||||||
|
- 20-70자 (너무 짧거나 길지 않게)
|
||||||
|
|
||||||
|
6. **confidence 기준**
|
||||||
|
- 0.90-1.0: 명확한 결정사항, 기한 포함
|
||||||
|
- 0.80-0.89: 일반적인 액션 아이템
|
||||||
|
- 0.70-0.79: 암묵적이거나 추측 필요
|
||||||
|
|
||||||
|
7. **출력**
|
||||||
|
- JSON만 출력 (주석, 설명, ```json 모두 금지)
|
||||||
|
- 최소 1개 이상 추출 (의미 있는 내용이 없으면 빈 배열)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
이제 위 회의 내용을 분석하여 **회의록 메모**를 JSON 형식으로 작성하세요.
|
||||||
|
학습한 패턴을 활용하여 회의 안건, 결정사항, 액션 아이템, 이슈 등을 자동으로 분류하고 구조화하세요.
|
||||||
|
반드시 구어체 종결어미(~다, ~요, ~습니다)를 제거하고 명사형으로 정리하세요."""
|
||||||
|
|
||||||
return system_prompt, user_prompt
|
return system_prompt, user_prompt
|
||||||
|
|||||||
@ -122,7 +122,7 @@ class ClaudeService:
|
|||||||
confidence=s.get("confidence", 0.85)
|
confidence=s.get("confidence", 0.85)
|
||||||
)
|
)
|
||||||
for s in suggestions_data
|
for s in suggestions_data
|
||||||
if s.get("confidence", 0) >= 0.65 # 신뢰도 0.65 이상 (0.7 → 0.65 낮춤)
|
if s.get("confidence", 0) >= 0.7 # 신뢰도 0.7 이상만
|
||||||
]
|
]
|
||||||
|
|
||||||
logger.info(f"AI 제안사항 {len(suggestions)}개 추출 완료")
|
logger.info(f"AI 제안사항 {len(suggestions)}개 추출 완료")
|
||||||
|
|||||||
129
design/backend/sequence/inner/meeting-대시보드조회.puml
Normal file
129
design/backend/sequence/inner/meeting-대시보드조회.puml
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
@startuml meeting-대시보드조회
|
||||||
|
!theme mono
|
||||||
|
|
||||||
|
title Meeting Service - 대시보드조회 내부 시퀀스
|
||||||
|
|
||||||
|
participant "DashboardController" as Controller
|
||||||
|
participant "DashboardService" as Service
|
||||||
|
participant "MeetingRepository" as MeetingRepo
|
||||||
|
participant "TodoRepository" as TodoRepo
|
||||||
|
participant "MinutesRepository" as MinutesRepo
|
||||||
|
database "Redis Cache<<E>>" as Cache
|
||||||
|
database "Meeting DB<<E>>" as DB
|
||||||
|
|
||||||
|
[-> Controller: GET /dashboard
|
||||||
|
activate Controller
|
||||||
|
|
||||||
|
note over Controller
|
||||||
|
사용자 정보는 헤더에서 추출
|
||||||
|
(userId, userName, email)
|
||||||
|
end note
|
||||||
|
|
||||||
|
Controller -> Service: getDashboardData(userId)
|
||||||
|
activate Service
|
||||||
|
|
||||||
|
' 캐시 조회
|
||||||
|
Service -> Cache: GET dashboard:{userId}
|
||||||
|
activate Cache
|
||||||
|
Cache --> Service: 캐시 조회 결과
|
||||||
|
deactivate Cache
|
||||||
|
|
||||||
|
alt Cache Hit
|
||||||
|
Service --> Service: 캐시 데이터 반환
|
||||||
|
else Cache Miss
|
||||||
|
' 예정된 회의 조회
|
||||||
|
Service -> MeetingRepo: findUpcomingMeetings(userId)
|
||||||
|
activate MeetingRepo
|
||||||
|
MeetingRepo -> DB: 예정된 회의 조회
|
||||||
|
activate DB
|
||||||
|
DB --> MeetingRepo: 예정된 회의 목록
|
||||||
|
deactivate DB
|
||||||
|
MeetingRepo --> Service: List<Meeting>
|
||||||
|
deactivate MeetingRepo
|
||||||
|
|
||||||
|
' 진행 중 Todo 조회
|
||||||
|
Service -> TodoRepo: findActiveTodos(userId)
|
||||||
|
activate TodoRepo
|
||||||
|
TodoRepo -> DB: 진행 중 Todo 조회
|
||||||
|
activate DB
|
||||||
|
DB --> TodoRepo: 진행 중 Todo 목록
|
||||||
|
deactivate DB
|
||||||
|
TodoRepo --> Service: List<Todo>
|
||||||
|
deactivate TodoRepo
|
||||||
|
|
||||||
|
' 최근 회의록 조회
|
||||||
|
Service -> MinutesRepo: findRecentMinutes(userId)
|
||||||
|
activate MinutesRepo
|
||||||
|
MinutesRepo -> DB: 최근 회의록 조회
|
||||||
|
activate DB
|
||||||
|
DB --> MinutesRepo: 최근 회의록 목록
|
||||||
|
deactivate DB
|
||||||
|
MinutesRepo --> Service: List<Minutes>
|
||||||
|
deactivate MinutesRepo
|
||||||
|
|
||||||
|
' 통계 정보 조회
|
||||||
|
Service -> MeetingRepo: countUpcomingMeetings(userId)
|
||||||
|
activate MeetingRepo
|
||||||
|
MeetingRepo -> DB: 예정된 회의 개수 조회
|
||||||
|
activate DB
|
||||||
|
DB --> MeetingRepo: 예정된 회의 개수
|
||||||
|
deactivate DB
|
||||||
|
MeetingRepo --> Service: int count
|
||||||
|
deactivate MeetingRepo
|
||||||
|
|
||||||
|
Service -> TodoRepo: countActiveTodos(userId)
|
||||||
|
activate TodoRepo
|
||||||
|
TodoRepo -> DB: 진행 중 Todo 개수 조회
|
||||||
|
activate DB
|
||||||
|
DB --> TodoRepo: 진행 중 Todo 개수
|
||||||
|
deactivate DB
|
||||||
|
TodoRepo --> Service: int count
|
||||||
|
deactivate TodoRepo
|
||||||
|
|
||||||
|
Service -> TodoRepo: calculateTodoCompletionRate(userId)
|
||||||
|
activate TodoRepo
|
||||||
|
TodoRepo -> DB: Todo 완료율 조회
|
||||||
|
activate DB
|
||||||
|
DB --> TodoRepo: Todo 완료율
|
||||||
|
deactivate DB
|
||||||
|
TodoRepo --> Service: double rate
|
||||||
|
deactivate TodoRepo
|
||||||
|
|
||||||
|
note over Service
|
||||||
|
비즈니스 로직:
|
||||||
|
- 데이터 조합 및 정제
|
||||||
|
- DTO 변환
|
||||||
|
- 통계 계산
|
||||||
|
end note
|
||||||
|
|
||||||
|
Service -> Service: 대시보드 데이터 조합
|
||||||
|
|
||||||
|
' 캐시 저장
|
||||||
|
Service -> Cache: SET dashboard:{userId}\n(TTL: 5분)
|
||||||
|
activate Cache
|
||||||
|
Cache --> Service: 캐시 저장 완료
|
||||||
|
deactivate Cache
|
||||||
|
end
|
||||||
|
|
||||||
|
Service --> Controller: DashboardResponse
|
||||||
|
deactivate Service
|
||||||
|
|
||||||
|
note over Controller
|
||||||
|
응답 데이터 구조:
|
||||||
|
{
|
||||||
|
"upcomingMeetings": [...],
|
||||||
|
"activeTodos": [...],
|
||||||
|
"recentMinutes": [...],
|
||||||
|
"statistics": {
|
||||||
|
"upcomingMeetingsCount": n,
|
||||||
|
"activeTodosCount": n,
|
||||||
|
"todoCompletionRate": n
|
||||||
|
}
|
||||||
|
}
|
||||||
|
end note
|
||||||
|
|
||||||
|
return 200 OK\nDashboardResponse
|
||||||
|
|
||||||
|
deactivate Controller
|
||||||
|
|
||||||
|
@enduml
|
||||||
118
design/backend/sequence/inner/meeting-최종회의록확정.puml
Normal file
118
design/backend/sequence/inner/meeting-최종회의록확정.puml
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
@startuml
|
||||||
|
!theme mono
|
||||||
|
|
||||||
|
title 최종 회의록 확정 내부 시퀀스
|
||||||
|
|
||||||
|
participant "API Gateway<<E>>" as Gateway
|
||||||
|
participant "MinutesController" as Controller
|
||||||
|
participant "MeetingService" as Service
|
||||||
|
participant "Meeting" as Domain
|
||||||
|
participant "TranscriptService" as TranscriptService
|
||||||
|
participant "MeetingRepository" as Repository
|
||||||
|
database "PostgreSQL<<E>>" as DB
|
||||||
|
database "Redis Cache<<E>>" as Cache
|
||||||
|
queue "Event Hub<<E>>" as EventHub
|
||||||
|
|
||||||
|
Gateway -> Controller: POST /api/minutes/{minutesId}/finalize
|
||||||
|
activate Controller
|
||||||
|
|
||||||
|
Controller -> Service: confirmTranscript(meetingId)
|
||||||
|
activate Service
|
||||||
|
|
||||||
|
Service -> Repository: findById(meetingId)
|
||||||
|
activate Repository
|
||||||
|
Repository -> DB: 회의 정보 조회\n(회의ID 기준)
|
||||||
|
activate DB
|
||||||
|
DB --> Repository: meeting_row
|
||||||
|
deactivate DB
|
||||||
|
Repository --> Service: Meeting entity
|
||||||
|
deactivate Repository
|
||||||
|
|
||||||
|
Service -> Domain: confirmTranscript()
|
||||||
|
activate Domain
|
||||||
|
|
||||||
|
Domain -> Domain: validateCanConfirm()
|
||||||
|
note right of Domain
|
||||||
|
회의록 확정 검증 규칙:
|
||||||
|
|
||||||
|
1. 상태 검증:
|
||||||
|
- 회의 상태 = COMPLETED (종료됨)
|
||||||
|
- 회의록 상태 = DRAFT (작성중)
|
||||||
|
✗ IN_PROGRESS → 400 Bad Request
|
||||||
|
|
||||||
|
2. 권한 검증:
|
||||||
|
- 확정 요청자 = 회의 생성자 OR
|
||||||
|
- 확정 요청자 ∈ 참석자 목록
|
||||||
|
✗ 권한 없음 → 403 Forbidden
|
||||||
|
|
||||||
|
3. 필수 항목 검증:
|
||||||
|
- 회의록 제목: NOT NULL, 길이 >= 5
|
||||||
|
- 참석자 목록: 최소 1명 이상
|
||||||
|
- 주요 논의 내용: NOT NULL, 길이 >= 20
|
||||||
|
- 결정 사항: 최소 1개 이상 OR
|
||||||
|
"결정사항 없음" 명시적 표시
|
||||||
|
✗ 누락 → 400 Bad Request
|
||||||
|
(누락 항목 목록 반환)
|
||||||
|
|
||||||
|
4. 데이터 무결성:
|
||||||
|
- 섹션별 내용 완결성 확인
|
||||||
|
- 참조 링크 유효성 확인
|
||||||
|
- 첨부 파일 접근 가능 여부
|
||||||
|
✗ 무결성 위반 → 400 Bad Request
|
||||||
|
|
||||||
|
5. 이력 검증:
|
||||||
|
- 마지막 수정 후 24시간 경과 경고
|
||||||
|
- 미승인 AI 제안 존재 시 알림
|
||||||
|
⚠️ 경고만 표시, 진행 가능
|
||||||
|
end note
|
||||||
|
|
||||||
|
Domain -> Domain: changeStatus(CONFIRMED)
|
||||||
|
|
||||||
|
Domain --> Service: updated Meeting
|
||||||
|
deactivate Domain
|
||||||
|
|
||||||
|
Service -> TranscriptService: lockTranscript(meetingId)
|
||||||
|
activate TranscriptService
|
||||||
|
note right of TranscriptService
|
||||||
|
회의록 잠금:
|
||||||
|
- 더 이상 수정 불가
|
||||||
|
- 버전 고정
|
||||||
|
end note
|
||||||
|
TranscriptService --> Service: lockedTranscript
|
||||||
|
deactivate TranscriptService
|
||||||
|
|
||||||
|
Service -> Repository: save(meeting)
|
||||||
|
activate Repository
|
||||||
|
Repository -> DB: 회의 상태 업데이트\n(상태='확정', 확정일시)
|
||||||
|
activate DB
|
||||||
|
DB --> Repository: affected_rows
|
||||||
|
deactivate DB
|
||||||
|
Repository --> Service: savedMeeting
|
||||||
|
deactivate Repository
|
||||||
|
|
||||||
|
Service -> Cache: SET meeting:{id}\n(TTL: 10분)
|
||||||
|
activate Cache
|
||||||
|
note right of Cache
|
||||||
|
회의 정보 캐싱:
|
||||||
|
- TTL: 10분
|
||||||
|
- 자동 만료
|
||||||
|
end note
|
||||||
|
Cache --> Service: OK
|
||||||
|
deactivate Cache
|
||||||
|
|
||||||
|
Service ->> EventHub: publish(MinutesFinalized)
|
||||||
|
activate EventHub
|
||||||
|
note right of EventHub
|
||||||
|
비동기 이벤트:
|
||||||
|
- 참석자에게 최종본 알림
|
||||||
|
- 공유 서비스로 전송
|
||||||
|
end note
|
||||||
|
deactivate EventHub
|
||||||
|
|
||||||
|
Service --> Controller: MeetingResponse
|
||||||
|
deactivate Service
|
||||||
|
|
||||||
|
Controller --> Gateway: 200 OK
|
||||||
|
deactivate Controller
|
||||||
|
|
||||||
|
@enduml
|
||||||
74
design/backend/sequence/outer/Todo완료및회의록반영.puml
Normal file
74
design/backend/sequence/outer/Todo완료및회의록반영.puml
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
@startuml Todo완료및회의록반영
|
||||||
|
!theme mono
|
||||||
|
|
||||||
|
title Todo 완료 및 회의록 반영 플로우
|
||||||
|
|
||||||
|
actor "담당자" as User
|
||||||
|
participant "Web App" as Web
|
||||||
|
participant "API Gateway" as Gateway
|
||||||
|
participant "Meeting Service" as Meeting
|
||||||
|
participant "Redis Cache" as Redis
|
||||||
|
participant "Notification Service" as Notification
|
||||||
|
|
||||||
|
note over Gateway
|
||||||
|
라우팅 규칙:
|
||||||
|
/api/meetings/** → Meeting Service
|
||||||
|
/api/minutes/** → Meeting Service
|
||||||
|
/api/dashboard → User Service
|
||||||
|
/api/notifications/** → Notification Service
|
||||||
|
/api/auth/** → User Service
|
||||||
|
/api/todos/** → Meeting Service
|
||||||
|
end note
|
||||||
|
|
||||||
|
autonumber
|
||||||
|
|
||||||
|
== Todo 완료 처리 ==
|
||||||
|
User -> Web: Todo 완료 버튼 클릭
|
||||||
|
activate Web
|
||||||
|
Web -> Gateway: PATCH /api/todos/{todoId}/complete\n(userId, userName, completedAt)
|
||||||
|
activate Gateway
|
||||||
|
Gateway -> Meeting: PATCH /todos/{todoId}/complete\n(userId, userName, completedAt)
|
||||||
|
activate Meeting
|
||||||
|
|
||||||
|
Meeting -> Meeting: Todo 상태 업데이트\n- 완료 시간 기록\n- 완료자 정보 저장\n- 상태: COMPLETED
|
||||||
|
Meeting -> Meeting: 관련 회의록에 완료 상태 반영\n- 회의록 섹션 업데이트\n- 완료 표시 (체크 아이콘)\n- 완료 시간 및 완료자 기록
|
||||||
|
Meeting -> Meeting: DB에 저장
|
||||||
|
|
||||||
|
== 캐시 무효화 ==
|
||||||
|
Meeting --> Redis: DELETE dashboard:{assigneeId}
|
||||||
|
note right
|
||||||
|
대시보드 캐시 무효화
|
||||||
|
end note
|
||||||
|
Meeting --> Redis: DELETE minutes:detail:{minutesId}
|
||||||
|
note right
|
||||||
|
회의록 상세 캐시 무효화
|
||||||
|
end note
|
||||||
|
|
||||||
|
== 이벤트 발행 ==
|
||||||
|
Meeting -> Notification: NotificationRequest 이벤트 발행
|
||||||
|
activate Notification
|
||||||
|
note right
|
||||||
|
이벤트 데이터:
|
||||||
|
- 발송수단: EMAIL
|
||||||
|
- 대상자: 회의록 작성자
|
||||||
|
- 메시지: Todo 완료 안내
|
||||||
|
- 메타데이터: todoId, 완료자, 완료 시간
|
||||||
|
end note
|
||||||
|
|
||||||
|
Meeting --> Gateway: 200 OK\n{todoId, status: COMPLETED,\ncompletedAt, completedBy}
|
||||||
|
deactivate Meeting
|
||||||
|
Gateway --> Web: 200 OK\n(Todo 완료 정보)
|
||||||
|
deactivate Gateway
|
||||||
|
Web --> User: Todo 완료 표시
|
||||||
|
deactivate Web
|
||||||
|
|
||||||
|
== 알림 발송 ==
|
||||||
|
Notification -> Notification: NotificationRequest 이벤트 구독
|
||||||
|
Notification -> Notification: 알림 메시지 생성\n- 수신자: 회의록 작성자\n- 내용: "Todo 완료됨"
|
||||||
|
Notification --> Notification: 이메일 발송\n(회의록 작성자에게)
|
||||||
|
note right
|
||||||
|
외부 Email Service 연동
|
||||||
|
end note
|
||||||
|
deactivate Notification
|
||||||
|
|
||||||
|
@enduml
|
||||||
113
design/backend/sequence/outer/대시보드조회.puml
Normal file
113
design/backend/sequence/outer/대시보드조회.puml
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
@startuml 대시보드조회
|
||||||
|
!theme mono
|
||||||
|
|
||||||
|
title 대시보드조회 외부 시퀀스
|
||||||
|
|
||||||
|
actor "사용자" as User
|
||||||
|
participant "Web App" as Frontend
|
||||||
|
participant "API Gateway" as Gateway
|
||||||
|
participant "User Service" as UserService
|
||||||
|
participant "Meeting Service" as MeetingService
|
||||||
|
database "Redis Cache" as Cache
|
||||||
|
database "User DB" as UserDB
|
||||||
|
database "Meeting DB" as MeetingDB
|
||||||
|
|
||||||
|
note over Gateway
|
||||||
|
라우팅 규칙:
|
||||||
|
/api/meetings/** → Meeting Service
|
||||||
|
/api/minutes/** → Meeting Service
|
||||||
|
/api/dashboard → User Service
|
||||||
|
/api/notifications/** → Notification Service
|
||||||
|
/api/auth/** → User Service
|
||||||
|
/api/todos/** → Meeting Service
|
||||||
|
end note
|
||||||
|
|
||||||
|
User -> Frontend: 대시보드 접근
|
||||||
|
activate Frontend
|
||||||
|
|
||||||
|
Frontend -> Gateway: GET /api/dashboard?\npage=1&size=10&sort=createdAt,desc
|
||||||
|
note right
|
||||||
|
페이지네이션 파라미터:
|
||||||
|
- page: 페이지 번호 (기본값: 1)
|
||||||
|
- size: 페이지 크기 (기본값: 10)
|
||||||
|
- sort: 정렬 기준 (기본값: createdAt,desc)
|
||||||
|
end note
|
||||||
|
activate Gateway
|
||||||
|
|
||||||
|
Gateway -> UserService: GET /dashboard?\npage=1&size=10&sort=createdAt,desc
|
||||||
|
activate UserService
|
||||||
|
|
||||||
|
' 캐시 조회
|
||||||
|
UserService -> Cache: GET dashboard:{userId}
|
||||||
|
activate Cache
|
||||||
|
Cache --> UserService: 캐시 조회 결과
|
||||||
|
deactivate Cache
|
||||||
|
|
||||||
|
alt Cache Hit
|
||||||
|
UserService -> UserService: 캐시 데이터 반환
|
||||||
|
else Cache Miss
|
||||||
|
par 병렬 데이터 조회
|
||||||
|
' Meeting Service 호출
|
||||||
|
UserService -> MeetingService: GET /api/v1/dashboard
|
||||||
|
note right
|
||||||
|
Meeting Service에서 조회:
|
||||||
|
- 예정된 회의 목록
|
||||||
|
- 진행 중 Todo 목록
|
||||||
|
- 최근 회의록 목록
|
||||||
|
- 공유받은 회의록
|
||||||
|
- 통계 정보
|
||||||
|
end note
|
||||||
|
activate MeetingService
|
||||||
|
MeetingService -> Cache: GET dashboard:{userId}
|
||||||
|
activate Cache
|
||||||
|
Cache --> MeetingService: 캐시 조회 결과
|
||||||
|
deactivate Cache
|
||||||
|
|
||||||
|
alt Meeting Service 캐시 미존재
|
||||||
|
MeetingService -> MeetingDB: 회의/Todo/회의록 데이터 조회
|
||||||
|
activate MeetingDB
|
||||||
|
MeetingDB --> MeetingService: 조회 결과
|
||||||
|
deactivate MeetingDB
|
||||||
|
|
||||||
|
MeetingService -> Cache: SET dashboard:{userId}\n(TTL: 5분)
|
||||||
|
activate Cache
|
||||||
|
Cache --> MeetingService: 캐시 저장
|
||||||
|
deactivate Cache
|
||||||
|
end
|
||||||
|
|
||||||
|
MeetingService --> UserService: 회의 관련 데이터 응답\n{\n "upcomingMeetings": [...],\n "activeTodos": [...],\n "recentMinutes": [...],\n "sharedMinutes": [...],\n "statistics": {...}\n}
|
||||||
|
deactivate MeetingService
|
||||||
|
else
|
||||||
|
' User Service 자체 데이터 조회
|
||||||
|
UserService -> UserDB: 최근 활동 내역 조회
|
||||||
|
activate UserDB
|
||||||
|
UserDB --> UserService: 활동 내역
|
||||||
|
deactivate UserDB
|
||||||
|
end
|
||||||
|
|
||||||
|
UserService -> UserService: 데이터 통합 및 조합
|
||||||
|
note right
|
||||||
|
대시보드 데이터 구성:
|
||||||
|
- Meeting Service 데이터
|
||||||
|
- User Service 활동 내역
|
||||||
|
- 통합 통계 정보
|
||||||
|
end note
|
||||||
|
|
||||||
|
UserService -> Cache: SET dashboard:{userId}\n(TTL: 5분)
|
||||||
|
activate Cache
|
||||||
|
Cache --> UserService: 캐시 저장 완료
|
||||||
|
deactivate Cache
|
||||||
|
end
|
||||||
|
|
||||||
|
UserService --> Gateway: 대시보드 데이터 응답\n{\n "upcomingMeetings": [...],\n "activeTodos": [...],\n "recentMinutes": [...],\n "recentActivities": [...],\n "statistics": {...},\n "pagination": {\n "page": 1,\n "size": 10,\n "totalElements": 45,\n "totalPages": 5,\n "hasNext": true\n }\n}
|
||||||
|
deactivate UserService
|
||||||
|
|
||||||
|
Gateway --> Frontend: 200 OK\n대시보드 데이터 + 페이지네이션 정보
|
||||||
|
deactivate Gateway
|
||||||
|
|
||||||
|
Frontend -> Frontend: 대시보드 화면 렌더링\n- 예정된 회의 표시\n- Todo 목록 표시\n- 최근 회의록 표시\n- 통계 차트 표시
|
||||||
|
|
||||||
|
Frontend --> User: 대시보드 화면 표시
|
||||||
|
deactivate Frontend
|
||||||
|
|
||||||
|
@enduml
|
||||||
@ -33,7 +33,7 @@ activate Gateway
|
|||||||
Gateway -> Meeting: POST /meetings/{meetingId}/start
|
Gateway -> Meeting: POST /meetings/{meetingId}/start
|
||||||
activate Meeting
|
activate Meeting
|
||||||
|
|
||||||
Meeting -> Meeting: 회의 세션 생성\n- Session 객체 생성\n- Minutes 초기화 (DRAFT)\n- WebSocket URL 생성
|
Meeting -> Meeting: 회의 세션 생성
|
||||||
|
|
||||||
Meeting -> STT: POST /stt/recording/start\n(meetingId, participantIds)
|
Meeting -> STT: POST /stt/recording/start\n(meetingId, participantIds)
|
||||||
activate STT
|
activate STT
|
||||||
@ -47,7 +47,7 @@ STT -> STT: 음성 녹음 준비 및 시작
|
|||||||
STT --> Meeting: 200 OK (recordingId)
|
STT --> Meeting: 200 OK (recordingId)
|
||||||
deactivate STT
|
deactivate STT
|
||||||
|
|
||||||
Meeting --> Gateway: 201 Created\n- sessionId\n- meetingId\n- minutesId\n- status (IN_PROGRESS)\n- websocketUrl\n- sessionToken\n- startedAt\n- expiresAt
|
Meeting --> Gateway: 201 Created
|
||||||
deactivate Meeting
|
deactivate Meeting
|
||||||
|
|
||||||
Gateway --> Frontend: 201 Created
|
Gateway --> Frontend: 201 Created
|
||||||
|
|||||||
@ -27,7 +27,7 @@ end note
|
|||||||
User -> WebApp: 회의 정보 입력\n(제목, 날짜/시간, 장소, 참석자)
|
User -> WebApp: 회의 정보 입력\n(제목, 날짜/시간, 장소, 참석자)
|
||||||
activate WebApp
|
activate WebApp
|
||||||
|
|
||||||
WebApp -> Gateway: POST /api/meetings/reserve\n+ JWT 토큰\n+ 사용자 정보 (userId, userName, email)
|
WebApp -> Gateway: POST /api/meetings\n+ JWT 토큰\n+ 사용자 정보 (userId, userName, email)
|
||||||
activate Gateway
|
activate Gateway
|
||||||
|
|
||||||
Gateway -> Meeting: 회의 생성 요청
|
Gateway -> Meeting: 회의 생성 요청
|
||||||
@ -69,30 +69,6 @@ deactivate Gateway
|
|||||||
WebApp --> User: 회의 예약 완료 표시\n캘린더에 자동 등록
|
WebApp --> User: 회의 예약 완료 표시\n캘린더에 자동 등록
|
||||||
deactivate WebApp
|
deactivate WebApp
|
||||||
|
|
||||||
== 템플릿 선택 (선택 사항) ==
|
|
||||||
User -> WebApp: 템플릿 선택\n(일반, 스크럼, 킥오프, 주간)
|
|
||||||
activate WebApp
|
|
||||||
|
|
||||||
WebApp -> Gateway: PUT /api/meetings/{meetingId}/template\n+ JWT 토큰\n+ templateId
|
|
||||||
activate Gateway
|
|
||||||
|
|
||||||
Gateway -> Meeting: 템플릿 적용 요청
|
|
||||||
activate Meeting
|
|
||||||
|
|
||||||
Meeting -> MeetingDB: 템플릿 정보 저장
|
|
||||||
activate MeetingDB
|
|
||||||
MeetingDB --> Meeting: 저장 완료
|
|
||||||
deactivate MeetingDB
|
|
||||||
|
|
||||||
Meeting --> Gateway: 200 OK\n템플릿 적용 완료
|
|
||||||
deactivate Meeting
|
|
||||||
|
|
||||||
Gateway --> WebApp: 템플릿 적용 응답
|
|
||||||
deactivate Gateway
|
|
||||||
|
|
||||||
WebApp --> User: 템플릿 적용 완료
|
|
||||||
deactivate WebApp
|
|
||||||
|
|
||||||
== 참석자 초대 알림 (비동기) ==
|
== 참석자 초대 알림 (비동기) ==
|
||||||
EventHub -> Notification: NotificationRequest 이벤트 수신\n(Consumer Group: notification-service-group)
|
EventHub -> Notification: NotificationRequest 이벤트 수신\n(Consumer Group: notification-service-group)
|
||||||
|
|
||||||
|
|||||||
@ -32,15 +32,8 @@ note right
|
|||||||
end note
|
end note
|
||||||
|
|
||||||
Gateway -> Meeting: 회의 종료 요청
|
Gateway -> Meeting: 회의 종료 요청
|
||||||
Meeting -> Meeting: 회의 종료 처리\n- 종료 시간 기록\n- 회의록 생성 (DRAFT 상태)\n- 회의 통계 생성\n (총 시간, 참석자 수 등)
|
Meeting -> Meeting: 회의 종료 처리\n- 종료 시간 기록\n- 회의 통계 생성\n (총 시간, 참석자 수, 발언 횟수 등)
|
||||||
|
Meeting -> Meeting: DB 저장
|
||||||
Meeting -> AI: AI 분석 요청\n- 키워드 추출\n- 안건별 요약 생성\n- Todo 항목 추출
|
|
||||||
activate AI
|
|
||||||
AI -> AI: AI 분석 수행
|
|
||||||
AI --> Meeting: AI 분석 결과\n(keywords, agendaSummaries, todos)
|
|
||||||
deactivate AI
|
|
||||||
|
|
||||||
Meeting -> Meeting: DB 저장\n- Meeting 종료 상태\n- Minutes 생성 (DRAFT)\n- AgendaSection 저장\n- Todo 저장
|
|
||||||
Meeting -> Meeting: Redis 캐시 무효화\n(meeting:info:{meetingId})
|
Meeting -> Meeting: Redis 캐시 무효화\n(meeting:info:{meetingId})
|
||||||
|
|
||||||
Meeting -> EventHub: MeetingEnded 이벤트 발행\n(meetingId, userId, endTime)
|
Meeting -> EventHub: MeetingEnded 이벤트 발행\n(meetingId, userId, endTime)
|
||||||
@ -62,9 +55,9 @@ end note
|
|||||||
EventHub --> Meeting: 발행 완료
|
EventHub --> Meeting: 발행 완료
|
||||||
deactivate EventHub
|
deactivate EventHub
|
||||||
|
|
||||||
Meeting -> Gateway: 200 OK\n- minutesId\n- 회의 통계 (참석자 수, 시간, 안건 수, Todo 수)\n- 키워드 목록\n- 안건별 AI 요약 (한줄 요약, 상세 요약)\n- Todo 목록
|
Meeting -> Gateway: 202 Accepted\n(회의 종료 완료)
|
||||||
Gateway -> WebApp: 회의 종료 완료 응답\n(MeetingEndResponse)
|
Gateway -> WebApp: 회의 종료 완료 응답
|
||||||
WebApp -> User: 회의 종료 화면 표시\n- 통계 카드\n- 키워드 태그\n- 안건 아코디언 (AI 요약 + Todo)
|
WebApp -> User: 회의 통계 표시\n(총 시간, 참석자, 발언 횟수 등)
|
||||||
|
|
||||||
== 비동기 처리 - STT 종료 ==
|
== 비동기 처리 - STT 종료 ==
|
||||||
EventHub --> STT: MeetingEnded 이벤트 수신
|
EventHub --> STT: MeetingEnded 이벤트 수신
|
||||||
@ -83,62 +76,43 @@ note right
|
|||||||
end note
|
end note
|
||||||
|
|
||||||
== 최종 회의록 확정 ==
|
== 최종 회의록 확정 ==
|
||||||
User -> WebApp: 최종 회의록 확정 버튼 클릭\n(회의록 수정 화면 또는 회의 종료 화면)
|
User -> WebApp: 최종 회의록 확정 버튼 클릭
|
||||||
WebApp -> Gateway: POST /api/meetings/minutes/{minutesId}/finalize
|
WebApp -> Gateway: POST /api/minutes/{minutesId}/finalize
|
||||||
note right
|
note right
|
||||||
요청 헤더에 JWT 토큰 포함
|
요청 헤더에 JWT 토큰 포함
|
||||||
X-User-Id, X-User-Name, X-User-Email
|
요청 바디에 사용자 정보 포함
|
||||||
end note
|
end note
|
||||||
|
|
||||||
Gateway -> Meeting: 회의록 확정 요청
|
Gateway -> Meeting: 회의록 확정 요청
|
||||||
Meeting -> Meeting: 회의록 상태 변경\n- DRAFT → FINALIZED\n- finalizedAt 기록\n- finalizedBy 기록
|
Meeting -> Meeting: 필수 항목 검사\n- 회의 제목\n- 참석자 목록\n- 주요 논의 내용\n- 결정 사항
|
||||||
|
|
||||||
Meeting -> Meeting: DB 저장\n- Minutes 상태 업데이트
|
alt 필수 항목 미작성
|
||||||
Meeting -> Meeting: Redis 캐시 저장\n(확정된 회의록, TTL: 10분)
|
Meeting -> Gateway: 400 Bad Request\n(누락된 항목 정보)
|
||||||
Meeting -> Meeting: Redis 목록 캐시 무효화\n(사용자별 회의록 목록)
|
Gateway -> WebApp: 검증 실패 응답
|
||||||
|
WebApp -> User: 누락된 항목 안내\n(해당 섹션으로 자동 이동)
|
||||||
|
else 필수 항목 작성 완료
|
||||||
|
Meeting -> Meeting: 회의록 최종 확정\n- 확정 버전 생성\n- 확정 시간 기록
|
||||||
|
Meeting -> Meeting: DB 저장 (MinutesVersion)
|
||||||
|
Meeting -> Meeting: Redis 캐시 무효화
|
||||||
|
|
||||||
Meeting -> EventHub: MinutesFinalizedEvent 발행\n(알림용 - 기존)
|
Meeting -> EventHub: NotificationRequest 이벤트 발행\n(회의록 확정 알림)
|
||||||
activate EventHub
|
activate EventHub
|
||||||
note right
|
note right
|
||||||
간단한 이벤트 데이터:
|
이벤트 데이터:
|
||||||
- minutesId
|
- 발송수단: EMAIL
|
||||||
- title
|
- 대상자: 참석자 전원
|
||||||
- userId
|
- 메시지: 회의록 확정 안내
|
||||||
- userName
|
- 메타데이터: 버전 번호, 확정 시간
|
||||||
end note
|
end note
|
||||||
EventHub --> Meeting: 발행 완료
|
EventHub --> Meeting: 발행 완료
|
||||||
deactivate EventHub
|
deactivate EventHub
|
||||||
|
|
||||||
Meeting -> EventHub: MinutesFinalizedEvent 발행\n(RAG용 - 완전한 데이터)
|
Meeting -> Gateway: 200 OK\n(확정 버전 정보)
|
||||||
activate EventHub
|
Gateway -> WebApp: 회의록 확정 완료
|
||||||
note right
|
WebApp -> User: 확정 완료 안내\n(버전 번호, 확정 시간)
|
||||||
완전한 이벤트 데이터:
|
|
||||||
- Meeting 정보 (meetingId, title, purpose, scheduledAt 등)
|
|
||||||
- Minutes 정보 (minutesId, status, version 등)
|
|
||||||
- Sections 정보 (모든 안건 섹션)
|
|
||||||
- 참석자 정보
|
|
||||||
end note
|
|
||||||
EventHub --> Meeting: 발행 완료
|
|
||||||
deactivate EventHub
|
|
||||||
|
|
||||||
Meeting -> Gateway: 200 OK\n(확정된 회의록 상세 정보)
|
EventHub --> Notification: NotificationRequest 이벤트 수신
|
||||||
Gateway -> WebApp: 회의록 확정 완료
|
Notification -> Notification: 회의록 확정 알림 발송\n(참석자 전원)
|
||||||
WebApp -> User: 확정 완료 토스트 표시\n회의록 상세 조회 화면으로 이동
|
end
|
||||||
|
|
||||||
== 비동기 처리 - 알림 발송 ==
|
|
||||||
EventHub --> Notification: MinutesFinalizedEvent 수신\n(알림용)
|
|
||||||
Notification -> Notification: 회의록 확정 알림 발송\n(참석자 전원)
|
|
||||||
note right
|
|
||||||
알림 내용:
|
|
||||||
- 회의 제목
|
|
||||||
- 확정 시간
|
|
||||||
- 회의록 링크
|
|
||||||
end note
|
|
||||||
|
|
||||||
== 비동기 처리 - RAG 저장 ==
|
|
||||||
EventHub --> AI: MinutesFinalizedEvent 수신\n(RAG용)
|
|
||||||
activate AI
|
|
||||||
AI -> AI: RAG 서비스 연동\n- 벡터 DB 저장\n- 관련 회의록 검색 준비
|
|
||||||
deactivate AI
|
|
||||||
|
|
||||||
@enduml
|
@enduml
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
Before Width: | Height: | Size: 566 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 144 KiB |
Loading…
x
Reference in New Issue
Block a user