hgzero/design/backend/sequence/inner/notification-알림발송.puml
yabo0812 d55fcfc1bd 내부 시퀀스 설계 완료 (25개 시나리오)
전체 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>
2025-10-22 18:21:15 +09:00

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