@startuml meeting-회의록상세조회 !theme mono title Meeting Service - 회의록상세조회 내부 시퀀스 participant "MinutesController" as Controller participant "MinutesService" as Service participant "MinutesRepository" as MinutesRepo participant "SectionRepository" as SectionRepo participant "RelatedMinutesService" as RelatedService database "Meeting DB<>" as DB database "Redis Cache<>" as Cache [-> Controller: GET /minutes/{minutesId} activate Controller note over Controller 경로 변수: minutesId 사용자 정보: userId, userName, email end note Controller -> Controller: minutesId 유효성 검증 Controller -> Service: getMinutesDetail(minutesId, userId) activate Service ' 캐시 조회 Service -> Cache: GET minutes:detail:{minutesId} activate Cache Cache --> Service: 캐시 조회 결과 deactivate Cache alt Cache Hit Service -> Service: 권한 확인\n(캐시 데이터에서) alt 권한 없음 Service --> Controller: 403 Forbidden\n조회 권한 없음 return 403 Forbidden else 권한 있음 Service --> Controller: MinutesDetailResponse\n(캐시 데이터) return 200 OK end else Cache Miss ' 회의록 기본 정보 조회 Service -> MinutesRepo: findByIdWithMeeting(minutesId) activate MinutesRepo MinutesRepo -> DB: SELECT m.*, mt.*\nFROM minutes m\nJOIN meetings mt ON m.meetingId = mt.id\nWHERE m.id = ? activate DB DB --> MinutesRepo: 회의록 및 회의 정보 deactivate DB MinutesRepo --> Service: Minutes + Meeting deactivate MinutesRepo note over Service 비즈니스 규칙 검증: - 회의록 존재 확인 - 조회 권한 확인 * 생성자 * 참석자 * 공유받은 사용자 end note Service -> Service: 회의록 존재 확인 ' 권한 확인 Service -> MinutesRepo: hasAccessPermission(minutesId, userId) activate MinutesRepo MinutesRepo -> DB: SELECT COUNT(*) FROM (\n SELECT 1 FROM minutes WHERE id = ? AND creatorId = ?\n UNION\n SELECT 1 FROM participants p JOIN meetings m\n ON p.meetingId = m.id JOIN minutes mi\n ON mi.meetingId = m.id\n WHERE mi.id = ? AND p.userId = ?\n UNION\n SELECT 1 FROM shared_minutes\n WHERE minutesId = ? AND sharedWith = ?\n) AS access activate DB DB --> MinutesRepo: 권한 확인 결과 deactivate DB MinutesRepo --> Service: boolean hasAccess deactivate MinutesRepo alt 권한 없음 Service --> Controller: 403 Forbidden\n조회 권한 없음 return 403 Forbidden else 권한 있음 ' 참석자 목록 조회 Service -> MinutesRepo: findParticipants(minutesId) activate MinutesRepo MinutesRepo -> DB: SELECT p.*, u.name, u.email\nFROM participants p\nJOIN meetings m ON p.meetingId = m.id\nJOIN minutes mi ON mi.meetingId = m.id\nJOIN users u ON p.userId = u.id\nWHERE mi.id = ? activate DB DB --> MinutesRepo: 참석자 목록 deactivate DB MinutesRepo --> Service: List deactivate MinutesRepo ' 섹션별 상세 내용 조회 Service -> SectionRepo: findSectionsByMinutesId(minutesId) activate SectionRepo SectionRepo -> DB: SELECT * FROM minutes_sections\nWHERE minutesId = ?\nORDER BY sectionOrder activate DB DB --> SectionRepo: 섹션 목록 deactivate DB SectionRepo --> Service: List
deactivate SectionRepo ' AI 요약 정보 조회 Service -> SectionRepo: findAISummaries(minutesId) activate SectionRepo SectionRepo -> DB: SELECT * FROM ai_summaries\nWHERE minutesId = ?\nORDER BY sectionId activate DB DB --> SectionRepo: AI 요약 목록 deactivate DB SectionRepo --> Service: List deactivate SectionRepo ' 관련 회의록 조회 Service -> RelatedService: findRelatedMinutes(minutesId, limit: 3) activate RelatedService note over RelatedService 관련 회의록 검색 로직: - 벡터 유사도 기반 검색 (AI 서비스 호출) - 관련도 70% 이상 - 최대 3개 end note RelatedService -> DB: SELECT * FROM related_minutes\nWHERE minutesId = ?\nAND similarityScore >= 0.7\nORDER BY similarityScore DESC\nLIMIT 3 activate DB DB --> RelatedService: 관련 회의록 목록 deactivate DB RelatedService --> Service: List deactivate RelatedService ' 조회 이력 기록 Service -> MinutesRepo: recordViewHistory(minutesId, userId) activate MinutesRepo MinutesRepo -> DB: INSERT INTO view_history\n(minutesId, userId, viewedAt)\nVALUES (?, ?, NOW()) activate DB DB --> MinutesRepo: 기록 완료 deactivate DB MinutesRepo --> Service: 기록 성공 deactivate MinutesRepo note over Service 데이터 조합: - 기본 정보 - 참석자 목록 - 섹션별 내용 - AI 요약 - 관련 회의록 - 권한 정보 (수정 가능 여부) end note Service -> Service: 상세 응답 DTO 구성 ' 캐시 저장 Service -> Cache: SET minutes:detail:{minutesId}\n(TTL: 10분) activate Cache Cache --> Service: 캐싱 완료 deactivate Cache Service --> Controller: MinutesDetailResponse deactivate Service note over Controller 응답 데이터: { "minutesId": "uuid", "meeting": {...}, "participants": [...], "sections": [...], "aiSummaries": [...], "relatedMinutes": [...], "permissions": { "canEdit": true/false, "canShare": true/false }, "status": "FINALIZED", "version": "v1.0" } end note return 200 OK\nMinutesDetailResponse end end deactivate Controller @enduml