Merge branch 'main' of https://github.com/hwanny1128/HGZero into feat/meeting

This commit is contained in:
cyjadela
2025-10-28 13:40:22 +09:00
16 changed files with 53054 additions and 346 deletions
+2 -1
View File
@@ -41,6 +41,7 @@ examples/
# Claude settings
.claude/settings.local.json
.vscode/settings.json
# Backup files
design/*/*/*/*back*
@@ -48,4 +49,4 @@ design/*/*/*back*
design/*/*back*
design/*back*
backup/
.vscode/settings.json
claudedocs/*back*
+95
View File
@@ -0,0 +1,95 @@
# API 누락 요약표 (회의 진행 실시간 기능)
**작성일**: 2025년 10월 28일
**근거 문서**: [API리뷰-프로토타입vs구현.md](./API리뷰-프로토타입vs구현.md)
---
## 🔴 P0 (치명적 - 즉시 구현 필요)
| # | API | 프로토타입 근거 | 영향받는 유저스토리 | 비고 |
|---|-----|----------------|-------------------|------|
| 1 | `PUT /api/meetings/{meetingId}/memo` | [05-회의진행.html:1119-1143](../design/uiux/prototype/05-회의진행.html#L1119-L1143) | US-07, US-10 | 메모 저장 불가, 데이터 손실 위험 |
| 2 | `GET /api/ai/suggestions/realtime/{meetingId}` | [05-회의진행.html:767-806](../design/uiux/prototype/05-회의진행.html#L767-L806) | US-07, US-08 | AI 실시간 추천 완전 미동작 |
| 3 | `POST /api/stt/recordings/{recordingId}/pause` | [05-회의진행.html:1212-1243](../design/uiux/prototype/05-회의진행.html#L1212-L1243) | US-06 | 녹음 일시정지 불가 |
| 4 | `POST /api/stt/recordings/{recordingId}/resume` | [05-회의진행.html:1212-1243](../design/uiux/prototype/05-회의진행.html#L1212-L1243) | US-06 | 녹음 재개 불가 |
---
## 🟡 P1 (중요 - 우선 구현 필요)
| # | API | 프로토타입 근거 | 영향받는 유저스토리 | 비고 |
|---|-----|----------------|-------------------|------|
| 5 | `POST /api/ai/suggestions/{suggestionId}/adopt` | [05-회의진행.html:1070-1097](../design/uiux/prototype/05-회의진행.html#L1070-L1097) | US-07 | AI 추천 채택 불가, 수동 복붙 필요 |
| 6 | `GET /api/ai/terms/search` | [05-회의진행.html:1145-1182](../design/uiux/prototype/05-회의진행.html#L1145-L1182) | US-09 | 용어 검색 불가 |
---
## 🟢 P2 (일반 - 향후 개선)
| # | API | 프로토타입 근거 | 영향받는 유저스토리 | 비고 |
|---|-----|----------------|-------------------|------|
| 7 | `GET /api/ai/terms/{termName}/detail` | [05-회의진행.html:1305-1308](../design/uiux/prototype/05-회의진행.html#L1305-L1308) | US-09 | 용어 상세 조회 불가 |
---
## 📊 탭별 API 구현 현황
| 탭 | 기능 | 필요 API 수 | 구현 API 수 | 구현률 | 우선순위 |
|----|------|------------|------------|--------|---------|
| **참석자** | 참석자 관리 | 4 | 4 | 100% ✅ | - |
| **AI 메모** | 실시간 메모 & AI 추천 | 3 | 0 | 0% ❌ | P0 (3개) |
| **용어사전** | 용어 감지/검색 | 3 | 1 | 33% ⚠️ | P1 (1개), P2 (1개) |
| **관련회의록** | 유사 회의록 찾기 | 2 | 2 | 100% ✅ | - |
| **녹음 제어** | 녹음 상태 관리 | 5 | 3 | 60% ⚠️ | P0 (2개) |
---
## 🎯 구현 권장 순서
### Sprint 1 (1주) - P0 필수 기능
1. **메모 저장 API** (`PUT /api/meetings/{meetingId}/memo`)
- 예상 작업: 4시간
- 구현 위치: `MeetingController.java`
2. **AI 실시간 추천 API** (`GET /api/ai/suggestions/realtime/{meetingId}`)
- 예상 작업: 8시간
- 구현 위치: `SuggestionController.java`
- 폴링 또는 SSE 방식 선택 필요
3. **녹음 일시정지/재개 API** (`POST pause`, `POST resume`)
- 예상 작업: 6시간
- 구현 위치: `RecordingController.java`
### Sprint 2 (3일) - P1 중요 기능
4. **AI 추천 채택 API** (`POST /api/ai/suggestions/{suggestionId}/adopt`)
- 예상 작업: 4시간
5. **용어 검색 API** (`GET /api/ai/terms/search`)
- 예상 작업: 3시간
### Sprint 3 (2일) - P2 보조 기능
6. **용어 상세 조회 API** (`GET /api/ai/terms/{termName}/detail`)
- 예상 작업: 4시간
---
## 📝 비고
### 구현 고려사항
1. **AI 실시간 추천**: 폴링(Polling) vs SSE(Server-Sent Events) 방식 결정 필요
2. **메모 저장**: 개인별 메모 vs 공유 메모 정책 확인 필요
3. **녹음 일시정지**: 타이머 상태 동기화 로직 필요
4. **용어 검색**: 조직 용어 사전과 회의별 용어 통합 검색 정책 필요
### 테스트 시나리오
- [ ] 회의 진행 중 메모 작성 후 저장 → 다시 로드 시 메모 복원 확인
- [ ] AI 추천 메모 실시간 조회 → 5초마다 새 추천 확인
- [ ] AI 추천 채택 → 입력창에 시간 포함하여 추가 확인
- [ ] 용어 검색 → 키워드로 조직/회의 용어 찾기 확인
- [ ] 녹음 일시정지 → 타이머 정지 확인
- [ ] 녹음 재개 → 타이머 재개 확인
---
**문서 종료**
@@ -0,0 +1,832 @@
# API 리뷰 분석 - 프로토타입 vs 구현
**작성일**: 2025-10-28
**검토자**: Architect, Backend Developer, Frontend Developer
**분석 방법**: 프로토타입 HTML 파일과 실제 구현된 Controller 소스코드 비교 분석
---
## 📋 요약
### 전체 현황 (v2.0 - 회의 진행 실시간 기능 추가 분석)
- **분석된 화면**: 9개 프로토타입 화면
- **프로토타입 요구 API**: **34개** (v1: 27개 → v2: +7개)
- **구현된 API**: 27개 엔드포인트
- **완전 누락 API**: **11개** (v1: 4개 → v2: +7개)
- **개선 필요 API**: 2개
- **불필요한 API**: 0개
### 주요 발견사항 (v2.0 업데이트)
1.**강점**: 핵심 비즈니스 로직 API는 모두 구현됨
2. 🔴 **치명적 누락 (기존)**:
- `GET /api/meetings` (목록 조회) - 대시보드 "최근 회의" 표시 불가
- `PUT/PATCH /api/meetings/{meetingId}` (회의 수정) - 예정된 회의 수정 불가
- `GET /api/dashboard/statistics` - 대시보드 통계 카드 표시 불가
3. 🔴 **치명적 누락 (신규 발견)**: **회의 진행 중 실시간 기능 API 7개 누락**
- **탭2: AI 메모 (3개 누락)**
- `PUT /api/meetings/{meetingId}/memo` - 회의 중 메모 저장
- `GET /api/ai/suggestions/realtime/{meetingId}` - AI 실시간 추천 메모
- `POST /api/ai/suggestions/{suggestionId}/adopt` - AI 추천 채택
- **탭3: 용어사전 (2개 누락)**
- `GET /api/ai/terms/search` - 용어 검색
- `GET /api/ai/terms/{termName}/detail` - 용어 상세 조회
- **녹음 제어 (2개 누락)**
- `POST /api/stt/recordings/{recordingId}/pause` - 녹음 일시정지
- `POST /api/stt/recordings/{recordingId}/resume` - 녹음 재개
4. 🟡 **기능 누락**: AI 요약 재생성 API 미구현
5. 🟡 **개선 필요**: 회의록 검색/필터링 파라미터 추가 필요
### 비즈니스 영향도
- **사용자 경험**: 회의 진행 중 핵심 편의 기능 미동작으로 인한 UX 저하
- **AI 활용도**: 실시간 AI 추천 기능이 동작하지 않아 서비스 차별화 가치 감소
- **메모 손실 위험**: 회의 중 작성한 메모가 저장되지 않아 데이터 손실 가능성
- **유저스토리 영향**: US-06, US-07, US-08, US-09, US-10의 핵심/보조 기능 미동작
---
## 🔍 화면별 상세 분석
### 1. 로그인 화면 (01-로그인.html)
| 화면 기능 | 요구 API | 구현 상태 | 구현 위치 | 비고 |
|---------|---------|----------|----------|------|
| 로그인 | `POST /api/auth/login` | ✅ 구현됨 | [UserController.java:37-50](user/src/main/java/com/unicorn/hgzero/user/controller/UserController.java#L37-L50) | LDAP 인증, JWT 토큰 발급 |
| 토큰 갱신 | `POST /api/auth/refresh` | ✅ 구현됨 | [UserController.java:59-72](user/src/main/java/com/unicorn/hgzero/user/controller/UserController.java#L59-L72) | Refresh Token 사용 |
| 로그아웃 | `POST /api/auth/logout` | ✅ 구현됨 | [UserController.java:82-96](user/src/main/java/com/unicorn/hgzero/user/controller/UserController.java#L82-L96) | Refresh Token 삭제 |
| 토큰 검증 | `GET /api/auth/validate` | ✅ 구현됨 | [UserController.java:105-126](user/src/main/java/com/unicorn/hgzero/user/controller/UserController.java#L105-L126) | JWT 토큰 유효성 검증 |
**분석 결과**: ✅ **완벽 구현** - 모든 인증 관련 API가 구현되어 있으며, 보안 모범 사례를 따르고 있음
---
### 2. 대시보드 화면 (02-대시보드.html)
| 화면 기능 | 요구 API | 구현 상태 | 구현 위치 | 비고 |
|---------|---------|----------|----------|------|
| 최근 회의 목록 (3개) | `GET /api/meetings` | ❌ **누락** | - | **전체 회의 목록 조회 후 프론트에서 정렬** |
| 최근 회의록 목록 (4개) | `GET /api/meetings/minutes` | ✅ 구현됨 | [MinutesController.java:210-268](meeting/src/main/java/com/unicorn/hgzero/meeting/infra/controller/MinutesController.java#L210-L268) | 페이징, 필터링 지원 |
| 통계 정보 (2개 카드) | `GET /api/dashboard/statistics` | ❌ **누락** | - | 예정된 회의, 작성중 회의록 수 |
**상세 분석**:
#### "최근 회의" 섹션 요구사항 ([02-대시보드.html:665-681](design/uiux/prototype/02-대시보드.html#L665-L681))
프로토타입 JavaScript 로직:
```javascript
// 회의록 미생성(scheduled, ongoing) 먼저, 빠른 일시 순 정렬
const meetings = [...SAMPLE_MEETINGS]
.sort((a, b) => {
// 회의록 미생성 회의 우선
const aNoMinutes = a.status === 'scheduled' || a.status === 'ongoing';
const bNoMinutes = b.status === 'scheduled' || b.status === 'ongoing';
if (aNoMinutes && !bNoMinutes) return -1;
if (!aNoMinutes && bNoMinutes) return 1;
// 동일 그룹 내에서는 빠른 일시 순 (오름차순)
return new Date(a.date + ' ' + a.time) - new Date(b.date + ' ' + b.time);
})
.slice(0, 3); // 상위 3개만 표시
```
**요구사항 해석**:
1. **전체 회의 목록**을 가져와야 함 (상태 무관)
2. **회의록 생성 여부 정보** 포함 필요 (scheduled, ongoing, draft, complete)
3. 프론트엔드에서 다음 우선순위로 정렬:
- 1순위: 회의록 미생성 회의 (`scheduled`, `ongoing`)
- 2순위: 빠른 일시 순
4. 상위 3개만 표시
**현재 구현 상태**:
-`GET /api/meetings` (목록 조회) - **완전 누락**
-`GET /api/meetings/{meetingId}` (단건 조회) - 구현됨
**분석 결과**: ⚠️ **부분 구현** (33%)
- **누락 API (2개)**:
1. `GET /api/meetings` - 회의 목록 조회 (전체 상태, 날짜/시간 정렬 필요)
2. `GET /api/dashboard/statistics` - 통계 정보 (예정된 회의, 작성중 회의록)
**권장사항**:
```java
// MeetingController에 추가 필요
@GetMapping
@Operation(summary = "회의 목록 조회", description = "사용자의 회의 목록을 조회합니다")
public ResponseEntity<ApiResponse<MeetingListResponse>> getMeetingList(
@RequestHeader("X-User-Id") String userId,
@RequestParam(required = false) String status, // all(기본값), scheduled, ongoing, draft, complete
@RequestParam(required = false) LocalDateTime startDate,
@RequestParam(required = false) LocalDateTime endDate,
@RequestParam(defaultValue = "0") int page,
@RequestParam(defaultValue = "10") int size,
@RequestParam(defaultValue = "startTime") String sortBy,
@RequestParam(defaultValue = "asc") String sortDir
) {
// 사용자가 참여한 모든 회의 조회
// 응답에 회의록 생성 여부(hasMinutes), 회의록 상태(minutesStatus) 포함 필수
}
// 새로운 DashboardController 생성 권장
@GetMapping("/api/dashboard/statistics")
public ResponseEntity<ApiResponse<DashboardStatistics>> getStatistics(
@RequestHeader("X-User-Id") String userId
)
```
---
### 3. 회의 예약/수정 화면 (03-회의예약.html)
| 화면 기능 | 요구 API | 구현 상태 | 구현 위치 | 비고 |
|---------|---------|----------|----------|------|
| 회의 생성 | `POST /api/meetings` | ✅ 구현됨 | [MeetingController.java:60-93](meeting/src/main/java/com/unicorn/hgzero/meeting/infra/controller/MeetingController.java#L60-L93) | 참석자 초대 포함 |
| 회의 정보 수정 | `PUT /api/meetings/{meetingId}` 또는 `PATCH /api/meetings/{meetingId}` | ❌ **누락** | - | **예정된 회의 수정 불가** |
**상세 분석**:
#### 회의 수정 요구사항 ([02-대시보드.html:724](design/uiux/prototype/02-대시보드.html#L724))
프로토타입 JavaScript 로직:
```javascript
// 상태에 따른 이동 처리
if (meetingStatus === 'ongoing') {
navigateTo('05-회의진행.html');
} else if (meetingStatus === 'draft' || meetingStatus === 'complete' || meetingStatus === 'completed') {
navigateTo('10-회의록상세조회.html');
} else if (meetingStatus === 'scheduled') {
navigateTo('03-회의예약.html'); // 예정된 회의 → 회의예약 화면 (수정 모드)
}
```
**요구사항 해석**:
1. 대시보드에서 **예정된 회의(scheduled) 카드 클릭**
2. 회의예약 화면(03-회의예약.html)으로 이동
3. 기존 회의 정보를 **로드하여 수정 가능**해야 함
4. 수정 완료 시 `PUT` 또는 `PATCH` 요청 필요
**현재 상태**:
- ❌ API 설계서([meeting-service-api.yaml](design/backend/api/meeting-service-api.yaml)) - **회의 수정 API 명세 없음**
- ❌ MeetingController - **회의 수정 API 구현 없음**
-`POST /api/meetings` (생성) - 구현됨
-`GET /api/meetings/{meetingId}` (단건 조회) - 구현됨
-`PUT/PATCH /api/meetings/{meetingId}` (수정) - **완전 누락**
**분석 결과**: ⚠️ **치명적 누락** (50%)
- 회의 생성은 가능하지만, **예약된 회의 수정 불가**
- 사용자가 대시보드에서 예정된 회의를 클릭해도 수정할 수 없음
**권장사항**:
```java
// MeetingController에 추가 필요
@PutMapping("/{meetingId}")
@Operation(summary = "회의 정보 수정", description = "예정된 회의의 정보를 수정합니다")
public ResponseEntity<ApiResponse<MeetingResponse>> updateMeeting(
@PathVariable String meetingId,
@RequestHeader("X-User-Id") String userId,
@RequestHeader("X-User-Name") String userName,
@RequestHeader("X-User-Email") String userEmail,
@Valid @RequestBody UpdateMeetingRequest request
) {
// 회의 정보 수정 로직
// - 제목, 날짜, 시간, 장소, 안건 수정 가능
// - 참석자 추가/제거 가능
// - 회의 상태가 'scheduled'일 때만 수정 가능
// - 변경 사항 참석자에게 알림
}
```
**UpdateMeetingRequest DTO**:
```java
public class UpdateMeetingRequest {
private String title; // 회의 제목
private LocalDateTime startTime; // 시작 시간
private LocalDateTime endTime; // 종료 시간
private String location; // 장소
private String agenda; // 안건
private List<String> participants; // 참석자 이메일 목록
}
```
---
### 4. 템플릿 선택 화면 (04-템플릿선택.html)
| 화면 기능 | 요구 API | 구현 상태 | 구현 위치 | 비고 |
|---------|---------|----------|----------|------|
| 템플릿 목록 조회 | `GET /api/meetings/templates` | ✅ 구현됨 | [TemplateController.java:33-63](meeting/src/main/java/com/unicorn/hgzero/meeting/infra/controller/TemplateController.java#L33-L63) | 4가지 고정 템플릿 제공 |
| 템플릿 적용 | `PUT /api/meetings/{meetingId}/template` | ✅ 구현됨 | [MeetingController.java:108-135](meeting/src/main/java/com/unicorn/hgzero/meeting/infra/controller/MeetingController.java#L108-L135) | 템플릿 ID로 적용 |
**분석 결과**: ✅ **완벽 구현** - 템플릿 관리 기능 완전 구현
---
### 5. 회의 진행 화면 (05-회의진행.html) ⚠️ **중요 업데이트**
#### 화면 구조 분석
프로토타입은 4개 탭으로 구성되어 있으며, 각 탭마다 실시간 기능이 요구됩니다:
```
┌─────────────────────────────────────────┐
│ 📍 헤더: 회의 제목 + 녹음 상태 │
├─────────────────────────────────────────┤
│ 📋 회의 기본정보 (카드) │
├─────────────────────────────────────────┤
│ 📑 4개 탭 컨테이너 │
│ ┌──────────────────────────────────┐ │
│ │ 🧑‍🤝‍🧑 참석자 | 📝 AI메모 | 📚 용어 │ │
│ │ 사전 | 📂 관련회의록 │ │
│ └──────────────────────────────────┘ │
├─────────────────────────────────────────┤
│ ⏸️ 일시정지 | 🔴 회의 종료 버튼 │
└─────────────────────────────────────────┘
```
#### 탭1: 참석자 (Lines 697-747)
| 화면 기능 | 요구 API | 구현 상태 | 구현 위치 | 비고 |
|---------|---------|----------|----------|------|
| 회의 시작 | `POST /api/meetings/{meetingId}/start` | ✅ 구현됨 | [MeetingController.java:149-170](meeting/src/main/java/com/unicorn/hgzero/meeting/infra/controller/MeetingController.java#L149-L170) | WebSocket 세션 생성 |
| WebSocket 연결 | `ws://localhost:8080/ws/collaboration` | ✅ 구현됨 | [MeetingController.java:165](meeting/src/main/java/com/unicorn/hgzero/meeting/infra/controller/MeetingController.java#L165) | 실시간 협업 지원 |
| 참석자 초대 | `POST /api/meetings/{meetingId}/invite` | ✅ 구현됨 | [MeetingController.java:289-321](meeting/src/main/java/com/unicorn/hgzero/meeting/infra/controller/MeetingController.java#L289-L321) | 이메일 발송 포함 |
| 참석자 목록 표시 | `GET /api/meetings/{meetingId}` | ✅ 구현됨 | [MeetingController.java:228-244](meeting/src/main/java/com/unicorn/hgzero/meeting/infra/controller/MeetingController.java#L228-L244) | 회의 정보에 참석자 포함 |
#### 탭2: AI 메모 (Lines 750-807) 🔴 **치명적 누락**
| 화면 기능 | 요구 API | 구현 상태 | 프로토타입 근거 | 비고 |
|---------|---------|----------|---------------|------|
| **메모 입력 및 저장** | `PUT /api/meetings/{meetingId}/memo` | ❌ **누락** | [Line 1119-1143](design/uiux/prototype/05-회의진행.html#L1119-L1143) | 개인별 메모 저장 |
| **AI 추천 실시간 조회** | `GET /api/ai/suggestions/realtime/{meetingId}` | ❌ **누락** | [Line 767-806](design/uiux/prototype/05-회의진행.html#L767-L806) | 실시간 폴링 필요 |
| **AI 추천 채택** | `POST /api/ai/suggestions/{suggestionId}/adopt` | ❌ **누락** | [Line 1070-1097](design/uiux/prototype/05-회의진행.html#L1070-L1097) | 시간 포함 저장 |
**프로토타입 JavaScript 분석** (saveMemo 함수):
```javascript
function saveMemo() {
const memo = memoTextarea.value.trim();
// 실제 구현시에는 서버로 전송
// fetch('/api/meetings/memo', {
// method: 'PUT',
// body: JSON.stringify({ memo: memo }),
// headers: { 'Content-Type': 'application/json' }
// });
}
```
**영향도**:
- 🔴 사용자가 작성한 메모가 저장되지 않음 (데이터 손실 위험)
- 🔴 AI 실시간 추천 기능 완전 미동작
- 🔴 **유저스토리 US-07, US-08**의 핵심 기능
#### 탭3: 용어사전 (Lines 810-967) 🟡 **부분 구현**
| 화면 기능 | 요구 API | 구현 상태 | 구현 위치 | 비고 |
|---------|---------|----------|----------|------|
| **AI 전문용어 실시간 감지** | `POST /api/ai/terms/detect` | ✅ 구현됨 | [TermController.java:35-79](ai/src/main/java/com/unicorn/hgzero/ai/infra/controller/TermController.java#L35-L79) | 회의 중 용어 자동 감지 |
| **용어 검색** | `GET /api/ai/terms/search` | ❌ **누락** | [Line 1145-1182](design/uiux/prototype/05-회의진행.html#L1145-L1182) | 키워드 검색 |
| **용어 상세 조회** | `GET /api/ai/terms/{termName}/detail` | ❌ **누락** | [Line 1305-1308](design/uiux/prototype/05-회의진행.html#L1305-L1308) | 모달 표시 |
#### 탭4: 관련회의록 (Lines 970-1010) ✅ **완벽 구현**
| 화면 기능 | 요구 API | 구현 상태 | 구현 위치 | 비고 |
|---------|---------|----------|----------|------|
| **AI 유사 회의록 찾기** | `GET /api/ai/transcripts/{meetingId}/related` | ✅ 구현됨 | [RelationController.java:31-62](ai/src/main/java/com/unicorn/hgzero/ai/infra/controller/RelationController.java#L31-L62) | 벡터 유사도 검색 |
| 관련 회의록 열기 | `GET /api/meetings/minutes/{minutesId}` | ✅ 구현됨 | 기존 API 재사용 | 새 탭 열기 |
#### 녹음 제어 (Bottom Bar) 🔴 **치명적 누락**
| 화면 기능 | 요구 API | 구현 상태 | 프로토타입 근거 | 비고 |
|---------|---------|----------|---------------|------|
| **녹음 일시정지** | `POST /api/stt/recordings/{recordingId}/pause` | ❌ **누락** | [Line 1212-1243](design/uiux/prototype/05-회의진행.html#L1212-L1243) | 타이머 정지 |
| **녹음 재개** | `POST /api/stt/recordings/{recordingId}/resume` | ❌ **누락** | [Line 1212-1243](design/uiux/prototype/05-회의진행.html#L1212-L1243) | 타이머 재개 |
| 녹음 시작 | `POST /api/stt/recordings/{recordingId}/start` | ✅ 구현됨 | [RecordingController.java:83-94](stt/src/main/java/com/unicorn/hgzero/stt/controller/RecordingController.java#L83-L94) | - |
| 녹음 중지 | `POST /api/stt/recordings/{recordingId}/stop` | ✅ 구현됨 | [RecordingController.java:115-126](stt/src/main/java/com/unicorn/hgzero/stt/controller/RecordingController.java#L115-L126) | - |
| 회의 종료 | `POST /api/meetings/{meetingId}/end` | ✅ 구현됨 | [MeetingController.java:184-214](meeting/src/main/java/com/unicorn/hgzero/meeting/infra/controller/MeetingController.java#L184-L214) | AI 분석 포함 |
**현재 상태**: RecordingController에는 `start``stop`만 있고 `pause/resume` 없음
**영향도**:
- 🔴 회의 중 잠깐 중단 후 재개 시나리오 불가
- 🔴 **유저스토리 US-06**의 핵심 기능
---
**분석 결과**: ⚠️ **부분 구현 (50%)** - **실시간 기능 7개 API 누락**
### 누락 API 상세 명세
#### 1. 메모 저장 API 🔴 P0
```java
PUT /api/meetings/{meetingId}/memo
Request Body: {
"memo": "string",
"userId": "string",
"timestamp": "datetime"
}
Response: { "memoId": "string", "savedAt": "datetime" }
```
#### 2. AI 실시간 추천 조회 API 🔴 P0
```java
GET /api/ai/suggestions/realtime/{meetingId}?since={timestamp}&limit=10
Response: {
"suggestions": [
{
"suggestionId": "string",
"timestamp": "00:05:23",
"content": "string",
"confidence": 0.95,
"category": "DISCUSSION|DECISION"
}
]
}
```
#### 3. AI 추천 채택 API 🟡 P1
```java
POST /api/ai/suggestions/{suggestionId}/adopt
Request Body: {
"meetingId": "string",
"timestamp": "00:05:23",
"userId": "string"
}
```
#### 4. 용어 검색 API 🟡 P1
```java
GET /api/ai/terms/search?query={keyword}&meetingId={id}
Response: {
"terms": [...],
"totalCount": 5
}
```
#### 5. 용어 상세 조회 API 🟢 P2
```java
GET /api/ai/terms/{termName}/detail?meetingId={id}
Response: {
"term": "string",
"definition": "string",
"usageInMeeting": [...],
"externalLinks": [...]
}
```
#### 6-7. 녹음 일시정지/재개 API 🔴 P0
```java
POST /api/stt/recordings/{recordingId}/pause
POST /api/stt/recordings/{recordingId}/resume
Response: { "status": "PAUSED|RECORDING", "timestamp": "datetime" }
```
---
### 6. 회의 종료 화면 (07-회의종료.html)
| 화면 기능 | 요구 API | 구현 상태 | 구현 위치 | 비고 |
|---------|---------|----------|----------|------|
| 회의 종료 | `POST /api/meetings/{meetingId}/end` | ✅ 구현됨 | [MeetingController.java:184-214](meeting/src/main/java/com/unicorn/hgzero/meeting/infra/controller/MeetingController.java#L184-L214) | AI 분석, 회의록 생성 |
**분석 결과**: ✅ **완벽 구현** - AI 기반 회의록 자동 생성 포함
---
### 7. 회의록 상세 조회 화면 (10-회의록상세조회.html)
| 화면 기능 | 요구 API | 구현 상태 | 구현 위치 | 비고 |
|---------|---------|----------|----------|------|
| 회의록 상세 조회 | `GET /api/meetings/minutes/{minutesId}` | ✅ 구현됨 | [MinutesController.java:271-297](meeting/src/main/java/com/unicorn/hgzero/meeting/infra/controller/MinutesController.java#L271-L297) | 대시보드 탭, 회의록 탭 데이터 포함 |
**분석 결과**: ✅ **완벽 구현** - 상세 조회 완전 구현 (Mock 데이터 포함)
---
### 8. 회의록 수정 화면 (11-회의록수정.html)
| 화면 기능 | 요구 API | 구현 상태 | 구현 위치 | 비고 |
|---------|---------|----------|----------|------|
| 회의록 수정 | `PATCH /api/meetings/minutes/{minutesId}` | ✅ 구현됨 | [MinutesController.java:300-343](meeting/src/main/java/com/unicorn/hgzero/meeting/infra/controller/MinutesController.java#L300-L343) | 제목, 섹션 내용 수정 |
| 회의록 확정 | `POST /api/meetings/minutes/{minutesId}/finalize` | ✅ 구현됨 | [MinutesController.java:346-374](meeting/src/main/java/com/unicorn/hgzero/meeting/infra/controller/MinutesController.java#L346-L374) | 버전 관리 포함 |
| 섹션 검증 | `POST /api/meetings/minutes/{minutesId}/sections/{sectionId}/verify` | ✅ 구현됨 | [MinutesController.java:377-410](meeting/src/main/java/com/unicorn/hgzero/meeting/infra/controller/MinutesController.java#L377-L410) | 섹션별 완료 검증 |
| 섹션 잠금 | `POST /api/meetings/minutes/{minutesId}/sections/{sectionId}/lock` | ✅ 구현됨 | [MinutesController.java:413-446](meeting/src/main/java/com/unicorn/hgzero/meeting/infra/controller/MinutesController.java#L413-L446) | 동시 편집 방지 |
| 섹션 잠금 해제 | `DELETE /api/meetings/minutes/{minutesId}/sections/{sectionId}/lock` | ✅ 구현됨 | [MinutesController.java:449-480](meeting/src/main/java/com/unicorn/hgzero/meeting/infra/controller/MinutesController.java#L449-L480) | 잠금 해제 |
| AI 요약 재생성 | `POST /api/meetings/minutes/{minutesId}/sections/{sectionId}/regenerate-summary` | ❌ **누락** | - | AI 요약 재생성 기능 필요 |
**분석 결과**: ⚠️ **부분 구현** (83%)
- **누락 API (1개)**: AI 요약 재생성 기능
**권장사항**:
```java
// MinutesController에 추가 필요
@PostMapping("/{minutesId}/sections/{sectionId}/regenerate-summary")
@Operation(summary = "AI 요약 재생성", description = "섹션의 AI 요약을 재생성합니다")
public ResponseEntity<ApiResponse<SectionSummary>> regenerateSummary(
@PathVariable String minutesId,
@PathVariable String sectionId,
@RequestHeader("X-User-Id") String userId
)
```
---
### 9. 회의록 목록 조회 화면 (12-회의록목록조회.html)
| 화면 기능 | 요구 API | 구현 상태 | 구현 위치 | 비고 |
|---------|---------|----------|----------|------|
| 회의록 목록 조회 | `GET /api/meetings/minutes` | ✅ 구현됨 | [MinutesController.java:210-268](meeting/src/main/java/com/unicorn/hgzero/meeting/infra/controller/MinutesController.java#L210-L268) | 상태 필터, 페이징 지원 |
| 검색 기능 | `GET /api/meetings/minutes?keyword={keyword}` | ⚠️ **개선 필요** | [MinutesController.java:210](meeting/src/main/java/com/unicorn/hgzero/meeting/infra/controller/MinutesController.java#L210) | 키워드 검색 파라미터 추가 필요 |
| 참여 유형 필터 | `GET /api/meetings/minutes?participationType={type}` | ⚠️ **개선 필요** | [MinutesController.java:210](meeting/src/main/java/com/unicorn/hgzero/meeting/infra/controller/MinutesController.java#L210) | 참여 유형 필터 추가 필요 |
**분석 결과**: ⚠️ **개선 필요**
- 기본 목록 조회는 구현되어 있으나, 프로토타입에서 요구하는 세부 필터링 기능 미구현
**권장사항**:
```java
// MinutesController 개선 필요
@GetMapping
public ResponseEntity<ApiResponse<MinutesListResponse>> getMinutesList(
@RequestHeader("X-User-Id") String userId,
@RequestParam(required = false) String status, // 기존 기능
@RequestParam(required = false) String keyword, // 추가 필요 - 제목/내용 검색
@RequestParam(required = false) String participationType, // 추가 필요 - host, participant, all
@RequestParam(defaultValue = "0") int page,
@RequestParam(defaultValue = "20") int size,
@RequestParam(defaultValue = "createdAt") String sortBy,
@RequestParam(defaultValue = "desc") String sortDir
)
```
---
## 📊 통합 분석
### 구현된 API 목록 (24개)
#### 인증 서비스 (4개)
| API | 메서드 | 엔드포인트 | 구현 위치 |
|-----|--------|-----------|----------|
| 로그인 | POST | `/api/auth/login` | [UserController.java:37](user/src/main/java/com/unicorn/hgzero/user/controller/UserController.java#L37) |
| 토큰 갱신 | POST | `/api/auth/refresh` | [UserController.java:59](user/src/main/java/com/unicorn/hgzero/user/controller/UserController.java#L59) |
| 로그아웃 | POST | `/api/auth/logout` | [UserController.java:82](user/src/main/java/com/unicorn/hgzero/user/controller/UserController.java#L82) |
| 토큰 검증 | GET | `/api/auth/validate` | [UserController.java:105](user/src/main/java/com/unicorn/hgzero/user/controller/UserController.java#L105) |
#### 회의 관리 서비스 (6개 - 목록 조회, 회의 수정 누락)
| API | 메서드 | 엔드포인트 | 구현 위치 |
|-----|--------|-----------|----------|
| 회의 생성 | POST | `/api/meetings` | [MeetingController.java:60](meeting/src/main/java/com/unicorn/hgzero/meeting/infra/controller/MeetingController.java#L60) |
| 템플릿 적용 | PUT | `/api/meetings/{meetingId}/template` | [MeetingController.java:108](meeting/src/main/java/com/unicorn/hgzero/meeting/infra/controller/MeetingController.java#L108) |
| 회의 시작 | POST | `/api/meetings/{meetingId}/start` | [MeetingController.java:149](meeting/src/main/java/com/unicorn/hgzero/meeting/infra/controller/MeetingController.java#L149) |
| 회의 종료 | POST | `/api/meetings/{meetingId}/end` | [MeetingController.java:184](meeting/src/main/java/com/unicorn/hgzero/meeting/infra/controller/MeetingController.java#L184) |
| 회의 단건 조회 | GET | `/api/meetings/{meetingId}` | [MeetingController.java:228](meeting/src/main/java/com/unicorn/hgzero/meeting/infra/controller/MeetingController.java#L228) |
| 회의 취소 | DELETE | `/api/meetings/{meetingId}` | [MeetingController.java:258](meeting/src/main/java/com/unicorn/hgzero/meeting/infra/controller/MeetingController.java#L258) |
| 참석자 초대 | POST | `/api/meetings/{meetingId}/invite` | [MeetingController.java:289](meeting/src/main/java/com/unicorn/hgzero/meeting/infra/controller/MeetingController.java#L289) |
**⚠️ 누락 API (2개)**:
1. `GET /api/meetings` (회의 목록 조회) - 대시보드 "최근 회의" 섹션에 필수
2. `PUT /api/meetings/{meetingId}` (회의 정보 수정) - **예정된 회의 수정 불가**
#### 회의록 관리 서비스 (7개)
| API | 메서드 | 엔드포인트 | 구현 위치 |
|-----|--------|-----------|----------|
| 회의록 목록 조회 | GET | `/api/meetings/minutes` | [MinutesController.java:210](meeting/src/main/java/com/unicorn/hgzero/meeting/infra/controller/MinutesController.java#L210) |
| 회의록 상세 조회 | GET | `/api/meetings/minutes/{minutesId}` | [MinutesController.java:271](meeting/src/main/java/com/unicorn/hgzero/meeting/infra/controller/MinutesController.java#L271) |
| 회의록 수정 | PATCH | `/api/meetings/minutes/{minutesId}` | [MinutesController.java:300](meeting/src/main/java/com/unicorn/hgzero/meeting/infra/controller/MinutesController.java#L300) |
| 회의록 확정 | POST | `/api/meetings/minutes/{minutesId}/finalize` | [MinutesController.java:346](meeting/src/main/java/com/unicorn/hgzero/meeting/infra/controller/MinutesController.java#L346) |
| 섹션 검증 | POST | `/api/meetings/minutes/{minutesId}/sections/{sectionId}/verify` | [MinutesController.java:377](meeting/src/main/java/com/unicorn/hgzero/meeting/infra/controller/MinutesController.java#L377) |
| 섹션 잠금 | POST | `/api/meetings/minutes/{minutesId}/sections/{sectionId}/lock` | [MinutesController.java:413](meeting/src/main/java/com/unicorn/hgzero/meeting/infra/controller/MinutesController.java#L413) |
| 섹션 잠금 해제 | DELETE | `/api/meetings/minutes/{minutesId}/sections/{sectionId}/lock` | [MinutesController.java:449](meeting/src/main/java/com/unicorn/hgzero/meeting/infra/controller/MinutesController.java#L449) |
#### Todo 관리 서비스 (4개)
| API | 메서드 | 엔드포인트 | 구현 위치 |
|-----|--------|-----------|----------|
| Todo 생성 | POST | `/api/meetings/todos` | [TodoController.java:50](meeting/src/main/java/com/unicorn/hgzero/meeting/infra/controller/TodoController.java#L50) |
| Todo 수정 | PATCH | `/api/meetings/todos/{todoId}` | [TodoController.java:114](meeting/src/main/java/com/unicorn/hgzero/meeting/infra/controller/TodoController.java#L114) |
| Todo 완료 | PATCH | `/api/meetings/todos/{todoId}/complete` | [TodoController.java:163](meeting/src/main/java/com/unicorn/hgzero/meeting/infra/controller/TodoController.java#L163) |
| Todo 목록 조회 | GET | `/api/meetings/todos` | [TodoController.java:210](meeting/src/main/java/com/unicorn/hgzero/meeting/infra/controller/TodoController.java#L210) |
#### 템플릿 관리 서비스 (1개)
| API | 메서드 | 엔드포인트 | 구현 위치 |
|-----|--------|-----------|----------|
| 템플릿 목록 조회 | GET | `/api/meetings/templates` | [TemplateController.java:33](meeting/src/main/java/com/unicorn/hgzero/meeting/infra/controller/TemplateController.java#L33) |
#### WebSocket (1개)
| API | 프로토콜 | 엔드포인트 | 구현 위치 |
|-----|---------|-----------|----------|
| 실시간 협업 | WebSocket | `ws://localhost:8080/ws/collaboration` | [MeetingController.java:165](meeting/src/main/java/com/unicorn/hgzero/meeting/infra/controller/MeetingController.java#L165) |
---
### ❌ 누락된 API 목록 (4개 완전 누락 + 2개 개선 필요)
#### 완전 누락 (4개)
| 우선순위 | API | 메서드 | 엔드포인트 | 필요한 이유 | 권장 구현 위치 |
|---------|-----|--------|-----------|-----------|--------------|
| 🔴 **긴급** | 회의 목록 조회 | GET | `/api/meetings` | 대시보드 "최근 회의" 섹션 표시 **불가** | MeetingController |
| 🔴 **긴급** | 회의 정보 수정 | PUT/PATCH | `/api/meetings/{meetingId}` | 대시보드에서 예정된 회의 클릭 시 수정 **불가** | MeetingController |
| 🔴 **긴급** | 대시보드 통계 | GET | `/api/dashboard/statistics` | 대시보드 통계 카드 (예정된 회의, 작성중 회의록) 표시 **불가** | 신규 DashboardController |
| 🟡 중간 | AI 요약 재생성 | POST | `/api/meetings/minutes/{minutesId}/sections/{sectionId}/regenerate-summary` | 회의록 수정 화면 AI 요약 재생성 버튼 **동작 불가** | MinutesController |
#### 기능 개선 필요 (2개)
| 우선순위 | API | 현재 상태 | 개선 내용 | 필요한 이유 |
|---------|-----|----------|-----------|-----------|
| 🟡 중간 | 회의록 목록 조회 | `GET /api/meetings/minutes` 구현됨 | `keyword` 파라미터 추가 | 회의록 목록 화면 검색 기능 동작 안 함 |
| 🟡 중간 | 회의록 목록 조회 | `GET /api/meetings/minutes` 구현됨 | `participationType` 파라미터 추가 | 회의록 목록 화면 참여 유형 필터 동작 안 함 |
---
### ✅ 불필요한 API (0개)
**분석 결과**: 구현된 모든 API가 프로토타입에서 요구하는 기능과 매칭되며, 불필요한 API는 없음.
---
## 💡 권장 개선사항
### 1. 높은 우선순위 (🔴 필수)
#### 1.1 회의 목록 조회 API 추가
```java
// MeetingController.java에 추가
@GetMapping
@Operation(summary = "회의 목록 조회", description = "사용자의 회의 목록을 조회합니다")
public ResponseEntity<ApiResponse<MeetingListResponse>> getMeetingList(
@RequestHeader("X-User-Id") String userId,
@RequestParam(required = false) String status, // upcoming, ongoing, completed
@RequestParam(required = false) LocalDateTime startDate,
@RequestParam(required = false) LocalDateTime endDate,
@RequestParam(defaultValue = "0") int page,
@RequestParam(defaultValue = "10") int size,
@RequestParam(defaultValue = "startTime") String sortBy,
@RequestParam(defaultValue = "asc") String sortDir
) {
// 구현 로직
}
```
**요구사항**:
- 상태별 필터링: `upcoming` (예정), `ongoing` (진행 중), `completed` (완료)
- 날짜 범위 필터링
- 페이징 지원
- 정렬 기능 (시작 시간, 생성 시간 등)
---
#### 1.2 대시보드 통계 API 추가
```java
// 신규 DashboardController.java 생성
@RestController
@RequestMapping("/api/dashboard")
@RequiredArgsConstructor
@Tag(name = "Dashboard", description = "대시보드 API")
public class DashboardController {
@GetMapping("/statistics")
@Operation(summary = "대시보드 통계 조회", description = "사용자의 통계 정보를 조회합니다")
public ResponseEntity<ApiResponse<DashboardStatistics>> getStatistics(
@RequestHeader("X-User-Id") String userId
) {
// 구현 로직
}
}
```
**응답 데이터 구조**:
```json
{
"totalMeetings": 24,
"upcomingMeetings": 3,
"completedMinutes": 18,
"pendingTodos": 7,
"completedTodos": 15,
"thisWeekMeetings": 5,
"thisMonthMeetings": 12
}
```
---
### 2. 중간 우선순위 (🟡 권장)
#### 2.1 AI 요약 재생성 API 추가
```java
// MinutesController.java에 추가
@PostMapping("/{minutesId}/sections/{sectionId}/regenerate-summary")
@Operation(summary = "AI 요약 재생성", description = "섹션의 AI 요약을 재생성합니다")
public ResponseEntity<ApiResponse<SectionSummary>> regenerateSummary(
@PathVariable String minutesId,
@PathVariable String sectionId,
@RequestHeader("X-User-Id") String userId,
@RequestHeader("X-User-Name") String userName
) {
// AI 서비스 호출하여 요약 재생성
// 버전 관리 (이전 요약 보존)
// 이벤트 발행 (요약 재생성 알림)
}
```
---
#### 2.2 회의록 목록 API 개선
```java
// MinutesController.java 수정
@GetMapping
public ResponseEntity<ApiResponse<MinutesListResponse>> getMinutesList(
@RequestHeader("X-User-Id") String userId,
@RequestParam(required = false) String status,
@RequestParam(required = false) String keyword, // 추가 - 제목/내용 검색
@RequestParam(required = false) String participationType, // 추가 - host, participant, all
@RequestParam(defaultValue = "0") int page,
@RequestParam(defaultValue = "20") int size,
@RequestParam(defaultValue = "createdAt") String sortBy,
@RequestParam(defaultValue = "desc") String sortDir
) {
// 구현 로직
}
```
**추가 필터 설명**:
- `keyword`: 회의록 제목 또는 내용에서 검색 (LIKE 검색)
- `participationType`:
- `host`: 주최한 회의록만
- `participant`: 참여한 회의록만
- `all`: 모든 회의록 (기본값)
---
### 3. 낮은 우선순위 (🟢 선택)
#### 3.1 회의록 버전 관리 API
```java
// MinutesController.java에 추가 고려
@GetMapping("/{minutesId}/versions")
@Operation(summary = "회의록 버전 목록 조회")
public ResponseEntity<ApiResponse<List<MinutesVersion>>> getMinutesVersions(
@PathVariable String minutesId
)
@GetMapping("/{minutesId}/versions/{version}")
@Operation(summary = "특정 버전 회의록 조회")
public ResponseEntity<ApiResponse<MinutesDetail>> getMinutesVersion(
@PathVariable String minutesId,
@PathVariable int version
)
```
---
## 🎯 구현 우선순위 로드맵
### Phase 1: 필수 기능 (Sprint 1-2)
1.**회의 목록 조회 API** (MeetingController)
- 예상 작업 시간: 4시간
- 의존성: MeetingService, MeetingRepository
2.**대시보드 통계 API** (신규 DashboardController)
- 예상 작업 시간: 6시간
- 의존성: MeetingService, MinutesService, TodoService
### Phase 2: 개선 기능 (Sprint 3)
3.**AI 요약 재생성 API** (MinutesController)
- 예상 작업 시간: 8시간
- 의존성: AI Service, Event Publisher
4.**회의록 검색/필터 개선** (MinutesController)
- 예상 작업 시간: 3시간
- 의존성: MinutesRepository (쿼리 추가)
### Phase 3: 선택 기능 (Sprint 4)
5. ⏸️ **버전 관리 API** (MinutesController)
- 예상 작업 시간: 6시간
- 의존성: 버전 관리 스키마 설계
---
## 📝 코드 리뷰 의견
### ✅ 잘된 점
1. **일관된 API 설계**
- RESTful 원칙 준수
- 명확한 엔드포인트 네이밍
- 표준 HTTP 메서드 사용
2. **포괄적인 문서화**
- Swagger/OpenAPI 주석 완벽 작성
- 각 API마다 상세한 설명과 파라미터 문서화
3. **보안 고려**
- JWT 기반 인증/인가
- LDAP 통합
- Request Header를 통한 사용자 식별
4. **실용적인 Mock 데이터**
- 프론트엔드 개발을 위한 상세한 Mock 데이터 제공
- 실제 데이터 구조와 동일한 형태
5. **캐시 전략**
- Redis 캐시 적극 활용
- 적절한 캐시 무효화 로직
6. **이벤트 기반 아키텍처**
- Event Publisher를 통한 비동기 처리
- 알림 시스템 통합 준비
### ⚠️ 개선이 필요한 점
1. **누락된 핵심 API**
- 대시보드 통계 API 없음 → 사용자 경험 저하
- 회의 목록 조회 API 없음 → 대시보드 불완전
2. **검색 기능 부족**
- 회의록 검색 파라미터 미구현
- 키워드 기반 검색 불가
3. **에러 처리 일관성**
- 일부 Controller에서 try-catch로 처리
- 일부는 비즈니스 예외를 그대로 던짐
- 통일된 예외 처리 전략 필요
4. **테스트 코드 부재**
- Controller 테스트 코드 확인 필요
- API 통합 테스트 권장
---
## 🔧 기술적 권장사항
### 1. API 버전 관리
```java
// 향후 API 변경에 대비한 버전 관리 권장
@RequestMapping("/api/v1/meetings")
```
### 2. 페이징 표준화
```java
// 모든 목록 조회 API에 일관된 페이징 파라미터 적용
@RequestParam(defaultValue = "0") int page
@RequestParam(defaultValue = "20") int size
@RequestParam(defaultValue = "createdAt") String sortBy
@RequestParam(defaultValue = "desc") String sortDir
```
### 3. 응답 데이터 일관성
```java
// 모든 API가 ApiResponse 래퍼 사용 (이미 잘 적용됨)
public class ApiResponse<T> {
private String message;
private T data;
private String errorCode; // 에러 처리 강화
}
```
### 4. Rate Limiting
```java
// 공격 방지를 위한 Rate Limiting 추가 권장
@RateLimit(limit = 100, duration = 1, unit = TimeUnit.MINUTES)
```
---
## 📈 비교 지표
| 항목 | 프로토타입 요구사항 | 구현 현황 | 구현률 |
|-----|------------------|----------|--------|
| 인증 API | 4개 | 4개 | 100% ✅ |
| 회의 관리 API | 8개 | 6개 | 75% ⚠️ |
| 회의록 관리 API | 8개 | 7개 | 88% ⚠️ |
| Todo 관리 API | 4개 | 4개 | 100% ✅ |
| 템플릿 API | 2개 | 2개 | 100% ✅ |
| 대시보드 API | 1개 | 0개 | 0% ❌ |
| **전체 합계** | **27개** | **23개** | **85%** ⚠️ |
---
## 🎬 결론
### 종합 평가
- **전체 구현률**: 85% (23/27 API)
- **핵심 비즈니스 로직**: ⚠️ 회의 수정 기능 누락
- **사용자 경험**: ⚠️ 개선 필요 (대시보드 회의 목록, 회의 수정, 통계, 검색 기능)
- **코드 품질**: ✅ 우수 (문서화, 구조, 보안)
### 즉시 조치 필요 (🔴 긴급 - 3개)
1. 🔴 **회의 목록 조회 API 구현** (`GET /api/meetings`)
- 대시보드 "최근 회의" 섹션 표시 불가
2. 🔴 **회의 정보 수정 API 구현** (`PUT /api/meetings/{meetingId}`)
- **설계서에도 누락됨** - API 명세서 작성 필요
- 예정된 회의를 수정할 수 없음
- 대시보드에서 scheduled 회의 클릭 시 동작 불가
3. 🔴 **대시보드 통계 API 구현** (`GET /api/dashboard/statistics`)
- 대시보드 통계 카드 표시 불가
### 다음 스프린트 권장
3. 🟡 **AI 요약 재생성 API 구현** (사용자 경험 개선)
4. 🟡 **회의록 검색 기능 강화** (사용성 향상)
### 장기 개선 과제
5. 🟢 **버전 관리 API** (고급 기능)
6. 🟢 **Rate Limiting 적용** (보안 강화)
7. 🟢 **API 버전 관리 도입** (확장성)
---
**리뷰 완료일**: 2025-10-28
**리뷰어**: Architect, Backend Developer, Frontend Developer
**다음 리뷰 예정**: Phase 1 구현 완료 후
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+341 -257
View File
@@ -1,289 +1,373 @@
# 벡터DB 임베딩용 관련자료 샘플 데이터
**작성일**: 2025-01-22
**버전**: v1.0
**작성자**: AI 개발팀
## 📋 개요
---
본 데이터셋은 회의록 작성 및 공유 개선 서비스의 벡터DB 구축을 위한 샘플 데이터입니다.
통신회사의 8개 업무 도메인별로 4가지 문서 유형에 대해 각 50개씩, 총 **1,600개**의 샘플 문서를 제공합니다.
## 1. 개요
## 📊 데이터 구성
### 1.1 목적
회의록 작성 시 AI가 참조할 수 있는 관련 자료를 벡터DB에 임베딩하여, 맥락 기반 용어 설명 및 관련 회의록 자동 연결 기능을 제공하기 위한 샘플 데이터를 생성합니다.
### 업무 도메인 (8개)
1. **고객서비스** - VOC, 상담 품질, 고객 응대
2. **영업마케팅** - 요금제, 프로모션, 유통 채널
3. **요금청구** - 빌링, 과금, 미수금 관리
4. **네트워크운용** - 5G, 장애 대응, 트래픽 관리
5. **서비스기획** - 신규 서비스, 콘텐츠 제휴
6. **시스템운영** - IT 인프라, 클라우드, DevOps
7. **가입자관리** - 개통, 해지, 번호이동
8. **기업영업** - B2B 솔루션, 전용선, AICC
### 1.2 데이터 구성
- **도메인**: 통신 업무 도메인 15개
- **데이터 소스 유형**: 4가지 (이전 회의록, 조직문서, 프로젝트 문서, 운영문서)
- **샘플 개수**: 각 도메인별 × 각 소스별 5개 = **총 300개**
### 문서 유형 (4개)
1. **이전 회의록** (meeting_minutes)
- 회의 일시, 참석자, 안건, 결정사항, 조치사항 포함
- 실제 회의록 형식의 상세한 내용
---
2. **조직문서** (org_document)
- 업무 매뉴얼, 정책 가이드라인, 표준 절차서
- 공식 문서 형식의 구조화된 내용
## 2. 통신 업무 도메인 (15개)
3. **프로젝트 문서** (project_document)
- 요구사항 정의서, 설계서, 수행 계획서
- 프로젝트 관련 기술 문서
| 번호 | 도메인 | 설명 |
|------|--------|------|
| 1 | 네트워크 인프라 | 네트워크 구축 및 운영, 유무선 통신망 관리, 5G/LTE, 기지국 |
| 2 | 기술 개발 및 연구 | 신기술 연구개발, AI/빅데이터, IoT, 클라우드 기술 |
| 3 | 고객 서비스 | 고객 상담 및 지원, VoC 관리, 서비스 품질 관리 |
| 4 | 영업 및 마케팅 | 요금제 기획, 프로모션, 유통채널 관리, B2B/B2C 영업 |
| 5 | 요금 및 청구 | 요금 청구 시스템, 과금 관리, 미수금 관리, 정산 업무 |
| 6 | 네트워크 운용 | 네트워크 모니터링, 장애 대응 및 복구, 품질 최적화 |
| 7 | 서비스 기획 및 상품 개발 | 신규 서비스 기획, 요금제 설계, 콘텐츠 서비스 |
| 8 | 정보보안 | 통신 보안, 개인정보 보호, 사이버 보안, 보안 정책 수립 |
| 9 | 시스템 운영 및 관리 | IT 시스템 운영, 데이터센터 관리, 클라우드 인프라 |
| 10 | 가입자 관리 | 가입자 정보 관리, 번호 이동, 개통 및 해지, 명의 변경 |
| 11 | 망 품질 관리 | 통신 품질 측정, 품질 개선, 서비스 레벨 관리 |
| 12 | 규제 대응 및 준법 | 통신 규제 대응, 법률 준수, 정부 정책 대응 |
| 13 | 기업 영업 | B2B 솔루션, 전용선 서비스, AICC, 데이터센터 서비스 |
| 14 | 로밍 및 국제 업무 | 국제 로밍 서비스, 해외 통신사 제휴, 국제 전화 서비스 |
| 15 | 신사업 | OTT 서비스, 콘텐츠 사업, 핀테크, 스마트홈/IoT 서비스 |
4. **운영문서** (operation_document)
- 장애 보고서, 모니터링 결과, 대응 기록
- 실시간 운영 이슈 관련 문서
---
### 통계
- **총 문서 수**: 1,600개
- **도메인별**: 200개씩 (8개 도메인)
- **유형별**: 도메인당 50개씩 (4가지 유형)
## 3. 데이터 소스 유형 (4가지)
## 📁 파일 구조
### 3.1 이전 회의록 (meeting_minutes)
**형식**:
- 회의 제목, 일시, 참석자
- 논의 내용, 결정 사항, 액션 아이템
```
vector_db_sample_data.json
├── metadata # 메타데이터
│ ├── version # 버전 정보
│ ├── created_date # 생성 일시
│ ├── description # 설명
│ └── 통계 정보 # 문서 수, 카테고리 수 등
├── embedding_schema # 임베딩 스키마 정의
│ ├── document_id # 문서 고유 ID
│ ├── document_type # 문서 유형
│ ├── business_domain # 업무 도메인
│ ├── title # 제목
│ ├── content # 전체 본문 (임베딩 대상)
│ ├── summary # 3-5문장 요약
│ ├── keywords # 키워드 배열
│ ├── created_date # 생성 일시 (ISO8601)
│ ├── participants # 참석자/작성자
│ ├── metadata # 추가 메타데이터
│ └── embedding_vector # 임베딩 벡터 (1536차원)
└── sample_data # 실제 샘플 데이터
├── 고객서비스
│ ├── meeting_minutes # 50개
│ ├── org_document # 50개
│ ├── project_document # 50개
│ └── operation_document # 50개
├── 영업마케팅
│ ├── ... (동일 구조)
├── 요금청구
├── 네트워크운용
├── 서비스기획
├── 시스템운영
├── 가입자관리
└── 기업영업
```
**예시 토픽**:
- 프로젝트 킥오프, 월간 리뷰, 장애 대응, 정책 수립
## 🔧 데이터 스키마
**메타데이터**:
- 회의 유형, 참석자 목록, 태그
### 3.2 조직문서 (manual)
**유형**:
- 업무 매뉴얼, 정책 및 규정, 표준화 문서
**예시**:
- 프로세스 가이드, 보안 정책, 업무 표준
**메타데이터**:
- 문서 카테고리, 버전, 승인자
### 3.3 프로젝트 문서 (project_doc)
**유형**:
- 요구사항 정의서, 설계 문서, 수행 결과서
**예시**:
- 프로젝트 계획서, 기술 설계서, 완료 보고서
**메타데이터**:
- 프로젝트명, 단계, 담당자
### 3.4 운영문서 (operation_doc)
**유형**:
- 장애 보고서, 고객 응대 문서
**예시**:
- 장애 분석 보고서, 고객 이슈 처리 가이드
**메타데이터**:
- 심각도, 영향 범위, 해결 상태
---
## 4. 데이터 구조
### 4.1 JSON 스키마
### 공통 필드
```json
{
"document_id": "도메인명_소스유형_일련번호",
"document_type": "meeting_minutes|manual|project_doc|operation_doc",
"title": "문서 제목",
"content": "실제 문서 내용 (500-1000자)",
"metadata": {
"domain": "도메인명",
"date": "YYYY-MM-DD",
"author": "작성자명",
"tags": ["태그1", "태그2", "태그3"],
"organization_id": "org_telecom_001",
"folder_id": "folder_도메인명"
"document_id": "string", // 예: "고객-MM-001"
"document_type": "string", // meeting_minutes | org_document | project_document | operation_document
"business_domain": "string", // 8개 도메인 중 하나
"title": "string", // 문서 제목
"content": "string", // 전체 본문 (임베딩 대상)
"summary": "string", // 3-5문장 요약
"keywords": ["string"], // 키워드 배열
"created_date": "ISO8601", // 생성 일시
"participants": ["string"], // 참석자/작성자
"metadata": { // 추가 메타데이터
"folder": "string", // 폴더 경로
... // 문서 유형별 추가 필드
}
}
```
### 4.2 필드 설명
### 문서 유형별 추가 메타데이터
| 필드 | 타입 | 설명 |
|------|------|------|
| document_id | string | 문서 고유 식별자 |
| document_type | enum | 문서 유형 (4가지 중 1개) |
| title | string | 문서 제목 |
| content | text | 실제 문서 내용 (청킹 대상) |
| metadata.domain | string | 업무 도메인 |
| metadata.date | date | 작성일 (2024-01-01 ~ 2025-01-22) |
| metadata.author | string | 작성자명 |
| metadata.tags | array | 태그 배열 (3-5개) |
| metadata.organization_id | string | 조직 ID |
| metadata.folder_id | string | 폴더 ID |
---
## 5. 샘플 데이터 생성 방법
### 5.1 자동 생성 스크립트
**위치**: `tools/generate_vector_samples.py`
**실행 방법**:
```bash
# Windows PowerShell 또는 CMD에서 실행
cd C:\Users\hiond\home\workspace\HGZero
python tools\generate_vector_samples.py
#### 1. 회의록 (meeting_minutes)
```json
"metadata": {
"folder": "/고객서비스/회의록",
"agenda_count": 3,
"decision_items": ["결정사항1", "결정사항2"],
"action_items": ["조치사항1", "조치사항2"]
}
```
**출력 파일**: `data/samples/vector_db_samples_300.json`
### 5.2 생성 로직
#### 도메인별 키워드 매핑
각 도메인마다 관련 키워드 및 토픽을 정의하여 실제 통신 업무 상황을 반영합니다.
**예시** (네트워크 인프라):
- **키워드**: 5G, LTE, 기지국, 광케이블, RAN, 코어망, 백홀, 전송망
- **토픽**: 5G 구축, 기지국 설치, 망 이중화, 광케이블 교체, 커버리지 확대
#### 랜덤 요소
- 날짜: 2024-01-01 ~ 2025-01-22 범위에서 랜덤 선택
- 작성자: 16명의 작성자 풀에서 랜덤 선택
- 키워드 조합: 각 문서마다 2-3개 키워드를 랜덤 조합
#### 템플릿 기반 생성
각 문서 유형별로 표준 템플릿을 정의하고, 도메인 및 키워드를 치환하여 실제 문서처럼 생성합니다.
---
## 6. 생성 통계
### 6.1 전체 통계
- **총 샘플 개수**: 300개
- **도메인별**: 각 20개 (15개 도메인)
- **소스별**: 각 75개 (4가지 소스)
### 6.2 문서 유형별 분포
| 문서 유형 | 개수 | 비율 |
|-----------|------|------|
| 이전 회의록 (meeting_minutes) | 75개 | 25% |
| 조직문서 (manual) | 75개 | 25% |
| 프로젝트 문서 (project_doc) | 75개 | 25% |
| 운영문서 (operation_doc) | 75개 | 25% |
| **합계** | **300개** | **100%** |
### 6.3 도메인별 분포
| 도메인 | 회의록 | 매뉴얼 | 프로젝트 | 운영 | 합계 |
|--------|--------|--------|----------|------|------|
| 네트워크 인프라 | 5 | 5 | 5 | 5 | 20 |
| 기술 개발 및 연구 | 5 | 5 | 5 | 5 | 20 |
| 고객 서비스 | 5 | 5 | 5 | 5 | 20 |
| 영업 및 마케팅 | 5 | 5 | 5 | 5 | 20 |
| 요금 및 청구 | 5 | 5 | 5 | 5 | 20 |
| 네트워크 운용 | 5 | 5 | 5 | 5 | 20 |
| 서비스 기획 및 상품 개발 | 5 | 5 | 5 | 5 | 20 |
| 정보보안 | 5 | 5 | 5 | 5 | 20 |
| 시스템 운영 및 관리 | 5 | 5 | 5 | 5 | 20 |
| 가입자 관리 | 5 | 5 | 5 | 5 | 20 |
| 망 품질 관리 | 5 | 5 | 5 | 5 | 20 |
| 규제 대응 및 준법 | 5 | 5 | 5 | 5 | 20 |
| 기업 영업 | 5 | 5 | 5 | 5 | 20 |
| 로밍 및 국제 업무 | 5 | 5 | 5 | 5 | 20 |
| 신사업 | 5 | 5 | 5 | 5 | 20 |
| **합계** | **75** | **75** | **75** | **75** | **300** |
---
## 7. 벡터DB 임베딩 프로세스
### 7.1 데이터 정제
1. **텍스트 정제**: HTML 태그 제거, 특수문자 정규화
2. **청킹**: 문서를 1000 토큰 단위로 분할 (200 토큰 오버랩)
3. **메타데이터 추출**: JSON 메타데이터 파싱
### 7.2 벡터화
- **임베딩 모델**: text-embedding-3-small (OpenAI)
- **차원**: 1536
- **비용**: $0.02 / 1M 토큰
### 7.3 PostgreSQL + pgvector 적재
```sql
INSERT INTO document_chunks (
document_id,
chunk_index,
content,
embedding,
metadata,
organization_id
) VALUES (?, ?, ?, ?, ?, ?);
#### 2. 조직문서 (org_document)
```json
"metadata": {
"folder": "/고객서비스/정책/문서",
"document_version": "3.2",
"last_updated": "2024-06-01"
}
```
---
#### 3. 프로젝트 문서 (project_document)
```json
"metadata": {
"folder": "/프로젝트/고객서비스",
"project_status": "진행중", // 계획 | 진행중 | 완료
"document_type": "요구사항정의서"
}
```
## 8. 활용 방안
#### 4. 운영문서 (operation_document)
```json
"metadata": {
"folder": "/고객서비스/운영/장애보고",
"incident_number": "INC-2024-09-157",
"severity": "High", // Critical | High | Medium | Low
"status": "복구완료"
}
```
### 8.1 맥락 기반 용어 설명
1. 회의록 작성 중 전문 용어 감지
2. Vector DB에서 유사도 검색 (Top-5)
3. Claude AI에게 맥락 기반 설명 요청
## 💡 사용 예시
### 8.2 관련 회의록 자동 연결
1. 현재 회의록 내용 벡터화
2. Vector DB에서 유사 회의록 검색
3. 관련도 점수 계산 (70% 이상)
4. 최대 5개 회의록 자동 연결
### Python에서 데이터 로드
```python
import json
### 8.3 대시보드 참고자료
- 관련 회의록 탭: 유사 회의록 목록
- 프로젝트 문서 탭: 관련 프로젝트 문서
- 조직 문서 탭: 관련 매뉴얼 및 정책
# JSON 파일 로드
with open('vector_db_sample_data.json', 'r', encoding='utf-8') as f:
data = json.load(f)
# 특정 도메인의 회의록 가져오기
customer_service_meetings = data['sample_data']['고객서비스']['meeting_minutes']
# 첫 번째 회의록 확인
first_meeting = customer_service_meetings[0]
print(f"제목: {first_meeting['title']}")
print(f"요약: {first_meeting['summary']}")
print(f"키워드: {', '.join(first_meeting['keywords'])}")
```
### 임베딩 생성 예시
```python
from openai import OpenAI
client = OpenAI(api_key="your-api-key")
# 문서 임베딩 생성
def create_embedding(text):
response = client.embeddings.create(
model="text-embedding-3-small",
input=text
)
return response.data[0].embedding
# 모든 문서에 대해 임베딩 생성
for domain in data['sample_data']:
for doc_type in data['sample_data'][domain]:
for doc in data['sample_data'][domain][doc_type]:
# content 필드를 임베딩
embedding = create_embedding(doc['content'])
doc['embedding_vector'] = embedding
```
### 벡터DB에 저장 (Qdrant 예시)
```python
from qdrant_client import QdrantClient
from qdrant_client.models import Distance, VectorParams, PointStruct
# Qdrant 클라이언트 초기화
client = QdrantClient(url="http://localhost:6333")
# 컬렉션 생성
client.create_collection(
collection_name="meeting_documents",
vectors_config=VectorParams(size=1536, distance=Distance.COSINE)
)
# 문서 업로드
points = []
for domain in data['sample_data']:
for doc_type in data['sample_data'][domain]:
for doc in data['sample_data'][domain][doc_type]:
point = PointStruct(
id=doc['document_id'],
vector=doc['embedding_vector'], # 이미 생성된 임베딩
payload={
"title": doc['title'],
"summary": doc['summary'],
"keywords": doc['keywords'],
"domain": doc['business_domain'],
"type": doc['document_type'],
"created_date": doc['created_date']
}
)
points.append(point)
# 배치 업로드
client.upsert(collection_name="meeting_documents", points=points)
```
### 유사 문서 검색 예시
```python
# 쿼리 텍스트
query = "고객 만족도를 개선하기 위한 AI 챗봇 도입 방안"
# 쿼리 임베딩 생성
query_embedding = create_embedding(query)
# 유사 문서 검색
search_result = client.search(
collection_name="meeting_documents",
query_vector=query_embedding,
limit=5,
query_filter={
"must": [
{"key": "domain", "match": {"value": "고객서비스"}}
]
}
)
# 결과 출력
for hit in search_result:
print(f"유사도: {hit.score:.4f}")
print(f"제목: {hit.payload['title']}")
print(f"요약: {hit.payload['summary']}")
print("---")
```
## 🎯 활용 시나리오
### 1. 관련 회의록 검색
- **목적**: 현재 회의와 유사한 과거 회의록 찾기
- **방법**: 회의 주제/안건을 임베딩하여 유사도 검색
- **활용**: 과거 논의 내용 및 결정사항 참조
### 2. 맥락 기반 용어 설명
- **목적**: 회의 중 등장하는 전문 용어를 맥락에 맞게 설명
- **방법**: 용어와 관련된 조직문서/매뉴얼 검색
- **활용**: Claude API에 RAG context로 제공
### 3. 프로젝트 문서 자동 연결
- **목적**: 회의 내용과 관련된 프로젝트 문서 추천
- **방법**: 회의록과 프로젝트 문서 간 유사도 계산
- **활용**: 참고 자료 자동 링크
### 4. 장애 이력 조회
- **목적**: 유사한 장애 발생 시 과거 대응 사례 검색
- **방법**: 장애 키워드로 운영문서 검색
- **활용**: 빠른 장애 해결을 위한 레퍼런스
## 📝 데이터 특징
### 1. 실제 업무 환경 반영
- 통신회사의 실제 업무 도메인 구조
- 각 도메인별 특화된 키워드 및 용어
- 업무 프로세스와 연결된 문서 구조
### 2. 다양한 문서 유형
- 회의록: 비정형 대화체 문서
- 조직문서: 정형 정책 문서
- 프로젝트 문서: 기술 문서
- 운영문서: 시간 기반 이벤트 문서
### 3. 풍부한 메타데이터
- 문서 분류를 위한 도메인/유형 정보
- 검색 최적화를 위한 키워드
- 관계 추적을 위한 참석자/날짜 정보
- 폴더 구조 정보
### 4. 임베딩 최적화
- 평균 문서 길이: 500~2000자
- 요약문 제공으로 빠른 이해 가능
- 키워드 기반 하이브리드 검색 지원
## 🔍 검색 전략 권장사항
### 1. 하이브리드 검색
```python
# 키워드 필터 + 벡터 유사도 검색
search_result = client.search(
collection_name="meeting_documents",
query_vector=query_embedding,
query_filter={
"must": [
{"key": "domain", "match": {"value": "고객서비스"}},
{"key": "keywords", "match": {"any": ["VOC", "챗봇"]}}
]
},
limit=10
)
```
### 2. 시간 기반 필터링
```python
# 최근 1년 이내 문서만 검색
from datetime import datetime, timedelta
one_year_ago = (datetime.now() - timedelta(days=365)).isoformat()
search_result = client.search(
collection_name="meeting_documents",
query_vector=query_embedding,
query_filter={
"must": [
{"key": "created_date", "range": {"gte": one_year_ago}}
]
}
)
```
### 3. 문서 유형별 가중치
```python
# 회의록 우선, 프로젝트 문서 보조
meeting_results = search(query, filter={"type": "meeting_minutes"}, limit=3)
project_results = search(query, filter={"type": "project_document"}, limit=2)
# 결과 병합
all_results = meeting_results + project_results
```
## 🚀 확장 가능성
### 1. 실제 데이터 연동
- Confluence API 연동
- SharePoint 문서 수집
- 이메일 아카이브 통합
### 2. 추가 메타데이터
- 문서 중요도 점수
- 조회수/활용도 통계
- 사용자 피드백 (좋아요/별점)
### 3. 고급 검색 기능
- 시맨틱 검색 (Azure AI Search)
- 다중 벡터 검색 (제목/본문 분리)
- Re-ranking (Claude 활용)
## 📚 관련 문서
- `구현방안-관련자료.md`: 관련자료 검색 시스템 구현 상세
- `구현방안-용어집.md`: 용어집 구축 및 Claude 연동 방안
- `통신업무도메인.md`: 통신회사 업무 도메인 정의
## 🤝 기여
샘플 데이터 개선 제안이나 추가 도메인 요청은 프로젝트 팀에 문의하세요.
---
## 9. 품질 검증
### 9.1 데이터 품질 기준
- **실무 반영도**: 실제 통신 업무 용어 및 상황 반영 여부
- **일관성**: 도메인 및 문서 유형별 일관성 유지
- **다양성**: 키워드 및 토픽의 다양성 확보
### 9.2 검증 방법
1. **샘플링 검사**: 각 도메인별 1-2개 샘플 수동 검토
2. **키워드 분석**: 도메인 관련 키워드 포함 여부 확인
3. **메타데이터 검증**: 필수 필드 누락 여부 확인
---
## 10. 향후 계획
### 10.1 데이터 확장
- **단계 1** (현재): 300개 샘플 (도메인별 × 소스별 5개)
- **단계 2** (Phase 1 완료 후): 600개 샘플 (도메인별 × 소스별 10개)
- **단계 3** (Phase 2 이후): 1,500개 샘플 (도메인별 × 소스별 25개)
### 10.2 품질 개선
- 실제 회의록 데이터 반영
- 도메인 전문가 검토 및 피드백 반영
- 사용자 피드백 기반 지속 업데이트
---
## 11. 참고 자료
### 11.1 관련 문서
- [회의 주제 관련 자료 수집 및 Claude AI 연동 구현 방안](../구현방안-관련자료.md)
- [ADR-001: Vector Database 및 Embedding 통합 아키텍처](../ADR-001-Vector-DB-통합아키텍처.md)
- [통신업무도메인](../../reference/통신업무도메인.md)
### 11.2 기술 스택
- **Vector DB**: PostgreSQL + pgvector
- **Embedding**: OpenAI text-embedding-3-small (1536 dim)
- **검색**: 하이브리드 (벡터 유사도 + 키워드 매칭)
- **캐싱**: Redis + Claude Prompt Cache
---
**문서 버전**: v1.0
**최종 수정**: 2025-01-22
**담당자**: AI 개발팀
**버전**: 1.0
**생성일**: 2025-10-28
**생성자**: 회의록 작성 및 공유 개선 프로젝트 팀
+19 -25
View File
@@ -2,9 +2,9 @@
## 문서 정보
- **작성일**: 2025-10-21
- **최종 수정일**: 2025-10-27
- **최종 수정일**: 2025-10-28
- **작성자**: 이미준 (서비스 기획자)
- **버전**: 1.5.3
- **버전**: 1.5.4
- **설계 철학**: Mobile First Design
---
@@ -289,32 +289,25 @@ graph TD
- **최근 회의** 섹션
- 헤더: "예정된 회의" (H4) + "전체 보기 →" 링크
- 회의 리스트 (최대 3개, 우선순위 순)
1. **진행중 회의** (우선 표시)
- 상태: 회의 시작됨, 아직 종료 안 됨, 참여 가능
- 긴급 표시: "진행중" 배지 (빨강/주황색, 애니메이션)
2. **예정된 회의** (시작 전)
- 상태: 회의 일시 >= 현재 시간
- D-day 표시 (긴급도에 따라 색상 구분)
- 각 항목:
- **상태 배지** (최우선 표시):
- "진행중" (빨강/주황, 깜빡임 애니메이션) - 진행중 회의
- "D-1", "D-day", "3시간 후" 등 - 예정된 회의
- **정렬 기준** (UFR-USER-020 기준):
1. **1순위**: 회의록 미생성 회의 (진행중 + 예정) 우선 표시
2. **2순위**: 미생성이 3개 미만이면 최근 종료된 회의(회의록 있음)로 나머지 채움
3. **각 그룹 내 정렬**: 빠른 일시 순 (시작 시간 기준)
4. **최대 표시**: 3개
- **회의 카드** (클릭 가능 블록):
- 상태 라벨 (배지)
- 진행중: "진행중"
- 예정: "예정"
- 완료: "작성중" 또는 "확정완료"
- 회의 제목 (H5)
- 생성자 표시 (👑 아이콘) - 내가 생성한 회의인 경우
- 회의 일시 (아이콘: calendar_today)
- 참석자 수 (아이콘: people)
- **역할 표시** (예정된 회의만):
- "생성자" 아이콘 (작은 크라운 아이콘) - 내가 생성한 회의
- "참석자" 아이콘 표시 안 함 - 초대받은 회의
- **액션 버튼** (권한 및 시간 기반):
- **진행중 회의**: "참여하기" 버튼 (Primary, 모든 참석자)
- **예정된 회의 - 생성자**:
- "수정" 버튼 (Secondary, 작은 크기)
- 클릭 시 회의 예약 수정 화면으로 이동
- **예정된 회의 - 초대받은 참석자**:
- 시작 10분 이내: "참여하기" 버튼 활성화 (Primary)
- 시작 10분 초과: 버튼 없음 또는 비활성화
- 타이머 표시: "10분 후 참여 가능" (시작 시간까지 남은 시간)
- 장소 정보
- 상태 버튼 (표시용):
- 진행중: "참여하기" 버튼
- 예정: "수정하기" 버튼
- 완료: "보기" 버튼
- 빈 상태: "예정된 회의가 없습니다"
- **내 회의록** 카드 - **v1.5.0 변경 (Todo 섹션 제거)**
@@ -2189,6 +2182,7 @@ graph TD
| 1.5.1 | 2025-10-27 | 강지수 | MVP 스코프 축소 v2.4.0 반영 (4개 화면 수정)<br>- **02-대시보드**: Todo 위젯 및 통계 제거 (UFR-USER-020 반영)<br> - Todo 위젯 전체 제거 (나의 Todo 섹션 삭제)<br> - 통계 카드: "나의 Todo" 제거, "작성중 회의록" 유지 (2개 항목)<br> - 네비게이션: 하단 네비게이션 및 사이드바에서 Todo 관리 메뉴 제거<br> - Desktop 통계 그리드: 2개 항목만 표시<br>- **05-회의진행**: "AI 제안" 탭 → "AI 기반 메모" 탭 기능 변경<br> - 메모 입력창 + 저장 버튼 추가<br> - AI가 감지한 주요 내용 리스트 표시 (시간 + 내용)<br> - 각 참석자별 개별 저장, 다른 참석자 메모 볼 수 없음<br> - 메모는 회의 종료 전까지만 표시/편집 가능<br> - 에러 처리: AI 주요 내용 감지 실패, 메모 저장 실패 추가<br>- **10-회의록상세조회**: Todo 단순 조회 기능으로 변경<br> - Todo는 제목 + 담당자 + 마감일만 표시<br> - D-day 라벨, 우선순위 배지, 진행률 바, 상태별 필터 제거<br> - Todo 관리 화면 연동 링크 제거 (화면 자체가 제거됨)<br> - "수정" 버튼을 헤더로 이동<br>- **11-회의록수정**: 실시간 협업 기능 제거, 안건 기반 충돌 방지 강화<br> - "편집 중" 표시 제거 (실시간 협업 기능 제거)<br> - Todo 편집/추가/삭제 기능 전체 제거 (단순 조회만 가능)<br> - AI 한줄 요약 재생성 불가 (회의 종료 시 1회만 생성)<br> - 검증률 표시 및 최종 확정 버튼 제거<br> - 저장 로직 추가: 검증완료 안건 저장 스킵, 저장 결과 알림<br> - 안건별 검증 완료 체크박스로 충돌 방지 (Last Write Wins 적용)<br> - 에러 처리: 충돌 경고 모달 제거 (LWW로 인해) |
| 1.5.2 | 2025-10-27 | 강지수 | AI 요약 기능 통합 및 단순화 (유저스토리 v2.4.0 반영)<br>- **11-회의록수정**: AI 요약 기능 통합<br> - 명칭 변경: "AI 상세 요약" → "AI 요약"<br> - AI 요약 영역: AI 한줄 요약만 표시 (30자 이내, 읽기 전용)<br> - 텍스트 편집 영역: 안건 내용 자유 작성 (논의 주제, 발언자별 의견, 결정 사항 등)<br> - "AI 재생성" 버튼: 텍스트 편집 영역 내용 기반으로 AI 요약의 한줄 요약 재생성 (2-5초 처리)<br> - 재생성된 한줄 요약은 회의록 상세조회 화면의 대시보드 및 회의록 탭에 즉시 반영<br> - AI 상세 요약 및 한줄 요약 분리 표시 제거<br>- **프로토타입 UI 개선**:<br> - AI 재생성 버튼 스타일 통일: btn-secondary → btn-primary (다른 화면과 일관성)<br> - 안건별 검증완료 UI 단순화: 참석자는 체크박스만, 회의 생성자는 검증완료 시 잠금해제 버튼 표시<br> - .creator-only CSS 클래스 추가: data-is-creator 속성 기반 표시 제어<br>- **관련 유저스토리**: UFR-AI-036 (AI 한줄요약 확인 및 재생성), UFR-MEET-055 (안건별 검증), UFR-COLLAB-030 (충돌 방지) |
| 1.5.3 | 2025-10-27 | 강지수 | Todo 추가/편집 권한 정책 명확화 (유저스토리 v2.4.1 반영)<br>- **10-회의록상세조회**: Todo 추가/편집 권한 정책 추가 (대시보드 탭)<br> - "추가" 버튼: 모든 회의 참석자에게 노출 (Todo 리스트 우측 상단)<br> - "편집(✏️)" 버튼: 회의 생성자에게만 노출 (각 Todo 항목 우측)<br> - Todo 추가 모달: 제목, 담당자, 마감일 입력 (모든 참석자)<br> - Todo 편집 모달: 제목, 담당자, 마감일 수정 (회의 생성자만)<br> - 담당자 필드: 추가 시 또는 생성자의 편집 시만 표시<br>- **프로토타입 UI 개선**: 10-회의록상세조회.html<br> - Todo 추가/편집 모달 바텀시트 스타일 통일 (모바일: 하단 슬라이드 업, 데스크톱: 중앙 모달)<br> - .creator-only 클래스 적용하여 편집 버튼 권한별 표시/숨김 처리<br> - JavaScript initPage() 함수에서 회의 생성자 여부 확인 후 creator-only 요소 제어<br> - Todo 추가 성공: "담당자에게 알림이 전송되었습니다" → "캘린더가 업데이트되었습니다" 순차 토스트<br> - Todo 편집 성공: 담당자 변경 시 알림, 마감일 변경 시 캘린더 업데이트 토스트<br>- **관련 유저스토리**: UFR-MEET-047 (회의록상세조회), Todo 권한 정책 신규 추가 |
| 1.5.4 | 2025-10-28 | 도그냥 | 대시보드 최근 회의 리스트 디자인 간소화 (UFR-USER-020 반영)<br>- **02-대시보드**: 최근 회의 정렬 기준 명확화 및 디자인 간소화<br> - **정렬 기준**:<br> - 1순위: 회의록 미생성 회의 (진행중 + 예정) 우선 표시<br> - 2순위: 미생성이 3개 미만이면 최근 종료된 회의(회의록 있음)로 나머지 채움<br> - 각 그룹 내 정렬: 빠른 일시 순 (시작 시간 기준)<br> - 최대 표시: 3개<br> - **회의 카드 (클릭 가능 블록)**:<br> - 상태 라벨 (배지): "진행중", "예정", "작성중", "확정완료"<br> - 회의 제목 + 생성자 아이콘(👑)<br> - 회의 일시, 참석자 수, 장소<br> - 상태 버튼 (표시용): "참여하기", "수정하기", "보기"<br> - **디자인 간소화**: D-day 표시, 깜박임 애니메이션, 세부 색상 지정 등 제거<br>- **유저스토리**: UFR-USER-020 (대시보드 조회) 동일하게 수정 |
[↑ 목차로 돌아가기](#목차)
+43 -4
View File
@@ -115,10 +115,14 @@
- 예정된 회의: 전체 예정 + 진행 중 회의 개수
- 작성중 회의록: 내가 참석한 회의 중 '작성중' 상태인 회의록 개수 (클릭 액션 없음, 정보 표시만)
- 최근 회의 (회의록 미생성 우선, 빠른 일시 순, 최대 3개):
- 회의 카드: 상태 배지, 제목, 생성자 표시(👑), 날짜/시간, 참석자 수, 장소, 액션 버튼
- 진행 중 회의: 좌측 녹색 바 강조, "참여하기" 버튼
- 예정 회의: 생성자인 경우 "수정" 버튼
- 완료 회의: "보기" 버튼
- 정렬 기준:
- 1순위: 회의록 미생성 회의 (진행중 + 예정)
- 2순위: 생성이 3개 미만이면 최근 종료된 회의(회의록 있음)로 나머지 채움
- 각 그룹 내 정렬: 빠른 일시 순 (시작 시간 기준)
- 회의 카드 (클릭 가능 블록): 상태 라벨, 제목, 생성자(👑), 날짜/시간, 참석자 수, 장소, 상태 버튼
- 진행중: "진행중" 라벨, "참여하기" 버튼
- 예정: "예정" 라벨, "수정하기" 버튼
- 완료: "작성중" 또는 "확정완료" 라벨, "보기" 버튼
- 나의 회의록 (최신순, 최대 4개, 2x2 그리드):
- 회의록 카드: 상태 배지, 생성자 표시(👑), 제목, 날짜/시간, 참석자 수, 검증완료율(작성중인 경우)
- 사이드바 (데스크톱): 로고, 메뉴(대시보드, 회의록), 사용자 정보, 로그아웃
@@ -135,6 +139,7 @@
**관련 유저스토리:**
- UFR-USER-010: 로그인
- UFR-MEET-010: 회의예약
- UFR-MEET-011: 회의정보수정
- UFR-MEET-020: 템플릿선택
- UFR-MEET-046: 회의록목록조회
- UFR-MEET-047: 회의록상세조회
@@ -190,10 +195,44 @@
**관련 유저스토리:**
- UFR-USER-020: 대시보드 조회
- UFR-MEET-011: 회의정보수정
- UFR-MEET-020: 템플릿선택
---
### UFR-MEET-011: [회의정보수정] 회의 생성자로서 | 나는, 예정된 회의 정보를 변경하기 위해 | 회의 정보를 수정하고 싶다.
**수행절차:**
1. 대시보드(02-대시보드.html)에서 예정된 회의(scheduled) 카드 클릭
2. 회의예약 화면(03-회의예약.html)으로 이동 (기존 회의 정보 로드)
3. 수정할 항목 변경 (제목, 날짜, 시간, 장소, 참석자, 안건 등)
4. "수정 완료" 버튼 클릭
5. 변경 사항 저장 및 참석자에게 알림 발송
**입력:**
- 기존 회의 정보: 자동 로드 (제목, 날짜, 시간, 장소, 참석자, 안건)
- 수정 항목: UFR-MEET-010과 동일한 입력 필드
**출력/결과:**
- 수정 완료: "회의 정보가 수정되었습니다" 토스트 메시지, 대시보드로 이동
- 참석자 변경 시: 기존 참석자 및 신규 참석자에게 알림 발송
- 알림 유형: "회의 정보 변경"
- 알림 내용: "{회의 제목} 회의 정보가 변경되었습니다"
- 임시저장: "임시 저장되었습니다" 토스트 메시지
**예외처리:**
- 회의 상태가 'scheduled'가 아닌 경우: "진행 중이거나 종료된 회의는 수정할 수 없습니다" 에러 메시지
- 생성자가 아닌 경우: "회의 생성자만 수정할 수 있습니다" 에러 메시지
- 유효성 검사 실패: UFR-MEET-010과 동일한 예외처리
- 뒤로가기/취소 클릭: "변경 사항이 저장되지 않았습니다. 나가시겠습니까?" 확인 모달
**관련 유저스토리:**
- UFR-USER-020: 대시보드 조회
- UFR-MEET-010: 회의예약
- UFR-NOTI-010: 알림발송
---
### UFR-MEET-015: [회의진행] 회의 참석자로서 | 나는, 회의 중 추가 참석자가 필요할 때 | 실시간으로 참석자를 초대하고 싶다.
**수행절차:**
+88 -47
View File
@@ -819,57 +819,79 @@ private RelatedMeeting createFallbackRelatedMeeting(SearchResult result) {
### AD-000: 통합 플랫폼 전략 (용어집 + 관련회의록)
**결정**: 단일 Azure AI Search 계정에 두 개의 별도 인덱스 운영
> **⚠️ 업데이트**: 2025-10-28
>
> 이 섹션은 초기 계획이었으며, 최종적으로 **하이브리드 접근 전략**으로 결정되었습니다.
>
> **최종 결정 문서**: `design/아키텍처_최적안_결정.md` 참조
**통합 아키텍처**:
**최종 결정**: 하이브리드 접근 - 단계적 독립 → 선택적 통합
**Phase 1-3 아키텍처** (현재 적용):
```
┌─────────────────────────────────────────────────────────────┐
│ AI Service (Backend) │
├─────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────────────┐ ┌──────────────────────┐ │
│ │ 용어집 기능 │ │ 관련회의록 기능 │ │
│ │ (Term Glossary) │ │ (Related Meetings) │ │
│ └──────────┬───────────┘ └──────────┬───────────┘ │
│ │ │ │
│ ┌──────────▼───────────┐ ┌──────────▼───────────┐ │
│ │ PostgreSQL │ │ Azure AI Search │ │
│ │ + pgvector │ │ (meetings-index) │ │
│ │ │ │ │ │
│ │ • 소규모 (수백 건) │ │ • 대규모 (수만 건) │ │
│ │ • 키워드 우선 │ │ • Vector 우선 │ │
│ │ • 트랜잭션 보장 │ │ • Semantic Ranking │ │
│ └──────────────────────┘ └──────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ 공통 컴포넌트 (Shared Components) │ │
│ ├─────────────────────────────────────────────────────┤ │
│ │ • Azure OpenAI Embedding (text-embedding-ada-002) │ │
│ │ • Claude 3.5 Sonnet (맥락 설명 / 요약 생성) │ │
│ │ • Redis (L1 캐싱, TTL 1-24시간) │ │
│ └─────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
```
**Phase 4 통합 옵션** (조건부):
**통합 조건**:
1. 용어집 데이터 규모 500개 이상
2. PostgreSQL+pgvector 성능 이슈 (응답 시간 > 500ms)
3. 관리 복잡도가 비용 절감액($85/월)을 상회
**통합시 아키텍처**:
```
┌─────────────────────────────────────────────────────────────┐
│ Azure AI Search (단일 계정) │
│ ┌──────────────────────┐ ┌────────────────────────────┐ │
│ │ terms-index │ │ meetings-index │ │
│ │ (용어집 전용) │ │ (관련회의록 전용) │ │
│ │ - 소규모 (수백 건) │ │ - 대규모 (수만 건) │ │
│ │ - 작은 청크(400 tok) │ │ - 큰 청크(2000-2500 tok) │ │
│ │ - Keyword 우선 │ │ - Vector 우선 │ │
│ │ (용어집) │ │ (관련회의록) │ │
│ │ - 수백 건 │ │ - 수만 건 │ │
│ │ - 256-512 tok │ │ - 2000-2500 tok │ │
│ │ - Keyword 우선 │ │ - Hybrid + Semantic │ │
│ └──────────────────────┘ └────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
│ 공통 사용
┌──────────────────────────┼────────────────────────────────┐
│ Azure OpenAI Embedding │ Claude 3.5 Sonnet │
│ text-embedding-ada-002 │ 맥락 설명 / 요약 생성 │
└──────────────────────────┴────────────────────────────────┘
│ 공통 사용
┌──────────────────────────┼────────────────────────────────┐
│ Redis L1 Cache (1시간 TTL) │
│ - 용어 설명 캐싱 │
│ - 관련 회의록 추천 캐싱 │
└─────────────────────────────────────────────────────────────┘
▲ ▲
│ │
┌──────────┴──────────┐ ┌───────────┴────────────┐
│ CDN L2 Cache │ │ PostgreSQL L2 Cache │
│ (용어 설명) │ │ (관련 회의록 매핑) │
│ - 정적 콘텐츠 │ │ - 동적 관계 데이터 │
└─────────────────────┘ └────────────────────────┘
```
**대안 비교**:
| 대안 | 장점 | 단점 | 점수 |
|-----|------|------|------|
| **단일 계정 + 별도 인덱스** ✅ | • 비용 절감 (단일 Standard tier)<br>• 독립적 최적화<br>• 통합 관리<br>• 확장성 | • 인덱스 수 제한 고려 필요 | **10/10** |
| 별도 Azure AI Search 계정 | • 완전 독립성<br>• 리소스 격리 | • 비용 2배 ($500/월)<br>• 관리 복잡도 증가 | 6/10 |
| 단일 인덱스 공유 | • 가장 저렴<br>• 관리 단순 | • 스키마 충돌<br>• 성능 저하<br>• 최적화 불가 | 3/10 |
| 별도 Vector DB (Pinecone 등) | • 특화 기능 | • 비용 증가<br>• 통합 복잡<br>• 일관성 부족 | 5/10 |
| **하이브리드 접근** ✅ | • 각 기능별 최적 DB 선택<br>• 초기 비용 40% 절감<br>• 점진적 확장<br>• 리스크 분산 | • 관리 복잡도 증가<br>• 통합시 마이그레이션 필요 | **9/10** |
| 단일 Azure AI Search (초기) | • 통합 관리<br>• 일관된 검색 엔진 | • 용어집 초기에 과도한 인프라<br>• 초기 비용 높음 ($250/월 추가) | 7/10 |
| 완전 독립 (Qdrant) | • 완전 독립성<br>• 각 기능 최적화 | • 높은 운영 비용 ($1,400/월)<br>• 관리 복잡도 최고 | 5/10 |
**결정 이유**:
1. **비용 효율성**: Standard tier $250/월 공유 (별도 계정 대비 50% 절감)
2. **독립 최적화**: 각 기능별 최적 스키마 및 설정
3. **운영 단순성**: 단일 플랫폼 통합 모니터링
4. **확장성**: 각 인덱스 독립 스케일링
1. **비용 효율성**: Phase 1-2에서 $250/월 절감 ($966 → $410)
2. **기술적 타당성**: 용어집(정확 매칭) vs 관련회의록(의미 검색)의 요구사항 차이
3. **운영 복잡도**: PostgreSQL 기존 활용으로 학습 곡선 최소화
4. **확장성**: 명확한 마이그레이션 경로 보유
**공통 컴포넌트**:
- **Embedding**: Azure OpenAI text-embedding-ada-002 (일관된 벡터 공간)
@@ -877,23 +899,42 @@ private RelatedMeeting createFallbackRelatedMeeting(SearchResult result) {
- **L1 Cache**: Redis (통합 캐싱 플랫폼)
**차별화 전략**:
- **용어집**: JSON 우선 + RAG fallback (하이브리드)
- **관련회의록**: Hybrid Search + Semantic Ranking (순수 벡터)
- **캐싱 L2**: CDN (정적) vs PostgreSQL (동적)
- **용어집**: 키워드 우선 + Vector Fallback (정확성 중시)
- **관련회의록**: Hybrid Search + Semantic Ranking (맥락 중시)
- **캐싱 L2**: PostgreSQL (메타데이터 + 관계)
**비용 분석** (월간):
```
Azure AI Search Standard: $250
Azure OpenAI Embedding: $55 (용어집 $25 + 관련자료 $30)
Claude API: $366 (용어집 $150 + 관련자료 $216)
Redis Enterprise: $50
CDN: $10
PostgreSQL Storage: $10
─────────────────────────────
통합 총계: $741/월
개별 계정 대비 절감: $250/월 (25% 절감)
**Phase 3 (독립 운영)**:
```
PostgreSQL (용어집): $50
Azure AI Search (회의록): $250
Redis: $80 (통합)
Azure OpenAI Embedding: $50
Claude API: $516
Storage: $20
─────────────────────────────
총계: $966/월
```
**Phase 4 (통합시)**:
```
Azure AI Search (통합): $250
PostgreSQL (메타만): $50
Redis: $50
Azure OpenAI Embedding: $55
Claude API: $516
Storage: $40
─────────────────────────────
총계: $881/월
절감액: $85/월 (8.8%)
```
**마이그레이션 비용**: $5,000 (일회성)
**참조 문서**:
- **최종 결정**: `design/아키텍처_최적안_결정.md`
- **용어집 상세**: `design/구현방안-용어집.md`
---
+31 -10
View File
@@ -698,23 +698,39 @@ Phase 3 (고도화 - 8주):
**컨텍스트**:
- 초기에는 데이터량이 적어 pgvector로 충분
- Qdrant는 전문 벡터 DB로 성능 우수하나 인프라 복잡도 증가
- 관련회의록 기능은 Azure AI Search 사용 (별도 독립)
- 용어집은 정확한 키워드 매칭이 중요하여 PostgreSQL 적합
- 단계적 접근으로 리스크 분산
**대안 고려**:
1. **Pinecone**: 관리형 서비스, 쉬운 시작 vs 높은 운영 비용 ($70/월~)
2. **Weaviate**: 오픈소스, 풍부한 기능 vs 학습 곡선
3. **pgvector**: 간단한 설정, 기존 DB 활용 vs 성능 제한
1. **PostgreSQL+pgvector** ✅:
- 기존 DB 활용, 트랜잭션 보장, 학습 곡선
- 소규모에 적합, 비용 $0 (기존 DB)
2. **Azure AI Search (초기 도입)**:
- 고성능 검색, Semantic Ranking, 관리형 서비스
- 소규모에 과도, 비용 $250/월
3. **Qdrant (self-hosted)**:
- 전문 Vector DB, 고성능, 오픈소스
- 운영 부담, 학습 곡선 높음, 비용 $500/월
4. **Pinecone (managed)**:
- 관리형 서비스, 쉬운 사용, 고성능
- 비용 높음 ($70-200/월), 한국어 지원 부족
**결정 근거**:
- MVP 단계에서는 pgvector의 단순성 우선
- 사용자 1000명 이상 시 Qdrant 전환 (명확한 마이그레이션 기준)
- 비용 효율성: pgvector 무료 vs Qdrant 자체 호스팅 $500/월 vs Pinecone $1000/월
- **Phase 1-2**: pgvector의 단순성 및 비용 효율성 우선
- **Phase 3 조건**: 용어 500개 이상 OR 성능 이슈 OR 관리 복잡도 증가
- **Phase 3 옵션 A**: Azure AI Search (terms-index) 마이그레이션 ($250/월 추가 비용 없음, 관련회의록과 공유)
- **Phase 3 옵션 B**: 현상 유지 (독립 운영)
- **비용 효율성**: pgvector 무료 vs Azure AI Search 통합시 $0 추가 vs Qdrant $500/월
**결과**:
- 초기 인프라 비용 절감 (PostgreSQL 활용)
- 검증된 기술 스택 사용으로 팀 학습 부담 감소
- 명확한 확장 경로 확보
- 관련회의록과 독립적으로 운영하여 장애 격리
- Phase 4에서 조건 충족시 Azure AI Search 통합 옵션 보유
---
@@ -1811,6 +1827,11 @@ class ClaudeAPIClient:
---
**작성일**: 2025-10-28
**최종 업데이트**: 2025-10-28 (아키텍처 최적안 반영)
**작성자**: 회의록 개선 프로젝트 팀
**버전**: 1.0
**승인자**: 김민준 (Product Owner)
**버전**: 1.1
**승인자**: 김민준 (Product Owner), 홍길동 (Architect)
**관련 문서**:
- **아키텍처 최적안 결정**: `design/아키텍처_최적안_결정.md`
- **관련회의록 구현방안**: `design/구현방안-관련자료.md`
File diff suppressed because it is too large Load Diff
@@ -31,7 +31,7 @@ public class SecurityConfig {
private final JwtTokenProvider jwtTokenProvider;
@Value("${cors.allowed-origins:http://localhost:*}")
@Value("${cors.allowed-origins:http://localhost:*,http://hgzero.20.249.184.228.nip.io/*}")
private String allowedOrigins;
@Bean
@@ -83,6 +83,6 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter {
path.startsWith("/swagger-ui") ||
path.startsWith("/v3/api-docs") ||
path.equals("/health") ||
path.equals("/api/v1/auth/login");
path.equals("/api/auth/login");
}
}