mirror of
https://github.com/hwanny1128/HGZero.git
synced 2025-12-06 07:56:24 +00:00
전체 5개 마이크로서비스의 내부 처리 흐름을 상세히 설계 [추가된 파일] - Meeting Service: 6개 시나리오 (검증완료, 실시간수정동기화, 최종회의록확정, 충돌해결, 템플릿선택, 회의록목록조회) - STT Service: 2개 시나리오 (음성녹음인식, 텍스트변환) - User Service: 2개 시나리오 (사용자인증, 대시보드조회) - Notification Service: 1개 시나리오 (알림발송) [주요 설계 내용] - Clean Architecture 적용 (Controller → Service → Domain → Repository) - Cache-Aside 패턴 (Redis 기반 성능 최적화) - Event-Driven Architecture (Azure Event Hub) - Real-time Collaboration (WebSocket + OT 알고리즘) - RAG 기능 (맥락 기반 AI) [검증 결과] - PlantUML 문법 검증: 모든 파일 통과 ✅ - 유저스토리 매칭: 100% 일치 ✅ - 아키텍처 패턴 준수: 완료 ✅ [병렬 처리] - 서브 에이전트 3개로 병렬 작업 수행 - Meeting Service, AI Service, STT/User/Notification 동시 설계 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
169 lines
4.7 KiB
Plaintext
169 lines
4.7 KiB
Plaintext
@startuml
|
|
!theme mono
|
|
|
|
title 알림 발송 내부 시퀀스 (Event-Driven)
|
|
|
|
queue "Event Hub<<E>>" as EventHub
|
|
participant "NotificationListener" as Listener
|
|
participant "NotificationService" as Service
|
|
participant "NotificationRouter" as Router
|
|
participant "EmailNotifier" as EmailNotifier
|
|
participant "Email Service<<E>>" as Email
|
|
participant "NotificationRepository" as Repository
|
|
database "PostgreSQL<<E>>" as DB
|
|
|
|
EventHub -> Listener: consume(NotificationEvent)
|
|
activate Listener
|
|
note right
|
|
Event 종류:
|
|
- MeetingCreatedEvent
|
|
- TodoAssignedEvent
|
|
- MeetingReminderEvent
|
|
- SummaryCompletedEvent
|
|
end note
|
|
|
|
Listener -> Service: processNotification(event)
|
|
activate Service
|
|
|
|
Service -> Repository: checkDuplicateNotification(eventId)
|
|
activate Repository
|
|
Repository -> DB: SELECT * FROM notifications\nWHERE event_id = ?
|
|
note right
|
|
중복 발송 방지:
|
|
- Event ID 기반
|
|
- Idempotency 보장
|
|
end note
|
|
|
|
alt 중복 이벤트
|
|
DB --> Repository: notification exists
|
|
Repository --> Service: duplicate
|
|
Service --> Listener: skip (already processed)
|
|
deactivate Service
|
|
Listener --> EventHub: ACK
|
|
deactivate Listener
|
|
|
|
else 신규 이벤트
|
|
DB --> Repository: not found
|
|
Repository --> Service: proceed
|
|
deactivate Repository
|
|
|
|
Service -> Service: parseEventPayload(event)
|
|
note right
|
|
이벤트 파싱:
|
|
- userId
|
|
- notificationType
|
|
- templateId
|
|
- templateData
|
|
end note
|
|
|
|
Service -> Repository: getUserPreferences(userId)
|
|
activate Repository
|
|
Repository -> DB: SELECT * FROM user_notification_prefs\nWHERE user_id = ?
|
|
note right
|
|
사용자 설정 확인:
|
|
- 알림 채널 (email/sms)
|
|
- 알림 활성화 여부
|
|
- 수신 시간대
|
|
end note
|
|
DB --> Repository: preferences
|
|
Repository --> Service: NotificationPreference
|
|
deactivate Repository
|
|
|
|
alt 알림 비활성화
|
|
Service --> Listener: skip (user preference)
|
|
deactivate Service
|
|
Listener --> EventHub: ACK
|
|
deactivate Listener
|
|
|
|
else 알림 활성화
|
|
Service -> Router: routeNotification(event, preferences)
|
|
activate Router
|
|
|
|
Router -> Router: determineChannel(preferences)
|
|
note right
|
|
채널 선택:
|
|
- 이메일 우선
|
|
- SMS 백업
|
|
end note
|
|
|
|
alt 이메일 알림
|
|
Router -> EmailNotifier: sendEmail(notification)
|
|
activate EmailNotifier
|
|
|
|
EmailNotifier -> EmailNotifier: loadTemplate(templateId)
|
|
note right
|
|
템플릿 로드:
|
|
- 회의 초대
|
|
- 할일 배정
|
|
- 회의 알림
|
|
- 요약 완료
|
|
end note
|
|
|
|
EmailNotifier -> EmailNotifier: renderTemplate(templateData)
|
|
note right
|
|
템플릿 렌더링:
|
|
- 제목 생성
|
|
- 본문 생성
|
|
- 다이나믹 데이터 삽입
|
|
end note
|
|
|
|
EmailNotifier -> Email: send(to, subject, body)
|
|
note right
|
|
이메일 발송:
|
|
- SMTP 프로토콜
|
|
- 재시도 로직
|
|
- Timeout: 10s
|
|
end note
|
|
|
|
alt 발송 성공
|
|
Email --> EmailNotifier: success
|
|
EmailNotifier --> Router: sent
|
|
deactivate EmailNotifier
|
|
|
|
else 발송 실패
|
|
Email --> EmailNotifier: failure
|
|
EmailNotifier -> EmailNotifier: scheduleRetry()
|
|
note right
|
|
재시도 전략:
|
|
- Max retry: 3
|
|
- Backoff: exponential
|
|
- 1m, 5m, 15m
|
|
end note
|
|
EmailNotifier --> Router: retry scheduled
|
|
deactivate EmailNotifier
|
|
end
|
|
end
|
|
|
|
Router --> Service: notification result
|
|
deactivate Router
|
|
|
|
Service -> Repository: saveNotificationLog(notification)
|
|
activate Repository
|
|
Repository -> DB: INSERT INTO notifications\n(event_id, user_id, type, channel, status, sent_at)
|
|
note right
|
|
알림 로그 저장:
|
|
- 발송 이력
|
|
- 채널 정보
|
|
- 성공/실패 상태
|
|
end note
|
|
DB --> Repository: saved
|
|
Repository --> Service: saved
|
|
deactivate Repository
|
|
|
|
Service -> Repository: updateUserActivity(userId, "NOTIFICATION_SENT")
|
|
activate Repository
|
|
Repository -> DB: INSERT INTO user_activities\n(user_id, activity_type, details)
|
|
DB --> Repository: saved
|
|
Repository --> Service: updated
|
|
deactivate Repository
|
|
|
|
Service --> Listener: processed
|
|
deactivate Service
|
|
|
|
Listener --> EventHub: ACK
|
|
deactivate Listener
|
|
end
|
|
end
|
|
|
|
@enduml
|