hgzero/design/backend/sequence/inner/notification-알림발송.puml

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