mirror of
https://github.com/hwanny1128/HGZero.git
synced 2025-12-06 20:46:23 +00:00
172 lines
4.8 KiB
Plaintext
172 lines
4.8 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(NotificationRequest)
|
|
activate Listener
|
|
note right
|
|
NotificationRequest 이벤트:
|
|
- channel: 발송수단 (EMAIL, SMS)
|
|
- recipients: 대상자 목록
|
|
- message: 메시지 내용
|
|
- metadata: 추가 정보 (회의정보 등)
|
|
|
|
Consumer Group:
|
|
- notification-service-group
|
|
end note
|
|
|
|
Listener -> Service: processNotification(event)
|
|
activate Service
|
|
|
|
Service -> Repository: checkDuplicateNotification(eventId)
|
|
activate Repository
|
|
Repository -> DB: 알림 중복 확인 조회\n(이벤트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: 사용자 알림 설정 조회\n(사용자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: 알림 이력 저장\n(이벤트ID, 사용자ID, 유형, 채널, 상태, 발송일시)
|
|
note right
|
|
알림 로그 저장:
|
|
- 발송 이력
|
|
- 채널 정보
|
|
- 성공/실패 상태
|
|
end note
|
|
DB --> Repository: saved
|
|
Repository --> Service: saved
|
|
deactivate Repository
|
|
|
|
Service -> Repository: updateUserActivity(userId, "NOTIFICATION_SENT")
|
|
activate Repository
|
|
Repository -> DB: 사용자 활동 이력 저장\n(사용자ID, 활동유형, 상세내용)
|
|
DB --> Repository: saved
|
|
Repository --> Service: updated
|
|
deactivate Repository
|
|
|
|
Service --> Listener: processed
|
|
deactivate Service
|
|
|
|
Listener --> EventHub: ACK
|
|
deactivate Listener
|
|
end
|
|
end
|
|
|
|
@enduml
|