@startuml meeting-회의록공유 !theme mono title Meeting Service - 회의록공유 내부 시퀀스 participant "ShareController" as Controller participant "ShareService" as Service participant "MinutesRepository" as MinutesRepo participant "ShareRepository" as ShareRepo participant "CalendarService" as CalendarService database "Meeting DB<>" as DB database "Redis Cache<>" as Cache queue "Azure Event Hubs<>" as EventHub [-> Controller: POST /minutes/{minutesId}/share activate Controller note over Controller 경로 변수: minutesId 요청 데이터: { "sharedWith": ["user1@example.com", "user2@example.com"], "permission": "READ_ONLY" | "COMMENT" | "EDIT", "shareMethod": "EMAIL" | "LINK", "linkOptions": { "expiresIn": 7, // days "requirePassword": true, "password": "..." } } 사용자 정보: userId, userName, email end note Controller -> Controller: 입력 검증\n- sharedWith 최소 1명\n- permission 유효성 Controller -> Service: shareMinutes(minutesId, request, userId) activate Service ' 회의록 정보 조회 Service -> MinutesRepo: findById(minutesId) activate MinutesRepo MinutesRepo -> DB: 회의록 정보 조회 activate DB DB --> MinutesRepo: 회의록 정보 deactivate DB MinutesRepo --> Service: Minutes deactivate MinutesRepo note over Service 비즈니스 규칙 검증: - 회의록 존재 확인 - 공유 권한 확인 (생성자만) - 회의록 상태 확인 (FINALIZED만 공유 가능) end note Service -> Service: 회의록 존재 확인 Service -> Service: 공유 권한 검증\n(생성자만 가능) Service -> Service: 회의록 상태 확인 alt 회의록이 확정되지 않음 Service --> Controller: 400 Bad Request\n확정된 회의록만 공유 가능 note right 에러 응답 형식: { "error": { "code": "MINUTES_NOT_FINALIZED", "message": "확정된 회의록만 공유 가능합니다", "details": "회의록을 먼저 확정해 주세요", "timestamp": "2025-10-23T12:00:00Z", "path": "/api/minutes/{minutesId}/share" } } end note return 400 Bad Request else 공유 가능 ' 공유 링크 생성 Service -> Service: 고유 공유 링크 생성\n(UUID 기반 토큰) Service -> ShareRepo: createShareLink(minutesId, token, options) activate ShareRepo ShareRepo -> DB: 공유 링크 정보 저장 activate DB DB --> ShareRepo: 링크 생성 완료 deactivate DB ShareRepo --> Service: ShareLink deactivate ShareRepo ' 공유 대상 저장 loop 각 공유 대상마다 Service -> ShareRepo: addSharedUser(minutesId, userEmail, permission) activate ShareRepo ShareRepo -> DB: 공유 대상 정보 저장 activate DB DB --> ShareRepo: 공유 정보 저장 완료 deactivate DB ShareRepo --> Service: 저장 성공 deactivate ShareRepo end ' 회의록에서 다음 회의 일정 언급 확인 Service -> Service: 다음 회의 일정 추출\n(회의록 내용 분석) alt 다음 회의 일정 언급됨 Service -> CalendarService: createCalendarEvent(meetingInfo) activate CalendarService note over CalendarService 캘린더 이벤트 생성: - 제목: 다음 회의 제목 - 일시: 추출된 일시 - 참석자: 공유 대상자 end note CalendarService -> CalendarService: 캘린더 이벤트 생성 CalendarService --> Service: 이벤트 ID deactivate CalendarService end ' 캐시 무효화 Service -> Cache: DELETE minutes:detail:{minutesId} activate Cache Cache --> Service: 삭제 완료 deactivate Cache note over Service 비동기 이벤트 발행: - 공유 대상자에게 이메일 발송 - 캘린더 초대 발송 (일정 있는 경우) end note ' NotificationRequest 이벤트 발행 Service -> EventHub: publish(NotificationRequest)\n{\n channel: EMAIL,\n recipients: sharedWith,\n message: "회의록 공유 안내",\n metadata: {\n minutesId, shareLink,\n permission, sharedBy,\n nextMeetingEvent\n }\n} activate EventHub note right Notification Service가 구독: - Consumer Group: notification-service-group - 공유 대상자에게 이메일 발송 end note EventHub --> Service: 발행 완료 deactivate EventHub Service --> Controller: ShareResponse deactivate Service note over Controller 응답 데이터: { "minutesId": "uuid", "shareLink": "https://.../share/{token}", "sharedWith": [...], "permission": "READ_ONLY", "expiresAt": "2025-01-30T00:00:00", "sharedAt": "2025-01-23T16:30:00", "nextMeetingEvent": { "eventId": "...", "title": "...", "startTime": "..." } } end note return 200 OK\nShareResponse end deactivate Controller @enduml