@startuml meeting-회의예약 !theme mono title Meeting Service - 회의예약 내부 시퀀스 participant "MeetingController" as Controller participant "MeetingService" as Service participant "MeetingRepository" as Repo participant "ParticipantRepository" as ParticipantRepo database "Meeting DB<>" as DB database "Redis Cache<>" as Cache queue "Azure Event Hubs<>" as EventHub [-> Controller: POST /meetings activate Controller note over Controller 요청 데이터: { "title": "회의 제목", "startTime": "2025-01-23T14:00:00", "endTime": "2025-01-23T15:00:00", "location": "회의실 A", "participants": ["user1@example.com", ...] } 사용자 정보: userId, userName, email end note Controller -> Controller: 입력 검증\n- 제목 필수 (최대 100자)\n- 날짜/시간 필수\n- 참석자 최소 1명 Controller -> Service: createMeeting(request, userId) activate Service note over Service 비즈니스 규칙 검증: - 회의 시간 유효성 (시작 < 종료) - 중복 회의 체크 - 참석자 유효성 검증 end note Service -> Service: 회의 시간 유효성 검사 Service -> Repo: checkConflictingMeetings(userId, startTime, endTime) activate Repo Repo -> DB: 중복 회의 확인 activate DB DB --> Repo: 중복 회의 개수 deactivate DB Repo --> Service: int count deactivate Repo alt 중복 회의 존재 Service --> Controller: 409 Conflict\n중복된 회의 시간 note right 에러 응답 형식: { "error": { "code": "MEETING_TIME_CONFLICT", "message": "중복된 회의 시간이 존재합니다", "details": "해당 시간대에 이미 예약된 회의가 있습니다", "timestamp": "2025-10-23T12:00:00Z", "path": "/api/meetings" } } end note return 409 Conflict else 중복 없음 Service -> Service: Meeting 엔티티 생성\n- 회의 ID 생성\n- 상태: SCHEDULED\n- 생성자 정보 설정 ' 회의 정보 저장 Service -> Repo: save(meeting) activate Repo Repo -> DB: 회의 정보 저장 activate DB DB --> Repo: 회의 저장 완료 deactivate DB Repo --> Service: Meeting deactivate Repo ' 참석자 저장 Service -> ParticipantRepo: saveAll(participants) activate ParticipantRepo ParticipantRepo -> DB: 참석자 정보 저장 activate DB DB --> ParticipantRepo: 참석자 저장 완료 deactivate DB ParticipantRepo --> Service: List deactivate ParticipantRepo ' 캐시 저장 Service -> Cache: SET meeting:info:{meetingId}\n(TTL: 10분) activate Cache Cache --> Service: 캐싱 완료 deactivate Cache Service -> Cache: SET meeting:participants:{meetingId}\n(TTL: 10분) activate Cache Cache --> Service: 캐싱 완료 deactivate Cache note over Service 비동기 이벤트 발행: - 초대 이메일 발송 - 캘린더 등록 - 리마인더 스케줄링 end note ' 이벤트 발행 Service -> EventHub: publish(MeetingCreated)\n{\n meetingId, title, startTime,\n participants, creatorInfo\n} activate EventHub EventHub --> Service: 발행 완료 deactivate EventHub Service --> Controller: MeetingResponse deactivate Service note over Controller 응답 데이터: { "meetingId": "uuid", "title": "회의 제목", "startTime": "...", "endTime": "...", "location": "...", "participants": [...], "status": "SCHEDULED" } end note return 201 Created\nMeetingResponse end deactivate Controller @enduml