mirror of
https://github.com/hwanny1128/HGZero.git
synced 2025-12-06 13:46:24 +00:00
15 KiB
15 KiB
Meeting Service 데이터베이스 스키마 분석 최종 보고서
작성일: 2025-10-28
분석 대상: Meeting Service (feat/meeting-ai 브랜치)
분석 범위: 마이그레이션 V1~V4, 엔티티 구조, 데이터 플로우
Executive Summary
핵심 발견사항
-
minutes 테이블에 content 필드가 없음
- 실제 회의록 내용은
minutes_sections.content에 저장 - minutes 테이블은 메타데이터만 보유 (title, status, version 등)
- 실제 회의록 내용은
-
사용자별 회의록 완벽하게 지원 (V3)
minutes.user_id = NULL: AI 통합 회의록minutes.user_id = 참석자ID: 개인별 회의록- 인덱스:
idx_minutes_meeting_user(meeting_id, user_id)
-
AI 분석 결과 구조화 저장 (V3, V4)
agenda_sections: 안건별 구조화된 요약ai_summaries: AI 처리 결과 캐싱todos(V4): 각 안건의 JSON으로 저장
-
정규화 완료 (V2)
meetings.participants(CSV) →meeting_participants(테이블)- 복합 PK: (meeting_id, user_id)
데이터베이스 구조 개요
테이블 분류
핵심 테이블 (V1):
meetings: 회의 기본 정보minutes: 회의록 메타데이터minutes_sections: 회의록 섹션 (실제 내용)
참석자 관리 (V2):
meeting_participants: 회의 참석자 정보
AI 분석 (V3):
agenda_sections: 안건별 AI 요약ai_summaries: AI 처리 결과 캐시todos: Todo 아이템 (expanded)
1. 핵심 테이블별 상세 분석
1.1 meetings (회의 기본 정보)
구성:
- PK: meeting_id (VARCHAR(50))
- 주요 필드: title, purpose, description
- 상태: SCHEDULED → IN_PROGRESS → COMPLETED
- 시간: scheduled_at, started_at, ended_at (V3)
중요 변경:
- V3에서
ended_at추가 - 회의 정확한 종료 시간 기록
-- 조회 예시
SELECT * FROM meetings
WHERE status = 'COMPLETED'
AND ended_at >= NOW() - INTERVAL '7 days'
ORDER BY ended_at DESC;
1.2 minutes (회의록 메타데이터)
구성:
minutes_id (PK)
├─ meeting_id (FK)
├─ user_id (V3) ← NULL: AI 통합 회의록 / NOT NULL: 개인 회의록
├─ title
├─ status (DRAFT, FINALIZED)
├─ version
├─ created_by, finalized_by
└─ created_at, finalized_at
중요:
- content 필드 없음 → minutes_sections에 저장
- 메타데이터만 관리 (생성자, 확정자, 버전 등)
쿼리 패턴:
-- AI 통합 회의록
SELECT * FROM minutes
WHERE meeting_id = ? AND user_id IS NULL;
-- 특정 사용자의 회의록
SELECT * FROM minutes
WHERE meeting_id = ? AND user_id = ?;
-- 복합 인덱스 활용: idx_minutes_meeting_user
1.3 minutes_sections (회의록 섹션 - 실제 내용)
구성:
section_id (PK)
├─ minutes_id (FK) ← 어느 회의록에 속하는가
├─ type (AGENDA, DISCUSSION, DECISION, ACTION_ITEM)
├─ title
├─ content ← ★ 실제 회의록 내용
├─ order
├─ verified (검증 완료)
├─ locked (수정 불가)
└─ locked_by
핵심 특성:
- content: 사용자가 작성한 실제 내용
- locked: finalize_minutes 호출시 잠금
- verified: 확정시 TRUE로 설정
데이터 흐름:
1. CreateMinutes → minutes_sections 초기 생성
2. UpdateMinutes → content 저장 (여러 번)
3. FinalizeMinutes → locked=TRUE, verified=TRUE
4. (locked 상태에서 수정 불가)
1.4 agenda_sections (AI 요약 - V3)
구성:
id (PK, UUID)
├─ minutes_id (FK) ← 통합 회의록만 (user_id=NULL)
├─ meeting_id (FK)
├─ agenda_number (1, 2, 3...)
├─ agenda_title
├─ ai_summary_short (1줄 요약)
├─ discussions (3-5문장 논의)
├─ decisions (JSON 배열)
├─ pending_items (JSON 배열)
├─ opinions (JSON 배열: {speaker, opinion})
└─ todos (JSON 배열 [V4])
V4 추가 사항:
todosJSON 필드 추가- 안건별 추출된 Todo 저장
{
"title": "시장 조사 보고서 작성",
"assignee": "김민준",
"dueDate": "2025-02-15",
"description": "20-30대 타겟 시장 조사",
"priority": "HIGH"
}
중요:
- 통합 회의록만 분석 (user_id=NULL인 것)
- 참석자별 회의록(user_id NOT NULL)은 AI 분석 대상 아님
- minutes_id로 통합 회의록 참조
1.5 minutes_sections vs agenda_sections
| 항목 | minutes_sections | agenda_sections |
|---|---|---|
| 용도 | 사용자 작성 | AI 요약 |
| 모든 회의록 | ✓ 통합 + 개인 | ✗ 통합만 |
| 구조 | 순차적 섹션 | 안건별 구조화 |
| 내용 저장 | content (TEXT) | JSON 필드들 |
| 관계 | 1:N (minutes과) | N:1 (minutes과) |
| 목적 | 기록 | 분석/요약 |
생성 흐름:
회의 시작
↓
minutes 생성 (통합 + 개인)
↓
minutes_sections 생성 (4개 그룹)
↓
사용자 작성 중...
↓
회의 종료 → FinalizeMinutes
↓
minutes_sections locked
↓
AI 분석 (비동기)
↓
agenda_sections 생성 (통합 회의록 기반)
1.6 ai_summaries (AI 처리 결과 - V3)
구성:
id (PK, UUID)
├─ meeting_id (FK)
├─ summary_type (CONSOLIDATED, TODO_EXTRACTION)
├─ source_minutes_ids (JSON: 사용된 회의록 ID 배열)
├─ result (JSON: AI 응답 전체)
├─ processing_time_ms (처리 시간)
├─ model_version (claude-3.5-sonnet)
├─ keywords (JSON: 키워드 배열)
└─ statistics (JSON: {participants, agendas, todos})
용도:
- AI 처리 결과 캐싱
- 재처리 필요시 참조
- 성능 통계 기록
1.7 todos (Todo 아이템)
기본 구조:
todo_id (PK)
├─ meeting_id (FK)
├─ minutes_id (FK)
├─ title
├─ description
├─ assignee_id
├─ due_date
├─ status (PENDING, COMPLETED)
├─ priority (HIGH, MEDIUM, LOW)
└─ completed_at
V3 추가 필드:
├─ extracted_by (AI / MANUAL) ← AI 자동 추출 vs 수동
├─ section_reference (안건 참조)
└─ extraction_confidence (0.00~1.00) ← AI 신뢰도
저장 전략:
agenda_sections.todos(JSON): 간단한 Todo, 기본 저장 위치todos테이블: 상세 관리 필요시만 추가 저장
1.8 meeting_participants (참석자 관리 - V2)
구성:
PK: (meeting_id, user_id)
├─ invitation_status (PENDING, ACCEPTED, DECLINED)
├─ attended (BOOLEAN)
└─ created_at, updated_at
V2 개선:
- 이전: meetings.participants (CSV 문자열)
- 현재: 별도 테이블 (정규화)
- 복합 PK로 중복 방지
2. 회의록 작성 플로우 (전체)
단계별 데이터 변화
PHASE 1: 회의 준비
═════════════════════════════════════════════
1. CreateMeeting
→ INSERT meetings (status='SCHEDULED')
→ INSERT meeting_participants (5명)
PHASE 2: 회의 진행
═════════════════════════════════════════════
2. StartMeeting
→ UPDATE meetings SET status='IN_PROGRESS'
3. CreateMinutes (회의 중)
→ INSERT minutes (user_id=NULL) × 1 (통합)
→ INSERT minutes (user_id=user_id) × 5 (개인)
→ INSERT minutes_sections (초기 생성)
4. UpdateMinutes (여러 번)
→ UPDATE minutes_sections SET content='...'
PHASE 3: 회의 종료
═════════════════════════════════════════════
5. EndMeeting
→ UPDATE meetings SET
status='COMPLETED',
ended_at=NOW() [V3]
PHASE 4: 회의록 최종화
═════════════════════════════════════════════
6. FinalizeMinutes
→ UPDATE minutes SET
status='FINALIZED'
→ UPDATE minutes_sections SET
locked=TRUE,
verified=TRUE
PHASE 5: AI 분석 (비동기)
═════════════════════════════════════════════
7. MinutesAnalysisEventConsumer
→ Read minutes (user_id=NULL)
→ Read minutes_sections
→ Call AI Service
→ INSERT agenda_sections [V3]
→ INSERT ai_summaries [V3]
→ INSERT todos [V3 확장]
3. 사용자별 회의록 구조
데이터 분리 방식
1개 회의 (참석자 5명):
meetings: 1개
├─ meeting_id = 'meeting-001'
└─ status = COMPLETED
meeting_participants: 5개
├─ (meeting-001, user1@example.com)
├─ (meeting-001, user2@example.com)
├─ (meeting-001, user3@example.com)
├─ (meeting-001, user4@example.com)
└─ (meeting-001, user5@example.com)
minutes: 6개 [V3]
├─ (id=consol-1, meeting_id=meeting-001, user_id=NULL)
│ → 통합 회의록 (AI 분석 대상)
├─ (id=user1-min, meeting_id=meeting-001, user_id=user1@example.com)
│ → 사용자1 개인 회의록
├─ (id=user2-min, meeting_id=meeting-001, user_id=user2@example.com)
│ → 사용자2 개인 회의록
├─ ... (user3, user4, user5)
└─
minutes_sections: 수십 개 (6개 회의록 × N개 섹션)
├─ Group 1: consol-1의 섹션들 (AI 작성)
├─ Group 2: user1-min의 섹션들 (사용자1 작성)
├─ Group 3: user2-min의 섹션들 (사용자2 작성)
└─ ... (user3, user4, user5)
agenda_sections: 5개 [V3]
├─ (id=ag-1, minutes_id=consol-1, agenda_number=1)
├─ (id=ag-2, minutes_id=consol-1, agenda_number=2)
└─ ... (3, 4, 5)
핵심:
- 참석자별 회의록은 minutes.user_id로 구분
- 인덱스 활용:
idx_minutes_meeting_user - AI 분석: 통합 회의록만 (user_id=NULL)
4. 마이그레이션 변경사항 요약
V2 (2025-10-27)
-- meeting_participants 테이블 생성
CREATE TABLE meeting_participants (
meeting_id, user_id (복합 PK),
invitation_status, attended
)
-- 데이터 마이그레이션
SELECT TRIM(participant) FROM meetings.participants (CSV)
→ INSERT INTO meeting_participants
-- meetings.participants 컬럼 삭제
ALTER TABLE meetings DROP COLUMN participants
영향: 정규화 완료, 중복 데이터 제거
V3 (2025-10-28)
3-1. minutes 테이블 확장
ALTER TABLE minutes ADD COLUMN user_id VARCHAR(100);
CREATE INDEX idx_minutes_meeting_user ON minutes(meeting_id, user_id);
의미: 사용자별 회의록 지원
3-2. agenda_sections 테이블 신규
CREATE TABLE agenda_sections (
id, minutes_id, meeting_id,
agenda_number, agenda_title,
ai_summary_short, discussions,
decisions (JSON),
pending_items (JSON),
opinions (JSON)
)
의미: AI 요약을 구조화된 형식으로 저장
3-3. ai_summaries 테이블 신규
CREATE TABLE ai_summaries (
id, meeting_id, summary_type,
source_minutes_ids (JSON),
result (JSON),
processing_time_ms,
model_version,
keywords (JSON),
statistics (JSON)
)
의미: AI 처리 결과 캐싱
3-4. todos 테이블 확장
ALTER TABLE todos ADD COLUMN extracted_by VARCHAR(50) DEFAULT 'AI';
ALTER TABLE todos ADD COLUMN section_reference VARCHAR(200);
ALTER TABLE todos ADD COLUMN extraction_confidence DECIMAL(3,2);
의미: AI 자동 추출 추적
V4 (2025-10-28)
ALTER TABLE agenda_sections ADD COLUMN todos JSON;
의미: 안건별 Todo를 JSON으로 저장
5. 성능 최적화
현재 인덱스
meetings:
├─ PK: meeting_id
minutes:
├─ PK: id
└─ idx_minutes_meeting_user (meeting_id, user_id) [V3]
minutes_sections:
├─ PK: id
└─ (minutes_id로 FK 지원)
agenda_sections: [V3]
├─ PK: id
├─ idx_sections_meeting (meeting_id)
├─ idx_sections_agenda (meeting_id, agenda_number)
└─ idx_sections_minutes (minutes_id)
ai_summaries: [V3]
├─ PK: id
├─ idx_summaries_meeting (meeting_id)
├─ idx_summaries_type (meeting_id, summary_type)
└─ idx_summaries_created (created_at)
todos:
├─ PK: todo_id
├─ idx_todos_extracted (extracted_by) [V3]
└─ idx_todos_meeting (meeting_id) [V3]
meeting_participants: [V2]
├─ PK: (meeting_id, user_id)
├─ idx_user_id (user_id)
└─ idx_invitation_status (invitation_status)
추천 추가 인덱스
-- 자주 조회하는 패턴
CREATE INDEX idx_minutes_status_created
ON minutes(status, created_at DESC);
CREATE INDEX idx_agenda_meeting_created
ON agenda_sections(meeting_id, created_at DESC);
CREATE INDEX idx_todos_meeting_assignee
ON todos(meeting_id, assignee_id);
6. 핵심 질문 답변
Q1: minutes 테이블에 content 필드가 있는가?
A: 없음
- minutes: 메타데이터만 (title, status, version 등)
- 실제 내용: minutes_sections.content
Q2: minutes_section과 agenda_sections의 차이점?
A:
| 항목 | minutes_sections | agenda_sections |
|---|---|---|
| 목적 | 사용자 작성 | AI 요약 |
| 모든 회의록 | O | X (통합만) |
| 내용 저장 | content (TEXT) | JSON |
Q3: 사용자별 회의록 저장 방식?
A:
- minutes.user_id로 구분
- NULL: AI 통합회의록
- NOT NULL: 개인별 회의록
- 인덱스: idx_minutes_meeting_user
Q4: V3, V4 주요 변경?
A:
- V3: user_id, agenda_sections, ai_summaries, todos 확장
- V4: agenda_sections.todos JSON 추가
7. 개발 시 주의사항
Do's ✓
- minutes_sections.content에 실제 내용 저장
- AI 분석시 user_id=NULL인 minutes만 처리
- agenda_sections.todos와 todos 테이블 동시 저장 (필요시)
- 복합 인덱스 활용 (meeting_id, user_id)
Don'ts ✗
- minutes 테이블에 content 저장 (없음)
- 참석자별 회의록(user_id NOT NULL)을 AI 분석 (통합만)
- agenda_sections를 모든 minutes에 생성 (통합만)
- 인덱스 무시한 풀 스캔
8. 파일 위치 및 참조
마이그레이션 파일:
/Users/jominseo/HGZero/meeting/src/main/resources/db/migration/V2__*.sql/Users/jominseo/HGZero/meeting/src/main/resources/db/migration/V3__*.sql/Users/jominseo/HGZero/meeting/src/main/resources/db/migration/V4__*.sql
엔티티:
MeetingEntity,MinutesEntity,MinutesSectionEntityAgendaSectionEntity,TodoEntity,MeetingParticipantEntity
서비스:
MinutesService,MinutesSectionServiceMinutesAnalysisEventConsumer(비동기)
9. 결론
핵심 설계 원칙
- 메타데이터 vs 내용 분리: minutes (메타) vs minutes_sections (내용)
- 사용자별 격리: user_id 컬럼으로 개인 회의록 관리
- AI 결과 구조화: JSON으로 유연성과 성능 확보
- 정규화 완료: 참석자 정보 테이블화
검증 사항
- V3, V4 마이그레이션 정상 적용
- 모든 인덱스 생성됨
- 관계 설정 정상 (FK, 1:N)
다음 단계
- 성능 모니터링 (쿼리 실행 계획)
- 추가 인덱스 검토
- AI 분석 결과 검증
- 참석자별 회의록 사용성 테스트
문서 정보:
- 작성자: Database Architecture Analysis
- 대상 서비스: Meeting Service (AI 통합 회의록)
- 최종 버전: 2025-10-28