<aside> 📌
알림 도메인은 사용자에게 전달되는 인앱 알림 이력과 Firebase Cloud Messaging(FCM)을 통한 외부 푸시 메시지를 통합적으로 관리하는 인프라입니다. 시스템 전체는 Ports and Adapters 아키텍처로 구성되어 있으며, 각 도메인이 NotificationService에 직접 의존하지 않고 도메인별 인터페이스를 통해 상호작용하도록 설계되어 있습니다. Chat, Post, Stream, Session, Performance, Band 등 여러 도메인 어댑터가 공통 NotifyPort 인터페이스를 구현합니다.
| 구성요소 | 역할 |
|---|---|
| NotificationService | 알림 영속화, 설정 검증, 푸시 발송을 총괄 조율합니다. |
| NotificationRepository | 읽지 않은 상태 및 커서 기반 페이지네이션을 위한 복잡한 쿼리를 처리합니다. |
| PushPort | 외부 푸시 제공자(FCM)에 대한 추상화 계층입니다. |
| Domain Adapters | 도메인 이벤트를 알림 요청으로 변환하는 브릿지 역할을 합니다. |
sequenceDiagram
participant Domain as "소스 도메인"
participant Port as "NotifyPort"
participant Adapter as "Domain Adapter"
participant Service as "NotificationService"
participant DB as "Database"
participant FCM as "PushPort / FCM"
Domain->>Port: "notify() 호출"
Port->>Adapter: "알림 도메인 형식으로 변환"
Adapter->>Service: "send(receiverId, PushMessage)"
Service->>Service: "NotificationSetting 확인"
Service->>DB: "Notification 엔티티 저장"
Service->>FCM: "PushToken 조회 후 발송"
Notification 엔티티는 개별 인앱 알림을 나타내며 수신자(receiver), 제목(title), 본문(body), 모바일 내비게이션을 위한 deepLink를 저장하고, isRead와 readAt을 통해 읽음 여부를 추적합니다.
| Adapter | Domain Port | 책임 |
|---|---|---|
| StreamAdapter | stream.port.NotifyPort | 라이브 시작, 공동 호스트 초대, 라이브 리마인더를 처리합니다. |
| SessionAdapter | session.port.NotifyPort | 지원 상태 변경 및 모집 마감일을 처리합니다. |
| PerformanceAdapter | performance.port.NotifyPort | 공연 업데이트 및 리마인더를 처리합니다. |
| ChatAdapter | chat.port.NotifyPort | 신규 메시지 알림을 처리합니다. |
| PostAdapter | post.port.NotifyPort | 게시물에 대한 좋아요와 댓글을 처리합니다. |
| BandAdapter | band.port.NotifyPort | 밴드 초대 및 멤버십 변경을 처리합니다. |
사용자는 현재 UserMode(FAN 또는 BAND)와 NotificationSettingType에 정의된 세부 카테고리에 따라 알림을 켜고 끌 수 있습니다. NotificationSettingMode가 설정을 FAN 또는 BAND 그룹으로 분류하고, NotificationSettingType이 FAN_FOLLOWED_BAND_LIVE_START, BAND_NEW_SESSION_APPLICATION과 같은 구체적인 트리거를 정의하며, NotificationService.isNotificationEnabled()가 발송 전에 이 설정들을 확인합니다.
NotificationRepository.findNotificationPage 쿼리는 사용자가 수천 건의 알림을 가지고 있어도 읽지 않은 알림이 항상 상단에, 그 다음에 읽은 알림이 ID 내림차순으로 표시되도록 보장합니다.
PushSendResult send(String targetToken, String title, String body, Map<String, String> data);
| Field | 목적 |
|---|---|
| NotificationType (type) | 푸시의 목적을 분류합니다(LIVE, SESSION, BAND 등). |
| NotificationSettingType (settingType) | 발송 전 사용자 설정을 검증합니다. |
| Title (title) | 푸시 알림의 굵은 헤더입니다. |
| Body (body) | 알림의 설명 텍스트입니다. |
| Deep Link (deepLink) | 클릭 시 이동할 프론트엔드 라우트입니다. |
| Reference ID (referenceId) | 연관된 엔티티의 ID입니다(Stream ID, Post ID 등). |
테스트는 딥링크 구성, 메시지 포맷팅, 트랜잭션 무결성을 검증합니다. UserServiceSessionApplyTest는 TxSyncSupport를 사용하여 데이터베이스 커밋이 성공한 이후에만 알림이 트리거되도록 보장합니다.