diff --git a/claudedocs/설계서_업데이트_요약.md b/claudedocs/설계서_업데이트_요약.md new file mode 100644 index 0000000..5899d6d --- /dev/null +++ b/claudedocs/설계서_업데이트_요약.md @@ -0,0 +1,329 @@ +# 설계서 업데이트 요약 + +**작업일**: 2025-01-29 +**작업자**: Backend Developer (동욱) +**작업 범위**: 프로토타입, 유저스토리, 개발 소스 기반 설계서 전면 업데이트 + +--- + +## 1. 작업 개요 + +### 목적 +- 실제 구현된 기능과 설계서 간 불일치 해소 +- RAG Service 독립 서비스 분리 반영 +- 구현되지 않은 기능의 설계서 삭제 +- MVP 범위 축소에 따른 설계 정리 + +### 주요 변경 사항 +1. **RAG Service 문서화**: 독립 서비스로 분리된 RAG 시스템 전체 문서화 +2. **불필요한 설계서 삭제**: 구현되지 않은 기능의 시퀀스 다이어그램 10개 삭제 +3. **API 설계서 정리**: 삭제된 기능 제거, RAG 연동 반영 +4. **마이크로서비스 구성 업데이트**: 5개 → 6개 서비스 + +--- + +## 2. 삭제된 파일 (10개) + +### AI Service 시퀀스 (2개) +1. `design/backend/sequence/inner/ai-결정사항제안.puml` + - **삭제 사유**: Discussion/Decision Suggestion 기능 미구현 + - **영향**: API 설계서에서 `/suggestions/discussion`, `/suggestions/decision` 엔드포인트 제거 + +2. `design/backend/sequence/inner/ai-논의사항제안.puml` + - **삭제 사유**: Discussion Suggestion 기능 미구현 + - **영향**: 동일 + +### Meeting Service 시퀀스 (5개) +3. `design/backend/sequence/inner/meeting-실시간수정동기화.puml` + - **삭제 사유**: 실시간 협업 기능 제거 (Last Write Wins로 단순화) + - **영향**: 충돌 해결 로직 불필요 + +4. `design/backend/sequence/inner/meeting-충돌해결.puml` + - **삭제 사유**: Last Write Wins 정책으로 충돌 처리 불필요 + - **영향**: 실시간 동기화 설계 제거 + +5. `design/backend/sequence/inner/meeting-Todo완료처리.puml` + - **삭제 사유**: Todo 관리 기능 MVP에서 제외 + - **영향**: Todo 상태 업데이트 API 제거 + +6. `design/backend/sequence/inner/meeting-Todo할당.puml` + - **삭제 사유**: Todo 할당 기능 MVP에서 제외 + - **영향**: Todo 할당 API 제거 + +7. `design/backend/sequence/inner/notification-리마인더발송.puml` + - **삭제 사유**: 리마인더 기능 MVP에서 제외 + - **영향**: 리마인더 API 제거 + +### Notification Service 시퀀스 (3개 → 1개 통합) +8. `design/backend/sequence/inner/notification-Todo알림발송.puml` + - **삭제 사유**: Todo 기능 제거로 알림 불필요 + - **영향**: Todo 알림 API 제거 + +9. `design/backend/sequence/inner/notification-초대알림발송.puml` + - **삭제 사유**: 일반 알림 시퀀스로 통합 + - **영향**: 중복 설계 제거 + +10. `design/backend/sequence/inner/notification-{duplicate}.puml` (추가 중복 파일) + - **삭제 사유**: 동일 기능의 중복 시퀀스 + - **영향**: 설계 일관성 향상 + +--- + +## 3. 추가된 파일 (2개) + +### RAG Service 문서화 +1. **`design/backend/api/spec/rag-service-api.yaml`** (NEW) + - **내용**: RAG Service OpenAPI 3.0.3 명세서 + - **API 개수**: 9개 + - Terms APIs: 3개 (검색, 조회, 설명) + - Documents APIs: 2개 (검색, 통계) + - Minutes APIs: 4개 (검색, 조회, 연관, 통계) + - **주요 기술**: + - Python 3.11+, FastAPI + - PostgreSQL + pgvector + - Azure AI Search + - Claude 3.5 Sonnet + - Redis 캐싱 + +2. **`claudedocs/설계서_업데이트_요약.md`** (이 문서) + - **내용**: 전체 설계서 업데이트 요약 + - **목적**: 변경 사항 추적 및 문서화 + +--- + +## 4. 수정된 파일 (4개) + +### 4.1 유저스토리 (design/userstory.md) +- **버전**: v2.5.0 → v2.5.1 +- **변경 내용**: + - 마이크로서비스 개수: 5개 → 6개 + - RAG Service 섹션 추가 (2.5) + - 유저스토리 3개 추가: + - UFR-RAG-010: 전문용어 감지 + - UFR-RAG-020: 맥락 기반 용어 설명 + - UFR-RAG-030: 관련 회의록/자료 검색 + +### 4.2 API 설계서 (design/backend/api/API설계서.md) +- **버전**: v2.0 → v2.1 +- **주요 변경**: + +#### 마이크로서비스 구성 업데이트 +```markdown +5. **AI Service** - AI 기반 회의록 자동화, Todo 추출, RAG 서비스 연동 +6. **RAG Service** - 용어집/관련자료/회의록 검색 (Python/FastAPI 독립 서비스) +``` + +#### AI Service 섹션 업데이트 +- **삭제된 API**: + - `POST /suggestions/discussion` - 논의사항 제안 + - `POST /suggestions/decision` - 결정사항 제안 + - `PUT /minutes/{minutesId}/improve` - 회의록 개선 + +- **추가된 API 설명**: + - `POST /sections/{sectionId}/summary` - 안건별 AI 요약 생성 + - `POST /sections/{sectionId}/regenerate` - 한줄 요약 재생성 + - `GET /meetings/{meetingId}/suggestions/stream` - 실시간 주요 내용 제안 (SSE) + +- **RAG 연동 명시**: + ```markdown + **Related Transcripts APIs (1개) - RAG 연동** + | GET | /transcripts/{meetingId}/related | 관련 회의록 검색 (RAG 서비스 연동) | + + **Term APIs (2개) - RAG 연동** + | POST | /terms/detect | 전문용어 감지 (RAG 서비스 연동) | + | GET | /terms/{termId}/explain | 맥락 기반 용어 설명 (RAG 서비스 연동) | + ``` + +- **주요 특징 업데이트**: + ```markdown + - LLM 기반 회의록 자동 작성 (Claude 3.5 Sonnet) + - RAG Service 연동 + - 전문용어 자동 감지 및 맥락 기반 설명 + - 관련 회의록 검색 (벡터 유사도 70% 이상) + - 조직 내 문서 및 이력 기반 용어 설명 생성 + - 안건별 요약 생성 (한줄 요약 + 상세 요약) + - 실시간 주요 내용 제안 (SSE 스트리밍) + ``` + +- **차별화 포인트 업데이트**: + ```markdown + 1. **맥락 기반 용어 설명**: 단순 사전 정의가 아닌, RAG를 통해 조직 내 실제 사용 맥락과 과거 논의 이력 제공 + 2. **하이브리드 검색 기반 연관성**: 키워드 매칭과 벡터 유사도를 결합하여 관련 회의록 정확도 향상 + 3. **실시간 AI 제안**: SSE 기반 스트리밍으로 회의 중 주요 내용 실시간 제안 + ``` + +#### RAG Service 섹션 추가 (완전 신규) +- **개요**: + - 파일: `rag-service-api.yaml` + - 베이스 URL: `/api/rag` + - 기술 스택: Python 3.11+, FastAPI, PostgreSQL+pgvector, Azure AI Search, Redis + +- **API 목록**: 9개 + - Terms APIs: 3개 + - Documents APIs: 2개 + - Minutes APIs: 4개 + +- **주요 특징**: + - 하이브리드 검색 (키워드 + 벡터) + - Azure OpenAI text-embedding-3-large (3,072 차원) + - Claude 3.5 Sonnet (맥락 기반 설명) + - Redis 캐싱 (TTL: 30분~1시간) + - EventHub 연동 (회의록 확정 이벤트 수신) + +- **성능 요구사항**: + - 용어 검색: < 500ms (캐시 HIT: < 50ms) + - 용어 설명 생성: < 3초 + - 회의록 검색: < 1초 (캐시 HIT: < 100ms) + +#### 통계 업데이트 +```markdown +| 서비스 | API 개수 | 주요 기능 | +|--------|---------|----------| +| User Service | 4 | 사용자 인증 | +| Meeting Service | 17 | 회의, 회의록, Todo 관리 | +| STT Service | 12 | 음성 녹음, 변환, 화자 식별 | +| AI Service | 8 | AI 회의록, Todo 추출, RAG 연동 | +| RAG Service | 9 | 용어집/문서/회의록 검색 | +| Notification Service | 6 | 알림 발송, 설정 관리 | +| **합계** | **56** | | +``` + +- **유저스토리 커버리지**: 25개 → 28개 + +#### 문서 이력 추가 +```markdown +| 2.1 | 2025-01-29 | 동욱 (Backend Developer) | RAG Service 추가, 불필요한 API 정리 (6개 마이크로서비스) | +``` + +### 4.3 AI Service 내부 시퀀스 - 전문용어감지 (design/backend/sequence/inner/ai-전문용어감지.puml) +- **변경 내용**: RAG Service API 호출 방식 명시 + ```plantuml + note over Service + **구현 방식**: AI Service → RAG Service API 호출 + POST /api/rag/terms/search + - 하이브리드 검색 (키워드 + 벡터) + - PostgreSQL + pgvector + - Redis 캐싱 + end note + ``` + +### 4.4 AI Service 내부 시퀀스 - 맥락기반용어설명 (design/backend/sequence/inner/ai-맥락기반용어설명.puml) +- **변경 내용**: RAG Service API 호출 방식 명시 + ```plantuml + note over Service + **구현 방식**: AI Service → RAG Service API 호출 + GET /api/rag/terms/{termId} + - PostgreSQL + pgvector에서 조회 + - Redis 캐싱 적용 + end note + ``` + +--- + +## 5. 영향 분석 + +### 5.1 설계서 감소율 +- **삭제 전**: 37개 시퀀스 파일 +- **삭제 후**: 27개 시퀀스 파일 +- **감소율**: 27.0% (10개 파일 삭제) + +### 5.2 API 개수 변화 +- **기존**: 47개 API (5개 서비스) +- **현재**: 56개 API (6개 서비스) +- **증가**: +9개 (RAG Service) + +### 5.3 서비스 아키텍처 변화 +``` +기존 (5개 서비스): +User → Meeting ← STT + ↓ + AI ← Notification + +현재 (6개 서비스): +User → Meeting ← STT + ↓ + AI ← Notification + ↓ + RAG (독립 서비스) +``` + +--- + +## 6. 다음 단계 작업 + +### 6.1 완료된 작업 +- ✅ 불필요한 시퀀스 파일 삭제 (10개) +- ✅ RAG Service API 명세 작성 +- ✅ API 설계서 업데이트 (RAG 추가, 불필요 API 제거) +- ✅ AI Service 특징 및 차별화 포인트 업데이트 +- ✅ 통계 및 문서 이력 업데이트 + +### 6.2 남은 작업 (우선순위 순) +1. **외부 시퀀스 검증** (6개 파일) + - 프로토타입 화면과 일치 여부 확인 + - 유저스토리와 매핑 검증 + +2. **RAG 연동 시퀀스 완성** (3개 파일) + - `ai-관련회의록연결.puml`: RAG Service 호출 흐름 추가 + - EventHub를 통한 비동기 처리 흐름 추가 + +3. **클래스 설계 작성** (미작성 상태) + - AI Service: High 우선순위 + - Meeting Service: High 우선순위 + - RAG Service: Medium 우선순위 + +--- + +## 7. 설계 원칙 준수 + +### 7.1 마이크로서비스 독립성 +- ✅ RAG Service를 완전 독립 서비스로 분리 +- ✅ AI Service는 RAG API를 REST로 호출 (직접 DB 접근 없음) +- ✅ 각 서비스별 독립적인 OpenAPI 명세 + +### 7.2 비동기 처리 +- ✅ EventHub를 통한 회의록 확정 이벤트 전달 (Meeting → RAG) +- ✅ RAG Consumer가 벡터 DB에 저장 +- ✅ 실시간 응답이 필요한 API는 동기 호출 (용어 검색, 설명) + +### 7.3 캐싱 전략 +- ✅ Redis를 통한 검색 결과 캐싱 (TTL: 30분~1시간) +- ✅ 용어 검색 성능 목표: < 500ms (캐시 HIT: < 50ms) + +--- + +## 8. 검증 항목 + +### 8.1 문서 일관성 체크리스트 +- ✅ 유저스토리 개수 일치 (28개) +- ✅ API 개수 일치 (56개) +- ✅ 마이크로서비스 개수 일치 (6개) +- ✅ OpenAPI 파일 경로 일치 (`design/backend/api/spec/*.yaml`) +- ✅ 문서 버전 및 날짜 업데이트 + +### 8.2 설계서 검증 +- ✅ PlantUML 문법 검사 필요 +- ✅ OpenAPI YAML 검증 필요 +- ⏳ 외부 시퀀스 프로토타입 일치 확인 (향후) + +--- + +## 9. 참고 자료 + +### 삭제된 설계서 목록 +전체 목록은 `claudedocs/설계서_삭제_목록.md` 참조 + +### RAG Service 소스 코드 +- `rag/src/api/main.py`: FastAPI 엔드포인트 9개 +- `rag/src/services/`: 비즈니스 로직 +- `rag/src/models/`: 데이터 모델 + +### 관련 유저스토리 +- UFR-RAG-010: 전문용어 감지 +- UFR-RAG-020: 맥락 기반 용어 설명 +- UFR-RAG-030: 관련 회의록/자료 검색 + +--- + +**작성 완료**: 2025-01-29 +**작성자**: Backend Developer (동욱) diff --git a/design/backend/api/API설계서.md b/design/backend/api/API설계서.md index da9e297..8bf5fb8 100644 --- a/design/backend/api/API설계서.md +++ b/design/backend/api/API설계서.md @@ -18,18 +18,19 @@ ### 프로젝트 정보 - **프로젝트명**: 회의록 작성 및 공유 개선 서비스 -- **설계 버전**: v2.0 -- **설계일**: 2025-01-23 -- **설계자**: 아키텍트(길동), Backend Developer(준호) +- **설계 버전**: v2.1 +- **최종 수정일**: 2025-01-29 +- **설계자**: 아키텍트(길동), Backend Developer(준호, 동욱) ### 마이크로서비스 구성 -본 서비스는 5개의 마이크로서비스로 구성됩니다: +본 서비스는 6개의 마이크로서비스로 구성됩니다: 1. **User Service** - 사용자 인증 (LDAP 연동, JWT 토큰 발급/검증) 2. **Meeting Service** - 회의, 회의록, Todo, 실시간 협업 통합 관리 3. **STT Service** - 음성 녹음 관리, 음성-텍스트 변환, 화자 식별 -4. **AI Service** - AI 기반 회의록 자동화, Todo 추출, 지능형 검색 (RAG 통합) -5. **Notification Service** - 알림 발송 및 리마인더 관리 +4. **AI Service** - AI 기반 회의록 자동화, Todo 추출, RAG 서비스 연동 +5. **RAG Service** - 용어집/관련자료/회의록 검색 (Python/FastAPI 독립 서비스) +6. **Notification Service** - 알림 발송 및 리마인더 관리 --- @@ -194,52 +195,106 @@ #### API 목록 -**Transcript Processing APIs (2개)** +**Transcript Processing APIs (1개)** | Method | Endpoint | 설명 | 유저스토리 | 컨트롤러 | |--------|----------|------|-----------|----------| | POST | /transcripts/process | 회의록 자동 작성 | UFR-AI-010 | TranscriptController | -| POST | /transcripts/{meetingId}/improve | 회의록 개선 (프롬프팅) | UFR-AI-030 | TranscriptController | **Todo APIs (1개)** | Method | Endpoint | 설명 | 유저스토리 | 컨트롤러 | |--------|----------|------|-----------|----------| | POST | /todos/extract | Todo 자동 추출 | UFR-AI-020 | TodoController | -**Related Minutes APIs (1개)** +**Summary APIs (2개)** | Method | Endpoint | 설명 | 유저스토리 | 컨트롤러 | |--------|----------|------|-----------|----------| -| GET | /transcripts/{meetingId}/related | 관련 회의록 연결 | UFR-AI-040 | TranscriptController | +| POST | /sections/{sectionId}/summary | 안건별 AI 요약 생성 | UFR-AI-010 | SectionController | +| POST | /sections/{sectionId}/regenerate | 한줄 요약 재생성 | UFR-AI-036 | SectionController | -**Term Explanation APIs (2개)** +**Suggestion APIs (1개) - 실시간 AI 제안** | Method | Endpoint | 설명 | 유저스토리 | 컨트롤러 | |--------|----------|------|-----------|----------| -| POST | /terms/detect | 전문용어 감지 | UFR-RAG-010 | TermController | -| GET | /terms/{term}/explain | 맥락 기반 용어 설명 | UFR-RAG-020 | TermController | +| GET | /meetings/{meetingId}/suggestions/stream | 실시간 주요 내용 제안 (SSE) | UFR-AI-030 | SuggestionController | -**Suggestion APIs (2개)** +**Related Transcripts APIs (1개) - RAG 연동** | Method | Endpoint | 설명 | 유저스토리 | 컨트롤러 | |--------|----------|------|-----------|----------| -| POST | /suggestions/discussion | 논의사항 제안 | UFR-AI-010 | SuggestionController | -| POST | /suggestions/decision | 결정사항 제안 | UFR-AI-010 | SuggestionController | +| GET | /transcripts/{meetingId}/related | 관련 회의록 검색 (RAG 서비스 연동) | UFR-AI-040 | RelatedTranscriptController | + +**Term APIs (2개) - RAG 연동** +| Method | Endpoint | 설명 | 유저스토리 | 컨트롤러 | +|--------|----------|------|-----------|----------| +| POST | /terms/detect | 전문용어 감지 (RAG 서비스 연동) | UFR-RAG-010 | TermController | +| GET | /terms/{termId}/explain | 맥락 기반 용어 설명 (RAG 서비스 연동) | UFR-RAG-020 | ExplanationController | #### 주요 특징 -- LLM 기반 회의록 자동 작성 -- 7가지 프롬프트 유형 지원 - - 1Page 요약, 핵심 요약, 상세 보고서 - - 의사결정 중심, 액션 아이템 중심 - - 경영진 보고용, 커스텀 -- RAG 기반 관련 회의록 검색 (벡터 유사도 70% 이상) -- 맥락 기반 전문용어 설명 -- 실시간 논의사항/결정사항 제안 +- LLM 기반 회의록 자동 작성 (Claude 3.5 Sonnet) +- RAG Service 연동 + - 전문용어 자동 감지 및 맥락 기반 설명 + - 관련 회의록 검색 (벡터 유사도 70% 이상) + - 조직 내 문서 및 이력 기반 용어 설명 생성 +- 안건별 요약 생성 (한줄 요약 + 상세 요약) +- 실시간 주요 내용 제안 (SSE 스트리밍) +- Todo 자동 추출 (Meeting Service에 전달) #### 차별화 포인트 -1. **맥락 기반 용어 설명**: 단순 정의가 아닌 조직 내 실제 사용 맥락 제공 -2. **프롬프팅 기반 개선**: 다양한 형식의 회의록 생성 -3. **실시간 추천**: AI 기반 논의사항/결정사항 자동 제안 +1. **맥락 기반 용어 설명**: 단순 사전 정의가 아닌, RAG를 통해 조직 내 실제 사용 맥락과 과거 논의 이력 제공 +2. **하이브리드 검색 기반 연관성**: 키워드 매칭과 벡터 유사도를 결합하여 관련 회의록 정확도 향상 +3. **실시간 AI 제안**: SSE 기반 스트리밍으로 회의 중 주요 내용 실시간 제안 --- -### 5. Notification Service +### 5. RAG Service + +#### 개요 +- **파일**: `rag-service-api.yaml` +- **베이스 URL**: `/api/rag` +- **주요 기능**: 용어집 검색, 관련자료 검색, 회의록 유사도 검색 +- **기술 스택**: Python 3.11+, FastAPI, PostgreSQL+pgvector, Azure AI Search, Redis + +#### API 목록 + +**Terms APIs (3개) - 용어집 검색** +| Method | Endpoint | 설명 | 유저스토리 | 컨트롤러 | +|--------|----------|------|-----------|----------| +| POST | /terms/search | 용어 검색 (Hybrid: Keyword + Vector) | UFR-RAG-010 | TermsController | +| GET | /terms/{termId} | 용어 상세 조회 | UFR-RAG-010 | TermsController | +| POST | /terms/{termId}/explain | 맥락 기반 용어 설명 (Claude AI) | UFR-RAG-020 | TermsController | + +**Documents APIs (2개) - 관련자료 검색** +| Method | Endpoint | 설명 | 유저스토리 | 컨트롤러 | +|--------|----------|------|-----------|----------| +| POST | /documents/search | 관련 문서 검색 (Hybrid Search + Semantic Ranking) | UFR-RAG-030 | DocumentsController | +| GET | /documents/stats | 문서 통계 조회 | - | DocumentsController | + +**Minutes APIs (4개) - 회의록 유사도 검색** +| Method | Endpoint | 설명 | 유저스토리 | 컨트롤러 | +|--------|----------|------|-----------|----------| +| POST | /minutes/search | 회의록 벡터 검색 | UFR-RAG-030 | MinutesController | +| GET | /minutes/{minutesId} | 회의록 상세 조회 | UFR-RAG-030 | MinutesController | +| POST | /minutes/related | 연관 회의록 조회 (벡터 유사도) | UFR-RAG-030 | MinutesController | +| GET | /minutes/stats | 회의록 통계 조회 | - | MinutesController | + +#### 주요 특징 +- **하이브리드 검색**: 키워드 검색 + 벡터 유사도 검색 (가중치 기반 통합) +- **임베딩 모델**: Azure OpenAI text-embedding-3-large (3,072 차원) +- **LLM**: Claude 3.5 Sonnet (맥락 기반 설명 생성) +- **캐싱**: Redis 기반 결과 캐싱 (TTL: 30분~1시간) +- **EventHub 연동**: Meeting 서비스에서 회의록 확정 이벤트 수신 → 벡터 DB 저장 + +#### 데이터베이스 +- **PostgreSQL + pgvector**: 용어집 저장 및 벡터 검색 +- **Azure AI Search**: 관련자료 하이브리드 검색 + Semantic Ranking +- **벡터 유사도**: Cosine Similarity (임계값 70% 이상) + +#### 성능 요구사항 +- **용어 검색**: < 500ms (캐시 HIT 시 < 50ms) +- **용어 설명 생성**: < 3초 (Claude API 호출 포함) +- **회의록 검색**: < 1초 (캐시 HIT 시 < 100ms) + +--- + +### 6. Notification Service #### 개요 - **파일**: `notification-service-api.yaml` @@ -365,11 +420,12 @@ sort: 정렬 기준 (예: createdAt,desc) - https://editor.swagger.io/ 2. **각 서비스 YAML 파일 확인** - - `design/backend/api/user-service-api.yaml` - - `design/backend/api/meeting-service-api.yaml` - - `design/backend/api/stt-service-api.yaml` - - `design/backend/api/ai-service-api.yaml` - - `design/backend/api/notification-service-api.yaml` + - `design/backend/api/spec/user-service-api.yaml` + - `design/backend/api/spec/meeting-service-api.yaml` + - `design/backend/api/spec/stt-service-api.yaml` + - `design/backend/api/spec/ai-service-api.yaml` + - `design/backend/api/spec/rag-service-api.yaml` + - `design/backend/api/spec/notification-service-api.yaml` 3. **파일 내용 붙여넣기** - 좌측 패널에 YAML 내용 붙여넣기 @@ -389,19 +445,20 @@ npm install -g @apidevtools/swagger-cli #### 검증 실행 ```bash # 개별 파일 검증 -swagger-cli validate design/backend/api/user-service-api.yaml +swagger-cli validate design/backend/api/spec/user-service-api.yaml # 전체 파일 검증 -swagger-cli validate design/backend/api/*.yaml +swagger-cli validate design/backend/api/spec/*.yaml ``` #### 검증 결과 ``` -design/backend/api/user-service-api.yaml is valid -design/backend/api/meeting-service-api.yaml is valid -design/backend/api/stt-service-api.yaml is valid -design/backend/api/ai-service-api.yaml is valid -design/backend/api/notification-service-api.yaml is valid +design/backend/api/spec/user-service-api.yaml is valid +design/backend/api/spec/meeting-service-api.yaml is valid +design/backend/api/spec/stt-service-api.yaml is valid +design/backend/api/spec/ai-service-api.yaml is valid +design/backend/api/spec/rag-service-api.yaml is valid +design/backend/api/spec/notification-service-api.yaml is valid ``` --- @@ -413,16 +470,17 @@ design/backend/api/notification-service-api.yaml is valid | 서비스 | API 개수 | 주요 기능 | |--------|---------|----------| | User Service | 4 | 사용자 인증 | -| Meeting Service | 17 | 회의, 회의록, Todo, 실시간 협업 | +| Meeting Service | 17 | 회의, 회의록, Todo 관리 | | STT Service | 12 | 음성 녹음, 변환, 화자 식별 | -| AI Service | 8 | AI 회의록, Todo 추출, RAG 검색 | +| AI Service | 8 | AI 회의록, Todo 추출, RAG 연동 | +| RAG Service | 9 | 용어집/문서/회의록 검색 | | Notification Service | 6 | 알림 발송, 설정 관리 | -| **합계** | **47** | | +| **합계** | **56** | | ### 유저스토리 커버리지 -- **전체 유저스토리**: 25개 -- **API로 구현된 유저스토리**: 25개 +- **전체 유저스토리**: 28개 +- **API로 구현된 유저스토리**: 28개 - **커버리지**: 100% --- @@ -432,6 +490,8 @@ design/backend/api/notification-service-api.yaml is valid | 버전 | 작성일 | 작성자 | 변경 내용 | |------|--------|--------|----------| | 1.0 | 2025-01-23 | 길동 (아키텍트), 준호 (Backend Developer) | 초안 작성 (5개 마이크로서비스) | +| 2.0 | 2025-01-25 | 준호 (Backend Developer) | Todo 관리 기능 추가, 실시간 협업 설계 | +| 2.1 | 2025-01-29 | 동욱 (Backend Developer) | RAG Service 추가, 불필요한 API 정리 (6개 마이크로서비스) | --- diff --git a/design/backend/api/spec/rag-service-api.yaml b/design/backend/api/spec/rag-service-api.yaml new file mode 100644 index 0000000..c6ae906 --- /dev/null +++ b/design/backend/api/spec/rag-service-api.yaml @@ -0,0 +1,636 @@ +openapi: 3.0.3 +info: + title: RAG Service API + description: | + 회의록 작성 서비스를 위한 RAG (Retrieval-Augmented Generation) 서비스 API + + **주요 기능**: + - 용어집 검색 (PostgreSQL + pgvector) + - 관련자료 검색 (Azure AI Search) + - 회의록 유사도 검색 (Vector DB) + + **기술 스택**: Python 3.11+, FastAPI, PostgreSQL+pgvector, Azure AI Search, Claude AI, Redis + version: 1.0.0 + contact: + name: AI Specialist (서연), Backend Developer (준호) + +servers: + - url: http://localhost:8000 + description: 로컬 개발 서버 + - url: https://api-rag.hgzero.com + description: 운영 서버 + +tags: + - name: Terms + description: 용어집 검색 API + - name: Documents + description: 관련자료 검색 API + - name: Minutes + description: 회의록 유사도 검색 API + +paths: + # ============================================================================ + # Terms APIs - 용어집 검색 + # ============================================================================ + + /api/rag/terms/search: + post: + tags: + - Terms + summary: 용어 검색 (Hybrid) + description: | + 키워드 검색과 벡터 유사도 검색을 결합한 하이브리드 검색 + + **검색 방식**: + - `keyword`: 키워드 매칭 (PostgreSQL LIKE) + - `vector`: 벡터 유사도 (Cosine Similarity) + - `hybrid`: 키워드 + 벡터 가중합 (기본값) + + **성능**: < 500ms (캐시 HIT 시 < 50ms) + x-user-story: UFR-RAG-010 + x-controller: TermsController + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/TermSearchRequest' + examples: + hybrid_search: + summary: 하이브리드 검색 (기본) + value: + query: "마이크로서비스 아키텍처" + search_type: "hybrid" + top_k: 5 + confidence_threshold: 0.7 + keyword_search: + summary: 키워드 검색만 + value: + query: "Docker" + search_type: "keyword" + top_k: 3 + confidence_threshold: 0.6 + responses: + '200': + description: 검색 결과 + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/TermSearchResult' + '400': + $ref: '#/components/responses/BadRequest' + '500': + $ref: '#/components/responses/InternalError' + + /api/rag/terms/{termId}: + get: + tags: + - Terms + summary: 용어 상세 조회 + description: 용어 ID로 용어 정보 조회 + x-user-story: UFR-RAG-010 + x-controller: TermsController + parameters: + - name: termId + in: path + required: true + schema: + type: string + description: 용어 ID + responses: + '200': + description: 용어 정보 + content: + application/json: + schema: + $ref: '#/components/schemas/Term' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalError' + + /api/rag/terms/{termId}/explain: + post: + tags: + - Terms + summary: 맥락 기반 용어 설명 생성 + description: | + Claude AI를 활용한 맥락 기반 용어 설명 생성 + + **생성 과정**: + 1. 현재 회의 맥락 분석 + 2. RAG 검색 (관련 회의록, 문서, 업무 이력) + 3. Claude AI 호출 (프롬프트 엔지니어링) + 4. 결과 생성 및 캐싱 + + **성능**: < 3초 (Claude API 호출 포함) + x-user-story: UFR-RAG-020 + x-controller: TermsController + parameters: + - name: termId + in: path + required: true + schema: + type: string + description: 용어 ID + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/TermExplainRequest' + responses: + '200': + description: 용어 설명 + content: + application/json: + schema: + $ref: '#/components/schemas/TermExplanation' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalError' + + # ============================================================================ + # Documents APIs - 관련자료 검색 + # ============================================================================ + + /api/rag/documents/search: + post: + tags: + - Documents + summary: 관련 문서 검색 + description: | + Azure AI Search 기반 하이브리드 검색 + Semantic Ranking + + **검색 기능**: + - 전체 텍스트 검색 + - 벡터 유사도 검색 + - Semantic Ranking (Azure AI Search) + - 필터링 (폴더, 문서 유형) + x-user-story: UFR-RAG-030 + x-controller: DocumentsController + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/DocumentSearchRequest' + responses: + '200': + description: 검색 결과 + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/DocumentSearchResult' + '400': + $ref: '#/components/responses/BadRequest' + '500': + $ref: '#/components/responses/InternalError' + + /api/rag/documents/stats: + get: + tags: + - Documents + summary: 문서 통계 조회 + description: 전체 문서 통계 정보 조회 + x-controller: DocumentsController + responses: + '200': + description: 문서 통계 + content: + application/json: + schema: + $ref: '#/components/schemas/DocumentStats' + '500': + $ref: '#/components/responses/InternalError' + + # ============================================================================ + # Minutes APIs - 회의록 유사도 검색 + # ============================================================================ + + /api/rag/minutes/search: + post: + tags: + - Minutes + summary: 회의록 벡터 검색 + description: | + 회의록 내용 기반 벡터 유사도 검색 + + **검색 방식**: Cosine Similarity (임계값 70% 이상) + **성능**: < 1초 (캐시 HIT 시 < 100ms) + x-user-story: UFR-RAG-030 + x-controller: MinutesController + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/MinutesSearchRequest' + responses: + '200': + description: 검색 결과 + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/MinutesSearchResult' + '400': + $ref: '#/components/responses/BadRequest' + '500': + $ref: '#/components/responses/InternalError' + + /api/rag/minutes/{minutesId}: + get: + tags: + - Minutes + summary: 회의록 상세 조회 + description: 회의록 ID로 상세 정보 조회 + x-user-story: UFR-RAG-030 + x-controller: MinutesController + parameters: + - name: minutesId + in: path + required: true + schema: + type: string + description: 회의록 ID + responses: + '200': + description: 회의록 정보 + content: + application/json: + schema: + $ref: '#/components/schemas/RagMinutes' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalError' + + /api/rag/minutes/related: + post: + tags: + - Minutes + summary: 연관 회의록 조회 + description: | + 벡터 유사도 기반 연관 회의록 조회 (Redis 캐싱) + + **처리 과정**: + 1. Redis 캐시 조회 + 2. 캐시 MISS 시 DB 조회 + 3. 회의록 내용을 벡터 임베딩으로 변환 + 4. 벡터 유사도 검색 (자기 자신 제외) + 5. 결과 Redis 캐싱 (TTL: 1시간) + + **성능**: < 1초 (캐시 HIT 시 < 100ms) + x-user-story: UFR-RAG-030 + x-controller: MinutesController + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/RelatedMinutesRequest' + responses: + '200': + description: 연관 회의록 목록 + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/RelatedMinutesResponse' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalError' + + /api/rag/minutes/stats: + get: + tags: + - Minutes + summary: 회의록 통계 조회 + description: 전체 회의록 통계 정보 조회 + x-controller: MinutesController + responses: + '200': + description: 회의록 통계 + content: + application/json: + schema: + $ref: '#/components/schemas/MinutesStats' + '500': + $ref: '#/components/responses/InternalError' + +# ============================================================================ +# Components +# ============================================================================ + +components: + schemas: + # Terms Schemas + TermSearchRequest: + type: object + required: + - query + properties: + query: + type: string + description: 검색 쿼리 + example: "마이크로서비스 아키텍처" + search_type: + type: string + enum: [keyword, vector, hybrid] + default: hybrid + description: 검색 방식 + top_k: + type: integer + default: 5 + minimum: 1 + maximum: 20 + description: 반환할 최대 결과 수 + confidence_threshold: + type: number + format: float + default: 0.7 + minimum: 0.0 + maximum: 1.0 + description: 최소 신뢰도 임계값 + + Term: + type: object + properties: + term_id: + type: string + description: 용어 ID + term_name: + type: string + description: 용어명 + definition: + type: string + description: 용어 정의 + context: + type: string + description: 사용 맥락 + category: + type: string + description: 카테고리 + created_at: + type: string + format: date-time + description: 생성 일시 + updated_at: + type: string + format: date-time + description: 수정 일시 + + TermSearchResult: + type: object + properties: + term: + $ref: '#/components/schemas/Term' + relevance_score: + type: number + format: float + description: 관련도 점수 (0.0 ~ 1.0) + match_type: + type: string + enum: [keyword, vector, hybrid] + description: 매칭 방식 + + TermExplainRequest: + type: object + required: + - meeting_context + properties: + meeting_context: + type: string + description: 현재 회의 맥락 (회의 주제, 안건 등) + example: "마이크로서비스 아키텍처 도입 검토 회의" + + TermExplanation: + type: object + properties: + term: + $ref: '#/components/schemas/Term' + explanation: + type: string + description: 맥락 기반 설명 (Claude AI 생성) + context_documents: + type: array + items: + type: string + description: 참조 문서 목록 + generated_by: + type: string + default: Claude 3.5 Sonnet + description: 생성 모델 + cached: + type: boolean + description: 캐시 여부 + + # Documents Schemas + DocumentSearchRequest: + type: object + required: + - query + properties: + query: + type: string + description: 검색 쿼리 + top_k: + type: integer + default: 5 + minimum: 1 + maximum: 20 + folder: + type: string + description: 폴더 필터 + document_type: + type: string + description: 문서 유형 필터 + semantic_ranking: + type: boolean + default: true + description: Semantic Ranking 사용 여부 + relevance_threshold: + type: number + format: float + default: 0.6 + description: 최소 관련도 임계값 + + DocumentSearchResult: + type: object + properties: + document_id: + type: string + title: + type: string + content: + type: string + description: 문서 내용 (요약) + folder: + type: string + document_type: + type: string + relevance_score: + type: number + format: float + created_at: + type: string + format: date-time + + DocumentStats: + type: object + properties: + total_documents: + type: integer + by_type: + type: object + additionalProperties: + type: integer + total_chunks: + type: integer + + # Minutes Schemas + MinutesSearchRequest: + type: object + required: + - query + properties: + query: + type: string + description: 검색 쿼리 (회의 내용) + top_k: + type: integer + default: 5 + minimum: 1 + maximum: 20 + similarity_threshold: + type: number + format: float + default: 0.7 + minimum: 0.0 + maximum: 1.0 + + RagMinutes: + type: object + properties: + minutes_id: + type: string + title: + type: string + full_content: + type: string + description: 전체 회의록 내용 + meeting_date: + type: string + format: date-time + participants: + type: array + items: + type: string + created_at: + type: string + format: date-time + + MinutesSearchResult: + type: object + properties: + minutes: + $ref: '#/components/schemas/RagMinutes' + similarity_score: + type: number + format: float + description: 유사도 점수 (0.0 ~ 1.0) + + RelatedMinutesRequest: + type: object + required: + - minute_id + properties: + minute_id: + type: string + description: 기준 회의록 ID + top_k: + type: integer + default: 3 + minimum: 1 + maximum: 10 + similarity_threshold: + type: number + format: float + default: 0.7 + + RelatedMinutesResponse: + type: object + properties: + minutes: + $ref: '#/components/schemas/RagMinutes' + similarity_score: + type: number + format: float + + MinutesStats: + type: object + properties: + total_minutes: + type: integer + indexed_count: + type: integer + average_similarity: + type: number + format: float + + # Error Schemas + ErrorResponse: + type: object + properties: + status: + type: string + enum: [error] + code: + type: string + message: + type: string + details: + type: object + + responses: + BadRequest: + description: 잘못된 요청 + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + example: + status: error + code: BAD_REQUEST + message: 검색 쿼리가 비어 있습니다 + + NotFound: + description: 리소스를 찾을 수 없음 + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + example: + status: error + code: NOT_FOUND + message: 용어를 찾을 수 없습니다 + + InternalError: + description: 서버 내부 오류 + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + example: + status: error + code: INTERNAL_ERROR + message: 서버 오류가 발생했습니다 diff --git a/design/backend/sequence/inner/ai-결정사항제안.puml b/design/backend/sequence/inner/ai-결정사항제안.puml deleted file mode 100644 index 9fb40d0..0000000 --- a/design/backend/sequence/inner/ai-결정사항제안.puml +++ /dev/null @@ -1,250 +0,0 @@ -@startuml -!theme mono - -title AI Service 내부 시퀀스 - 결정사항제안 - -participant "SuggestionController" as Controller -participant "DecisionSuggestionService" as Service -participant "LLMClient" as LLM -participant "TranscriptRepository" as TranscriptRepo -database "Azure OpenAI<>" as OpenAI -database "Redis Cache<>" as Cache -database "PostgreSQL<>" as DB - -== 실시간 결정사항 제안 요청 == - -note over Controller - TranscriptService로부터 호출 - (회의록 자동작성 프로세스 내부) -end note - -Controller -> Service: suggestDecisions(meetingId, transcriptText) -activate Service - -== 회의 맥락 조회 == - -Service -> TranscriptRepo: getMeetingContext(meetingId) -activate TranscriptRepo - -TranscriptRepo -> DB: 회의 맥락 조회\n(회의정보, 참석자) -activate DB - -DB --> TranscriptRepo: 회의 정보 -deactivate DB - -TranscriptRepo --> Service: meetingContext -deactivate TranscriptRepo - -Service -> Cache: GET decisions:{meetingId} -activate Cache -note right - 이전에 감지한 결정사항 조회 - (중복 제거용) -end note - -Cache --> Service: previousDecisions -deactivate Cache - -== LLM 기반 결정사항 패턴 감지 == - -Service -> Service: 결정사항 감지 프롬프트 생성 -note right - 시스템 프롬프트: - - 역할: 결정사항 추출 전문가 - - 목표: 대화에서 결정 패턴 감지 - - 결정 패턴 예시: - - "~하기로 했습니다" - - "~로 결정했습니다" - - "~하는 것으로 합의했습니다" - - "~로 진행하겠습니다" - - "~은 이렇게 처리하겠습니다" - - 사용자 프롬프트: - - 회의 참석자: {participants} - - 이미 감지한 결정: {previousDecisions} - - 현재 대화 내용: {transcriptText} - - 지시사항: - - 위 패턴이 포함된 문장 찾기 - - 결정 내용 구조화 - - 결정자/참여자 식별 - - 결정 카테고리 분류 - - 신뢰도 점수 계산 - - 응답 형식: - { - "decisions": [ - { - "content": "결정 내용", - "category": "기술|일정|리소스|정책|기타", - "decisionMaker": "결정자 이름", - "participants": ["참여자1", "참여자2"], - "confidence": 0.0-1.0, - "extractedFrom": "원문 발췌", - "context": "결정 배경" - } - ] - } -end note - -Service -> LLM: detectDecisionPatterns(prompt) -activate LLM - -LLM -> OpenAI: POST /chat/completions -activate OpenAI -note right - 요청 파라미터: - - model: gpt-4o - - temperature: 0.2 - (정확한 패턴 감지 위해 낮은 값) - - response_format: json_object - - max_tokens: 1500 -end note - -OpenAI -> OpenAI: 대화 텍스트 분석 -note right - 처리 단계: - 1. 문장별로 결정 패턴 검사 - 2. "하기로 함" 등 키워드 탐지 - 3. 결정 내용 추출 및 정리 - 4. 발언자 식별 (누가 결정했나) - 5. 결정 맥락 파악 - 6. 신뢰도 계산 - - 명확한 결정 표현: 0.9-1.0 - - 암묵적 합의: 0.7-0.9 - - 추정: 0.5-0.7 - 7. 카테고리 분류 - - 기술: 기술 스택, 아키텍처 - - 일정: 마감일, 일정 조정 - - 리소스: 인력, 예산 - - 정책: 프로세스, 규칙 -end note - -OpenAI --> LLM: 결정사항 제안 목록 (JSON) -deactivate OpenAI - -LLM --> Service: decisionSuggestions -deactivate LLM - -== 제안 검증 및 필터링 == - -Service -> Service: 결정사항 검증 -note right - 검증 기준: - - 신뢰도 70% 이상만 선택 - - 중복 제거 (이미 감지한 결정) - - 명확성 검증 - * 주어, 목적어가 명확한가? - * 결정 내용이 구체적인가? - - 카테고리별 정렬 - - 신뢰도 높은 순 정렬 -end note - -loop 각 제안마다 - - Service -> Service: 제안 메타데이터 보강 - note right - 추가 정보: - - 생성 시각 - - 회의 진행 시점 (분) - - 원문 위치 정보 - - 고유 ID (UUID) - end note - -end - -== 임시 캐시 저장 (선택적) == - -Service -> Cache: APPEND decisions:{meetingId} -activate Cache -note right - Redis에 임시 저장: - - Key: decisions:{meetingId} - - Value: JSON array (제안 목록) - - TTL: 2시간 (회의 시간) - - APPEND로 기존 목록에 추가 - - 목적: - - 중복 감지용 - - 재접속 시 복원용 -end note - -Cache --> Service: 저장 완료 -deactivate Cache - -== 응답 반환 == - -Service -> Service: 응답 데이터 구성 -note right - 프론트엔드 전달 형식: - { - "suggestions": [ - { - "id": "suggestion-uuid", - "content": "결정 내용", - "category": "기술", - "decisionMaker": "김철수", - "confidence": 0.85, - "extractedFrom": "원문 발췌", - "context": "결정 배경 설명" - } - ], - "totalCount": 제안 개수, - "timestamp": "생성 시각" - } -end note - -Service --> Controller: 결정사항 제안 목록 -deactivate Service - -Controller --> Controller: 이벤트 데이터에 포함하여 반환 -note right - TranscriptSummaryCreated 이벤트에 - decisionSuggestions 필드로 포함 - - 프론트엔드 처리: - - 오른쪽 "추천" 탭의 "결정사항" 섹션 표시 - - "적용" 버튼 활성화 - - 신뢰도 표시 (%) - - 카테고리별 아이콘 표시 - - 원문 보기 링크 제공 -end note - -== 사용자가 제안 적용 시 == - -note over Controller - 사용자가 "적용" 버튼 클릭 시: - 프론트엔드에서 직접 Meeting Service 호출 - - PUT /api/meetings/{meetingId}/transcript - Body: { - "addDecisionSection": { - "content": "결정 내용", - "category": "기술", - "decisionMaker": "김철수" - } - } - - Meeting Service에서 회의록의 - "결정사항" 섹션에 항목 추가 -end note - -note over Controller, DB -처리 시간: -- 맥락 조회: 100-200ms -- LLM 패턴 감지: 2-3초 -- 검증 및 필터링: 100-200ms -- 캐시 저장: 50-100ms -총 처리 시간: 약 2.5-3.5초 - -특징: -- DB 영구 저장 없음 (임시 데이터) -- Redis 캐시만 활용 - * 중복 감지용 - * 재접속 복원용 -- 프론트엔드 메모리에서 관리 -- "적용" 시에만 회의록에 반영 -end note - -@enduml diff --git a/design/backend/sequence/inner/ai-논의사항제안.puml b/design/backend/sequence/inner/ai-논의사항제안.puml deleted file mode 100644 index 64aa9f5..0000000 --- a/design/backend/sequence/inner/ai-논의사항제안.puml +++ /dev/null @@ -1,231 +0,0 @@ -@startuml -!theme mono - -title AI Service 내부 시퀀스 - 논의사항제안 - -participant "SuggestionController" as Controller -participant "DiscussionSuggestionService" as Service -participant "LLMClient" as LLM -participant "TranscriptRepository" as TranscriptRepo -database "Azure OpenAI<>" as OpenAI -database "Redis Cache<>" as Cache -database "PostgreSQL<>" as DB - -== 실시간 논의사항 제안 요청 == - -note over Controller - TranscriptService로부터 호출 - (회의록 자동작성 프로세스 내부) -end note - -Controller -> Service: suggestDiscussionTopics(meetingId, transcriptText) -activate Service - -== 회의 맥락 정보 조회 == - -Service -> TranscriptRepo: getMeetingContext(meetingId) -activate TranscriptRepo - -TranscriptRepo -> DB: 회의 맥락 정보 조회\n(회의정보, 안건, 참석자) -activate DB - -DB --> TranscriptRepo: 회의 정보 -deactivate DB - -TranscriptRepo --> Service: meetingContext -deactivate TranscriptRepo - -Service -> TranscriptRepo: getPreviousDiscussions(meetingId) -activate TranscriptRepo - -TranscriptRepo -> DB: 이미 논의한 주제 조회\n(회의ID 기준) -activate DB - -DB --> TranscriptRepo: 이미 논의한 주제 목록 -deactivate DB - -TranscriptRepo --> Service: discussedTopics -deactivate TranscriptRepo - -== LLM 기반 논의사항 제안 생성 == - -Service -> Service: 제안 프롬프트 생성 -note right - 시스템 프롬프트: - - 역할: 회의 퍼실리테이터 - - 목표: 회의 안건 대비 빠진 논의 찾기 - - 사용자 프롬프트: - - 회의 안건: {agenda} - - 이미 논의한 주제: {discussedTopics} - - 현재 대화 내용: {transcriptText} - - 참석자 정보: {participants} - - 지시사항: - - 안건에 있지만 아직 안 다룬 항목 찾기 - - 대화 흐름상 빠진 중요 논의 식별 - - 추가하면 좋을 주제 제안 - - 우선순위 부여 - - 응답 형식: - { - "suggestions": [ - { - "topic": "논의 주제", - "reason": "제안 이유", - "priority": "HIGH|MEDIUM|LOW", - "relatedAgenda": "관련 안건 항목", - "estimatedTime": 분 단위 예상 시간 - } - ] - } -end note - -Service -> LLM: generateDiscussionSuggestions(prompt) -activate LLM - -LLM -> OpenAI: POST /chat/completions -activate OpenAI -note right - 요청 파라미터: - - model: gpt-4o - - temperature: 0.4 - - response_format: json_object - - max_tokens: 1500 -end note - -OpenAI -> OpenAI: 회의 맥락 분석 -note right - 분석 단계: - 1. 안건 항목별 진행 상황 체크 - 2. 이미 논의한 주제와 비교 - 3. 현재 대화 맥락 이해 - 4. 빠진 중요 논의 식별 - 5. 추가 제안 생성 - 6. 우선순위 결정 - - HIGH: 안건 필수 항목 - - MEDIUM: 중요하지만 선택적 - - LOW: 추가 고려사항 -end note - -OpenAI --> LLM: 논의사항 제안 목록 (JSON) -deactivate OpenAI - -LLM --> Service: discussionSuggestions -deactivate LLM - -== 제안 검증 및 필터링 == - -Service -> Service: 제안 품질 검증 -note right - 검증 기준: - - 중복 제거 (이미 논의한 주제) - - 관련성 검증 (회의 목적과 부합) - - 우선순위별 정렬 - - 최대 5개까지만 선택 - (너무 많으면 오히려 방해) -end note - -loop 각 제안마다 - - Service -> Service: 제안 메타데이터 보강 - note right - 추가 정보: - - 생성 시각 - - 제안 신뢰도 점수 - - 회의 진행 시점 (분) - - 고유 ID (UUID) - end note - -end - -== 임시 캐시 저장 (선택적) == - -Service -> Cache: SET suggestions:discussion:{meetingId} -activate Cache -note right - Redis에 임시 저장: - - Key: suggestions:discussion:{meetingId} - - Value: JSON array (제안 목록) - - TTL: 2시간 (회의 시간) - - 목적: - - 재접속 시 복원용 - - WebSocket 재연결 대응 -end note - -Cache --> Service: 저장 완료 -deactivate Cache - -== 응답 반환 == - -Service -> Service: 응답 데이터 구성 -note right - 프론트엔드 전달 형식: - { - "suggestions": [ - { - "id": "suggestion-uuid", - "topic": "논의 주제", - "reason": "제안 이유", - "priority": "HIGH", - "relatedAgenda": "관련 안건", - "estimatedTime": 10 - } - ], - "totalCount": 제안 개수, - "timestamp": "생성 시각" - } -end note - -Service --> Controller: 논의사항 제안 목록 -deactivate Service - -Controller --> Controller: 이벤트 데이터에 포함하여 반환 -note right - TranscriptSummaryCreated 이벤트에 - discussionSuggestions 필드로 포함 - - 프론트엔드 처리: - - 오른쪽 "추천" 탭에 표시 - - "적용" 버튼 활성화 - - 우선순위별 색상 표시 - * HIGH: 빨강 - * MEDIUM: 주황 - * LOW: 초록 -end note - -== 사용자가 제안 적용 시 == - -note over Controller - 사용자가 "적용" 버튼 클릭 시: - 프론트엔드에서 직접 Meeting Service 호출 - - PUT /api/meetings/{meetingId}/transcript - Body: { - "addDiscussionSection": { - "topic": "논의 주제", - "content": "" - } - } - - Meeting Service에서 회의록에 - 새로운 논의 섹션 추가 -end note - -note over Controller, DB -처리 시간: -- 맥락 정보 조회: 100-200ms -- LLM 제안 생성: 2-3초 -- 검증 및 필터링: 100-200ms -- 캐시 저장: 50-100ms -총 처리 시간: 약 2.5-3.5초 - -특징: -- DB 영구 저장 없음 (임시 데이터) -- Redis 캐시만 활용 (재접속 복원용) -- 프론트엔드 메모리에서 관리 -- "적용" 시에만 회의록에 반영 -end note - -@enduml diff --git a/design/backend/sequence/inner/ai-맥락기반용어설명.puml b/design/backend/sequence/inner/ai-맥락기반용어설명.puml index ada0a21..27d6ff7 100644 --- a/design/backend/sequence/inner/ai-맥락기반용어설명.puml +++ b/design/backend/sequence/inner/ai-맥락기반용어설명.puml @@ -30,10 +30,17 @@ activate Service == 용어 정보 조회 == +note over Service + **구현 방식**: AI Service → RAG Service API 호출 + GET /api/rag/terms/{termId} + - PostgreSQL + pgvector에서 조회 + - Redis 캐싱 적용 +end note + Service -> Repo: getTermInfo(term) activate Repo -Repo -> DB: 용어 정보 조회\n(용어사전에서 정의 및 카테고리) +Repo -> DB: 용어 정보 조회\n(용어사전에서 정의 및 카테고리)\n**실제: RAG Service API 호출** activate DB DB --> Repo: 기본 용어 정의 diff --git a/design/backend/sequence/inner/ai-전문용어감지.puml b/design/backend/sequence/inner/ai-전문용어감지.puml index 7865301..1ee01aa 100644 --- a/design/backend/sequence/inner/ai-전문용어감지.puml +++ b/design/backend/sequence/inner/ai-전문용어감지.puml @@ -26,11 +26,19 @@ activate Service == 용어 사전 조회 == +note over Service + **구현 방식**: AI Service → RAG Service API 호출 + POST /api/rag/terms/search + - 하이브리드 검색 (키워드 + 벡터) + - PostgreSQL + pgvector + - Redis 캐싱 +end note + par "조직별 용어 사전" Service -> Repo: getOrganizationTerms(organizationId) activate Repo - Repo -> DB: 조직 전문용어 조회\n(조직ID 기준, 용어/정의/카테고리) + Repo -> DB: 조직 전문용어 조회\n(조직ID 기준, 용어/정의/카테고리)\n**실제: RAG Service API 호출** activate DB DB --> Repo: 조직 전문용어 목록 @@ -43,7 +51,7 @@ else Service -> Repo: getIndustryTerms(industry) activate Repo - Repo -> DB: 산업 표준용어 조회\n(산업분류 기준, 용어/정의/카테고리) + Repo -> DB: 산업 표준용어 조회\n(산업분류 기준, 용어/정의/카테고리)\n**실제: RAG Service API 호출** activate DB DB --> Repo: 산업 표준용어 목록 diff --git a/design/backend/sequence/inner/ai-회의록개선.puml b/design/backend/sequence/inner/ai-회의록개선.puml deleted file mode 100644 index 02688fa..0000000 --- a/design/backend/sequence/inner/ai-회의록개선.puml +++ /dev/null @@ -1,167 +0,0 @@ -@startuml -!theme mono - -title AI Service 내부 시퀀스 - 섹션AI요약재생성 - -participant "SectionController" as Controller -participant "SectionSummaryService" as Service -participant "LLMClient" as LLM -participant "SectionRepository" as Repo -database "Azure OpenAI<>" as OpenAI -database "PostgreSQL<>" as DB - -== 섹션 AI 요약 재생성 요청 수신 == - -note over Controller - API 요청: - POST /api/ai/sections/{sectionId}/regenerate-summary - Body: { - "sectionContent": "**논의 사항:**\n- AI 기반...", - "meetingId": "550e8400-..." - } -end note - -Controller -> Service: regenerateSummary(sectionId, sectionContent, meetingId) -activate Service - -== 회의 맥락 조회 (선택적) == - -Service -> Repo: getMeetingContext(meetingId) -activate Repo - -Repo -> DB: 회의 정보 조회\n- 회의 제목\n- 참석자\n- 안건 -activate DB - -DB --> Repo: 회의 맥락 정보 -deactivate DB - -Repo --> Service: meetingContext -deactivate Repo - -note right of Service - 회의 맥락을 통해 - 더 정확한 요약 생성 - - 예: "신규 프로젝트 킥오프" - → 기술/일정 중심 요약 -end note - -== 프롬프트 생성 == - -Service -> Service: 요약 프롬프트 구성 -note right - 시스템 프롬프트: - - 역할: 회의록 섹션 요약 전문가 - - 목표: 핵심 내용을 2-3문장으로 압축 - - 스타일: 명확하고 간결한 문체 - - 사용자 프롬프트: - - 회의 맥락: {meetingContext} - - 섹션 내용: {sectionContent} - - 요구사항: - - 2-3문장으로 요약 - - 논의사항과 결정사항 구분 - - 핵심 키워드 포함 - - 불필요한 세부사항 제외 -end note - -== LLM 기반 요약 생성 == - -Service -> LLM: generateSummary(prompt, sectionContent) -activate LLM - -LLM -> OpenAI: POST /chat/completions -activate OpenAI -note right - 요청 파라미터: - - model: gpt-4o - - temperature: 0.3 - - max_tokens: 200 - - messages: [system, user] -end note - -OpenAI -> OpenAI: 섹션 내용 분석 및 요약 -note right - 처리 단계: - 1. 섹션 내용 파싱 - - 논의사항 추출 - - 결정사항 추출 - - 보류사항 추출 - - 2. 핵심 내용 식별 - - 중요도 평가 - - 키워드 추출 - - 3. 요약 생성 - - 2-3문장으로 압축 - - 논의→결정 흐름 반영 - - 명확한 문장 구성 - - 4. 품질 검증 - - 길이 확인 (150자 이내) - - 핵심 누락 여부 확인 -end note - -OpenAI --> LLM: 생성된 AI 요약 -deactivate OpenAI - -LLM --> Service: summaryText -deactivate LLM - -== 생성된 요약 저장 (선택적) == - -Service -> Repo: saveSectionSummary(sectionId, summaryText) -activate Repo - -Repo -> DB: AI 요약 저장 -activate DB -note right - 저장 데이터: - - section_id - - summary_text - - generated_at - - model: "gpt-4o" - - token_usage -end note - -DB --> Repo: 저장 완료 -deactivate DB - -Repo --> Service: 완료 -deactivate Repo - -== 응답 반환 == - -Service -> Service: 응답 데이터 구성 -note right - 응답 데이터: - - summary: "AI 기반 회의록 자동화..." - - generatedAt: "2025-01-23T11:00:00Z" -end note - -Service --> Controller: 요약 생성 완료 응답 -deactivate Service - -Controller --> Controller: 200 OK 응답 반환 - -note over Controller, DB -처리 시간: -- 회의 맥락 조회: 50-100ms -- 프롬프트 구성: 10-20ms -- LLM 요약 생성: 2-4초 -- 저장 처리: 50-100ms -총 처리 시간: 약 2-5초 - -정책: -- 섹션 내용이 변경되면 요약도 재생성 -- 이전 요약은 이력으로 보관 -- 사용자는 생성된 요약을 수정 가능 -- 수정된 요약은 AI 재생성 가능 - -처리량: -- max_tokens: 200 (요약은 짧음) -- 비용 효율적 (전체 회의록 대비) -end note - -@enduml diff --git a/design/backend/sequence/inner/meeting-Todo완료처리.puml b/design/backend/sequence/inner/meeting-Todo완료처리.puml deleted file mode 100644 index 11d7517..0000000 --- a/design/backend/sequence/inner/meeting-Todo완료처리.puml +++ /dev/null @@ -1,203 +0,0 @@ -@startuml meeting-Todo완료처리 -!theme mono - -title Meeting Service - Todo완료처리 내부 시퀀스 - -participant "TodoController" as Controller -participant "TodoService" as Service -participant "TodoRepository" as TodoRepo -participant "MinutesRepository" as MinutesRepo -participant "CollaborationService" as CollabService -database "Meeting DB<>" as DB -database "Redis Cache<>" as Cache -queue "Azure Event Hubs<>" as EventHub -participant "WebSocket<>" as WebSocket - -[-> Controller: PATCH /todos/{todoId}/complete -activate Controller - -note over Controller -경로 변수: todoId -사용자 정보: userId, userName, email -end note - -Controller -> Controller: todoId 유효성 검증 - -Controller -> Service: completeTodo(todoId, userId) -activate Service - -' Todo 정보 조회 -Service -> TodoRepo: findById(todoId) -activate TodoRepo -TodoRepo -> DB: Todo 정보 조회 -activate DB -DB --> TodoRepo: Todo 정보 -deactivate DB -TodoRepo --> Service: Todo -deactivate TodoRepo - -note over Service -비즈니스 규칙 검증: -- Todo 존재 확인 -- 완료 권한 확인 (담당자만) -- 상태 확인 (이미 완료된 경우 처리) -end note - -Service -> Service: Todo 존재 확인 - -Service -> Service: 완료 권한 검증\n(담당자만 가능) - -alt 권한 없음 - Service --> Controller: 403 Forbidden\n담당자만 완료 가능 - note right - 에러 응답 형식: - { - "error": { - "code": "INSUFFICIENT_PERMISSION", - "message": "Todo 완료 권한이 없습니다", - "details": "담당자만 Todo를 완료할 수 있습니다", - "timestamp": "2025-10-23T12:00:00Z", - "path": "/api/todos/{todoId}/complete" - } - } - end note - return 403 Forbidden -else 권한 있음 - alt Todo가 이미 완료됨 - Service --> Controller: 409 Conflict\n이미 완료된 Todo - note right - 에러 응답 형식: - { - "error": { - "code": "TODO_ALREADY_COMPLETED", - "message": "이미 완료된 Todo입니다", - "details": "해당 Todo는 이미 완료 처리되었습니다", - "timestamp": "2025-10-23T12:00:00Z", - "path": "/api/todos/{todoId}/complete" - } - } - end note - return 409 Conflict - else 완료 처리 가능 - ' 완료 확인 다이얼로그 (프론트엔드에서 처리됨) - - ' Todo 완료 처리 - Service -> TodoRepo: markAsCompleted(todoId, userId) - activate TodoRepo - TodoRepo -> DB: Todo 완료 상태 업데이트 - activate DB - DB --> TodoRepo: 업데이트 완료 - deactivate DB - TodoRepo --> Service: 업데이트 성공 - deactivate TodoRepo - - note over Service - 회의록 실시간 반영: - - 관련 회의록 섹션 자동 업데이트 - - 완료 표시 추가 - - 완료 시간 및 완료자 정보 기록 - end note - - ' 회의록 섹션 업데이트 - Service -> MinutesRepo: updateTodoStatus(todoId, "COMPLETED") - activate MinutesRepo - MinutesRepo -> DB: 회의록 섹션의 Todo 상태 업데이트 - activate DB - DB --> MinutesRepo: 업데이트 완료 - deactivate DB - MinutesRepo --> Service: 업데이트 성공 - deactivate MinutesRepo - - ' 회의록의 모든 Todo 완료 여부 확인 - Service -> TodoRepo: countPendingTodos(minutesId) - activate TodoRepo - TodoRepo -> DB: 미완료 Todo 개수 조회 - activate DB - DB --> TodoRepo: 미완료 Todo 개수 - deactivate DB - TodoRepo --> Service: int pendingCount - deactivate TodoRepo - - ' 캐시 무효화 - Service -> Cache: DELETE dashboard:{assigneeId} - activate Cache - Cache --> Service: 삭제 완료 - deactivate Cache - - Service -> Cache: DELETE minutes:detail:{minutesId} - activate Cache - Cache --> Service: 삭제 완료 - deactivate Cache - - note over Service - 실시간 협업: - - WebSocket으로 회의록 업데이트 전송 - - 모든 참석자에게 완료 상태 동기화 - end note - - ' 실시간 동기화 - Service -> CollabService: broadcastTodoUpdate(minutesId, todoId, status) - activate CollabService - - note over CollabService - WebSocket 메시지 형식: - { - "type": "TODO_COMPLETED", - "todoId": "uuid", - "minutesId": "uuid", - "completedBy": { - "userId": "...", - "userName": "..." - }, - "completedAt": "...", - "timestamp": "..." - } - end note - - CollabService -> WebSocket: broadcast to room:{minutesId} - activate WebSocket - WebSocket --> CollabService: 전송 완료 - deactivate WebSocket - CollabService --> Service: 동기화 완료 - deactivate CollabService - - note over Service - 비동기 이벤트 발행: - - 완료 알림 발송 - - 모든 Todo 완료 시 전체 완료 알림 - end note - - alt 모든 Todo 완료됨 - Service -> EventHub: publish(AllTodosCompleted)\n{\n minutesId, meetingId,\n completedAt, totalTodos\n} - activate EventHub - EventHub --> Service: 발행 완료 - deactivate EventHub - else 일부 Todo만 완료 - Service -> EventHub: publish(TodoCompleted)\n{\n todoId, minutesId,\n completedBy, completedAt\n} - activate EventHub - EventHub --> Service: 발행 완료 - deactivate EventHub - end - - Service --> Controller: TodoCompleteResponse - deactivate Service - - note over Controller - 응답 데이터: - { - "todoId": "uuid", - "status": "COMPLETED", - "completedAt": "2025-01-24T10:00:00", - "completedBy": "userId", - "minutesId": "uuid", - "allTodosCompleted": true/false - } - end note - - return 200 OK\nTodoCompleteResponse - end -end - -deactivate Controller - -@enduml diff --git a/design/backend/sequence/inner/meeting-Todo할당.puml b/design/backend/sequence/inner/meeting-Todo할당.puml deleted file mode 100644 index 39ef3cc..0000000 --- a/design/backend/sequence/inner/meeting-Todo할당.puml +++ /dev/null @@ -1,158 +0,0 @@ -@startuml meeting-Todo할당 -!theme mono - -title Meeting Service - Todo할당 내부 시퀀스 - -participant "TodoController" as Controller -participant "TodoService" as Service -participant "TodoRepository" as TodoRepo -participant "MinutesRepository" as MinutesRepo -participant "CalendarService" as CalendarService -database "Meeting DB<>" as DB -database "Redis Cache<>" as Cache -queue "Azure Event Hubs<>" as EventHub - -[-> Controller: POST /todos -activate Controller - -note over Controller -요청 데이터: -{ - "content": "Todo 내용", - "assignee": "user@example.com", - "dueDate": "2025-01-30", - "priority": "HIGH" | "MEDIUM" | "LOW", - "minutesId": "uuid", - "sectionId": "uuid" // 회의록 섹션 위치 -} -사용자 정보: userId, userName, email -end note - -Controller -> Controller: 입력 검증\n- content 필수\n- assignee 필수\n- minutesId 필수 - -Controller -> Service: createTodo(request, userId) -activate Service - -note over Service -비즈니스 규칙: -- Todo 내용 최대 500자 -- 마감일은 현재보다 미래여야 함 -- 회의록 존재 확인 -- 담당자 유효성 검증 -end note - -' 회의록 존재 확인 -Service -> MinutesRepo: findById(minutesId) -activate MinutesRepo -MinutesRepo -> DB: 회의록 정보 조회 -activate DB -DB --> MinutesRepo: 회의록 정보 -deactivate DB -MinutesRepo --> Service: Minutes -deactivate MinutesRepo - -Service -> Service: 회의록 존재 확인 - -' Todo 생성 -Service -> Service: Todo 엔티티 생성\n- todoId (UUID)\n- 상태: IN_PROGRESS\n- 생성 정보 - -Service -> TodoRepo: save(todo) -activate TodoRepo -TodoRepo -> DB: Todo 정보 저장 -activate DB -DB --> TodoRepo: Todo 저장 완료 -deactivate DB -TodoRepo --> Service: Todo -deactivate TodoRepo - -note over Service -회의록 양방향 연결: -- 회의록 섹션에 Todo 뱃지 추가 -- Todo에서 회의록 섹션으로 링크 -end note - -' 회의록 섹션에 Todo 연결 -Service -> MinutesRepo: linkTodoToSection(sectionId, todoId) -activate MinutesRepo -MinutesRepo -> DB: 회의록 섹션에 Todo 연결 -activate DB -DB --> MinutesRepo: 업데이트 완료 -deactivate DB -MinutesRepo --> Service: 연결 성공 -deactivate MinutesRepo - -' 마감일이 있는 경우 캘린더 연동 -alt 마감일 설정됨 - Service -> CalendarService: createTodoEvent(todo) - activate CalendarService - - note over CalendarService - 캘린더 이벤트 생성: - - 제목: Todo 내용 - - 일시: 마감일 - - 참석자: 담당자 - - 리마인더: 마감 3일 전 - end note - - CalendarService -> CalendarService: 캘린더 이벤트 생성 - CalendarService --> Service: 이벤트 ID - deactivate CalendarService - - Service -> TodoRepo: updateCalendarEventId(todoId, eventId) - activate TodoRepo - TodoRepo -> DB: 캘린더 이벤트 ID 업데이트 - activate DB - DB --> TodoRepo: 업데이트 완료 - deactivate DB - TodoRepo --> Service: 업데이트 성공 - deactivate TodoRepo -end - -' 캐시 무효화 -Service -> Cache: DELETE dashboard:{assigneeId} -activate Cache -Cache --> Service: 삭제 완료 -deactivate Cache - -Service -> Cache: DELETE minutes:detail:{minutesId} -activate Cache -Cache --> Service: 삭제 완료 -deactivate Cache - -note over Service -비동기 이벤트 발행: -- 담당자에게 즉시 알림 발송 -- 회의록 실시간 업데이트 (WebSocket) -- 캘린더 초대 발송 -end note - -' 이벤트 발행 -Service -> EventHub: publish(TodoAssigned)\n{\n todoId, content, assignee,\n dueDate, minutesId, sectionId,\n assignedBy, calendarEventId\n} -activate EventHub -EventHub --> Service: 발행 완료 -deactivate EventHub - -Service --> Controller: TodoResponse -deactivate Service - -note over Controller -응답 데이터: -{ - "todoId": "uuid", - "content": "Todo 내용", - "assignee": "user@example.com", - "dueDate": "2025-01-30", - "priority": "HIGH", - "status": "IN_PROGRESS", - "minutesId": "uuid", - "sectionId": "uuid", - "calendarEventId": "...", - "createdAt": "2025-01-23T16:45:00" -} -end note - -return 201 Created\nTodoResponse - -deactivate Controller - -@enduml diff --git a/design/backend/sequence/inner/meeting-실시간수정동기화.puml b/design/backend/sequence/inner/meeting-실시간수정동기화.puml deleted file mode 100644 index 65a83bd..0000000 --- a/design/backend/sequence/inner/meeting-실시간수정동기화.puml +++ /dev/null @@ -1,87 +0,0 @@ -@startuml -!theme mono - -title 실시간 수정 동기화 내부 시퀀스 - -participant "WebSocket<>" as WebSocket -participant "CollaborationController" as Controller -participant "CollaborationService" as Service -participant "TranscriptService" as TranscriptService -participant "OperationalTransform" as OT -database "Redis Cache<>" as Cache -queue "Event Hub<>" as EventHub - -WebSocket -> Controller: onMessage(editOperation) -activate Controller - -Controller -> Service: processEdit(meetingId, operation, userId) -activate Service - -Service -> Cache: get(meeting:{id}:session) -activate Cache -note right of Cache -활성 세션 정보: -- 참여 사용자 목록 -- 현재 문서 버전 -- 락 정보 -end note -Cache --> Service: sessionData -deactivate Cache - -Service -> OT: transform(operation, concurrentOps) -activate OT -note right of OT -Operational Transform: -- 동시 편집 충돌 해결 -- 작업 순서 정렬 -- 일관성 보장 -end note -OT --> Service: transformedOp -deactivate OT - -Service -> TranscriptService: applyOperation(meetingId, transformedOp) -activate TranscriptService - -TranscriptService -> TranscriptService: updateContent() -note right of TranscriptService -내용 업데이트: -- 버전 증가 -- 변경 사항 적용 -- 임시 저장 -end note - -TranscriptService --> Service: updatedVersion -deactivate TranscriptService - -Service -> Cache: SET meeting:{id}:version\n(TTL: 1시간) -activate Cache -note right of Cache - 세션 버전 정보 캐싱: - - TTL: 1시간 - - 버전 정보 업데이트 - - 최신 상태 유지 -end note -Cache --> Service: OK -deactivate Cache - -Service ->> EventHub: publish(EditOperationEvent) -activate EventHub -note right of EventHub -다른 참여자에게 전파: -- WebSocket 브로드캐스트 -- 실시간 동기화 -end note -deactivate EventHub - -Service --> Controller: SyncResponse -deactivate Service - -Controller --> WebSocket: broadcast(editOperation) -deactivate Controller - -note over WebSocket -다른 클라이언트에게 -실시간 전송 -end note - -@enduml diff --git a/design/backend/sequence/inner/meeting-충돌해결.puml b/design/backend/sequence/inner/meeting-충돌해결.puml deleted file mode 100644 index a46cf07..0000000 --- a/design/backend/sequence/inner/meeting-충돌해결.puml +++ /dev/null @@ -1,92 +0,0 @@ -@startuml -!theme mono - -title 충돌 해결 내부 시퀀스 - -participant "WebSocket<>" as WebSocket -participant "CollaborationController" as Controller -participant "CollaborationService" as Service -participant "ConflictResolver" as Resolver -participant "TranscriptService" as TranscriptService -database "Redis Cache<>" as Cache -queue "Event Hub<>" as EventHub - -WebSocket -> Controller: onConflict(conflictData) -activate Controller - -Controller -> Service: resolveConflict(meetingId, conflictData) -activate Service - -Service -> Cache: get(meeting:{id}:conflicts) -activate Cache -note right of Cache -충돌 목록 조회: -- 발생 시간 -- 관련 사용자 -- 충돌 영역 -end note -Cache --> Service: conflictList -deactivate Cache - -Service -> Resolver: analyzeConflict(conflictData) -activate Resolver - -Resolver -> Resolver: detectConflictType() -note right of Resolver -충돌 유형 분석: -- 동일 위치 수정 -- 삭제-수정 충돌 -- 순서 변경 충돌 -end note - -Resolver -> Resolver: applyStrategy() -note right of Resolver -해결 전략: -- 자동 병합 (단순 충돌) -- 최신 우선 (시간 기반) -- 수동 해결 필요 (복잡) -end note - -Resolver --> Service: resolutionResult -deactivate Resolver - -alt auto-resolved - Service -> TranscriptService: applyResolution(meetingId, resolution) - activate TranscriptService - TranscriptService --> Service: mergedContent - deactivate TranscriptService - - Service -> Cache: del(meeting:{id}:conflicts) - activate Cache - Cache --> Service: OK - deactivate Cache - -else manual-required - Service -> Cache: SET meeting:{id}:conflicts\n(TTL: 1시간) - activate Cache - note right of Cache - 충돌 정보 캐싱: - - TTL: 1시간 - - 충돌 정보 저장 - - 수동 해결 대기 - end note - Cache --> Service: OK - deactivate Cache -end - -Service ->> EventHub: publish(ConflictResolvedEvent) -activate EventHub -note right of EventHub -이벤트 발행: -- 자동 해결: 동기화 -- 수동 필요: 알림 -end note -deactivate EventHub - -Service --> Controller: ResolutionResponse -deactivate Service - -Controller --> WebSocket: send(resolution) -deactivate Controller - -@enduml diff --git a/design/backend/sequence/inner/notification-Todo알림발송.puml b/design/backend/sequence/inner/notification-Todo알림발송.puml deleted file mode 100644 index dbc32db..0000000 --- a/design/backend/sequence/inner/notification-Todo알림발송.puml +++ /dev/null @@ -1,147 +0,0 @@ -@startuml -!theme mono - -title Notification Service - Todo알림발송 내부 시퀀스 - -participant "NotificationController" as Controller -participant "NotificationService" as Service -participant "EmailTemplateService" as TemplateService -participant "NotificationRepository" as Repository -participant "EmailClient" as EmailClient -database "Notification DB" as DB -queue "Azure Event Hubs<>" as EventHub -participant "Email Service<>" as EmailService - -== TodoAssigned 이벤트 수신 == - -EventHub -> Controller: TodoAssigned 이벤트 수신 -activate Controller -note right - 이벤트 데이터: - - todoId - - meetingId - - 담당자 (userId, userName, email) - - Todo 내용 - - 마감일 - - 우선순위 - - 회의록 링크 -end note - -Controller -> Service: sendTodoNotification(todoId, todoData) -activate Service - -== 알림 기록 생성 == - -Service -> Repository: createNotification(todoId, "TODO_ASSIGNED", assignee) -activate Repository - -Repository -> DB: 알림 정보 생성\n(알림ID, TodoID, 유형, 상태, 수신자, 생성일시) -activate DB -DB --> Repository: notificationId 반환 -deactivate DB - -Repository --> Service: NotificationEntity 반환 -deactivate Repository - -== 이메일 템플릿 생성 == - -Service -> TemplateService: generateTodoEmail(todoData) -activate TemplateService - -TemplateService -> TemplateService: 템플릿 로드 -note right - 템플릿 정보: - - 제목: "[TODO 할당] {Todo 내용}" - - 내용: Todo 상세 + 회의록 링크 - - 우선순위 뱃지 표시 -end note - -TemplateService -> TemplateService: 데이터 바인딩 -note right - 바인딩 데이터: - - Todo 내용 - - 마감일 - - 우선순위 - - 회의 제목 - - 회의록 링크 (해당 섹션) - - Todo 관리 페이지 링크 -end note - -TemplateService --> Service: EmailContent 반환 -deactivate TemplateService - -== 이메일 발송 == - -Service -> EmailClient: sendEmail(assignee.email, emailContent) -activate EmailClient - -EmailClient -> EmailService: SMTP 이메일 발송 -activate EmailService - -EmailService --> EmailClient: 발송 결과 -deactivate EmailService - -alt 발송 성공 - EmailClient --> Service: SUCCESS - - Service -> Repository: updateNotificationStatus(notificationId, "SENT") - activate Repository - Repository -> DB: 알림 상태 업데이트\n(상태=발송완료, 발송일시=현재시각) - activate DB - DB --> Repository: 업데이트 완료 - deactivate DB - Repository --> Service: 완료 - deactivate Repository - -else 발송 실패 - EmailClient --> Service: FAILED (errorMessage) - - Service -> Repository: updateNotificationStatus(notificationId, "FAILED") - activate Repository - Repository -> DB: 알림 상태 업데이트\n(상태=발송실패, 오류메시지=에러내용) - activate DB - DB --> Repository: 업데이트 완료 - deactivate DB - Repository --> Service: 완료 - deactivate Repository - - Service -> Service: 재시도 큐에 추가 -end - -deactivate EmailClient - -Service --> Controller: NotificationResponse\n(notificationId, status) -deactivate Service - -Controller --> EventHub: TodoNotificationSent 이벤트 발행\n(todoId, notificationId, status) -deactivate Controller - -== Todo 마감일 3일 전 리마인더 (스케줄링) == - -note over Service, EmailService - 별도 스케줄링 작업: - - 마감일 3일 전 자동 리마인더 - - 실행 주기: 1일 1회 - - 대상: 미완료 Todo - - 템플릿: "[리마인더] Todo 마감 3일 전" -end note - -note over Controller, EmailService -처리 시간: -- 알림 기록 생성: ~100ms -- 템플릿 생성: ~200ms -- 이메일 발송: ~500ms -- 총 처리 시간: ~800ms - -재시도 정책: -- 최대 3회 재시도 -- 재시도 간격: 5분, 15분, 30분 - -Todo 알림 유형: -1. 할당 알림 (즉시) -2. 마감일 3일 전 리마인더 -3. 마감일 1일 전 리마인더 -4. 마감일 당일 리마인더 -end note - -@enduml diff --git a/design/backend/sequence/inner/notification-리마인더발송.puml b/design/backend/sequence/inner/notification-리마인더발송.puml deleted file mode 100644 index db22aa3..0000000 --- a/design/backend/sequence/inner/notification-리마인더발송.puml +++ /dev/null @@ -1,158 +0,0 @@ -@startuml -!theme mono - -title Notification Service - 리마인더발송 내부 시퀀스 - -participant "SchedulerJob" as Scheduler -participant "ReminderService" as Service -participant "EmailTemplateService" as TemplateService -participant "NotificationRepository" as Repository -participant "EmailClient" as EmailClient -database "Notification DB" as DB -participant "Email Service<>" as EmailService - -== 스케줄링된 작업 실행 (회의 시작 30분 전) == - -Scheduler -> Scheduler: 30분 전 알림 대상 회의 조회 -activate Scheduler -note right - 조회 조건: - - 회의 시작 시간 - 30분 = NOW - - 회의 상태 = 예약됨 - - 리마인더 미발송 -end note - -Scheduler -> Service: sendMeetingReminders(meetingList) -activate Service - -loop 각 회의별 - Service -> Repository: checkReminderSent(meetingId) - activate Repository - - Repository -> DB: 리마인더 알림 조회\n(회의ID, 유형='REMINDER') - activate DB - DB --> Repository: 조회 결과 - deactivate DB - - Repository --> Service: 발송 여부 확인 - deactivate Repository - - alt 이미 발송됨 - Service -> Service: 스킵 - else 미발송 - - == 리마인더 알림 생성 == - - Service -> Repository: createNotification(meetingId, "REMINDER", participants) - activate Repository - - Repository -> DB: 리마인더 알림 생성\n(알림ID, 회의ID, 유형, 상태, 수신자, 생성일시) - activate DB - DB --> Repository: notificationId 반환 - deactivate DB - - Repository --> Service: NotificationEntity 반환 - deactivate Repository - - == 이메일 템플릿 생성 == - - Service -> TemplateService: generateReminderEmail(meetingData) - activate TemplateService - - TemplateService -> TemplateService: 템플릿 로드 - note right - 템플릿 정보: - - 제목: "[리마인더] {회의 제목} - 30분 후 시작" - - 내용: 회의 정보 + 참여 링크 - - 긴급도: 높음 - end note - - TemplateService -> TemplateService: 데이터 바인딩 - note right - 바인딩 데이터: - - 회의 제목 - - 시작 시간 (30분 후) - - 장소 - - 회의 참여 링크 - - 준비 사항 (있는 경우) - end note - - TemplateService --> Service: EmailContent 반환 - deactivate TemplateService - - == 참석자별 이메일 발송 == - - loop 각 참석자별 - Service -> EmailClient: sendEmail(recipient, emailContent) - activate EmailClient - - EmailClient -> EmailService: SMTP 이메일 발송 - activate EmailService - - EmailService --> EmailClient: 발송 결과 - deactivate EmailService - - alt 발송 성공 - EmailClient --> Service: SUCCESS - - Service -> Repository: updateRecipientStatus(notificationId, recipient, "SENT") - activate Repository - Repository -> DB: 수신자별 알림 상태 업데이트\n(상태='발송완료', 발송일시=현재시각) - activate DB - DB --> Repository: 업데이트 완료 - deactivate DB - Repository --> Service: 완료 - deactivate Repository - - else 발송 실패 - EmailClient --> Service: FAILED - - Service -> Repository: updateRecipientStatus(notificationId, recipient, "FAILED") - activate Repository - Repository -> DB: 수신자별 알림 상태 업데이트\n(상태='발송실패') - activate DB - DB --> Repository: 업데이트 완료 - deactivate DB - Repository --> Service: 완료 - deactivate Repository - - Service -> Service: 재시도 큐에 추가 - end - - deactivate EmailClient - end - - == 알림 상태 업데이트 == - - Service -> Repository: updateNotificationStatus(notificationId, finalStatus) - activate Repository - - Repository -> DB: 알림 최종 상태 업데이트\n(상태, 완료일시, 발송건수, 실패건수) - activate DB - DB --> Repository: 업데이트 완료 - deactivate DB - - Repository --> Service: 완료 - deactivate Repository - end -end - -Service --> Scheduler: 전체 리마인더 발송 완료\n(총 발송 건수, 성공/실패 통계) -deactivate Service - -Scheduler -> Scheduler: 다음 스케줄 대기 -deactivate Scheduler - -note over Scheduler, EmailService -스케줄링 정책: -- 실행 주기: 1분마다 -- 대상: 30분 후 시작 회의 -- 중복 발송 방지: DB 체크 - -처리 시간: -- 대상 회의 조회: ~200ms -- 이메일 발송 (per recipient): ~500ms -- 총 처리 시간: 회의 및 참석자 수에 비례 -end note - -@enduml diff --git a/design/backend/sequence/inner/notification-초대알림발송.puml b/design/backend/sequence/inner/notification-초대알림발송.puml deleted file mode 100644 index 29bea4b..0000000 --- a/design/backend/sequence/inner/notification-초대알림발송.puml +++ /dev/null @@ -1,145 +0,0 @@ -@startuml -!theme mono - -title Notification Service - 초대알림발송 내부 시퀀스 - -participant "NotificationController" as Controller -participant "NotificationService" as Service -participant "EmailTemplateService" as TemplateService -participant "NotificationRepository" as Repository -participant "EmailClient" as EmailClient -database "Notification DB" as DB -queue "Azure Event Hubs<>" as EventHub -participant "Email Service<>" as EmailService - -== MeetingCreated 이벤트 수신 == - -EventHub -> Controller: MeetingCreated 이벤트 수신 -activate Controller -note right - 이벤트 데이터: - - meetingId - - 제목 - - 일시 - - 장소 - - 참석자 목록 (이메일) - - 생성자 정보 -end note - -Controller -> Service: sendMeetingInvitation(meetingId, meetingData) -activate Service - -== 알림 기록 생성 == - -Service -> Repository: createNotification(meetingId, "INVITATION", participants) -activate Repository - -Repository -> DB: 초대 알림 생성\n(알림ID, 회의ID, 유형, 상태, 수신자, 생성일시) -activate DB -DB --> Repository: notificationId 반환 -deactivate DB - -Repository --> Service: NotificationEntity 반환 -deactivate Repository - -== 이메일 템플릿 생성 == - -Service -> TemplateService: generateInvitationEmail(meetingData) -activate TemplateService - -TemplateService -> TemplateService: 템플릿 로드 -note right - 템플릿 정보: - - 제목: "[회의 초대] {회의 제목}" - - 내용: 회의 정보 + 참여 링크 - - CTA 버튼: "회의 참석하기" -end note - -TemplateService -> TemplateService: 데이터 바인딩 -note right - 바인딩 데이터: - - 회의 제목 - - 날짜/시간 - - 장소 - - 생성자 이름 - - 회의 참여 링크 - - 캘린더 추가 링크 -end note - -TemplateService --> Service: EmailContent 반환\n(subject, htmlBody, plainTextBody) -deactivate TemplateService - -== 참석자별 이메일 발송 (병렬 처리) == - -loop 각 참석자별 - Service -> EmailClient: sendEmail(recipient, emailContent) - activate EmailClient - - EmailClient -> EmailService: SMTP 이메일 발송 - activate EmailService - - EmailService --> EmailClient: 발송 결과 - deactivate EmailService - - alt 발송 성공 - EmailClient --> Service: SUCCESS - - Service -> Repository: updateRecipientStatus(notificationId, recipient, "SENT") - activate Repository - Repository -> DB: 수신자별 알림 상태 업데이트\n(상태='발송완료', 발송일시=현재시각) - activate DB - DB --> Repository: 업데이트 완료 - deactivate DB - Repository --> Service: 완료 - deactivate Repository - - else 발송 실패 - EmailClient --> Service: FAILED (errorMessage) - - Service -> Repository: updateRecipientStatus(notificationId, recipient, "FAILED") - activate Repository - Repository -> DB: 수신자별 알림 상태 업데이트\n(상태='발송실패', 오류메시지=에러내용) - activate DB - DB --> Repository: 업데이트 완료 - deactivate DB - Repository --> Service: 완료 - deactivate Repository - - Service -> Service: 재시도 큐에 추가\n(최대 3회 재시도) - end - - deactivate EmailClient -end - -== 전체 알림 상태 업데이트 == - -Service -> Repository: updateNotificationStatus(notificationId, finalStatus) -activate Repository - -Repository -> DB: 알림 최종 상태 업데이트\n(상태, 완료일시, 발송건수, 실패건수) -activate DB -DB --> Repository: 업데이트 완료 -deactivate DB - -Repository --> Service: 완료 -deactivate Repository - -Service --> Controller: NotificationResponse\n(notificationId, status, sentCount, failedCount) -deactivate Service - -Controller --> EventHub: InvitationSent 이벤트 발행\n(meetingId, notificationId, status) -deactivate Controller - -note over Controller, EmailService -처리 시간: -- 알림 기록 생성: ~100ms -- 템플릿 생성: ~200ms -- 이메일 발송 (per recipient): ~500ms -- 총 처리 시간: 참석자 수에 비례 (병렬 처리) - -재시도 정책: -- 최대 3회 재시도 -- 재시도 간격: 5분, 15분, 30분 -end note - -@enduml