Commit 36dfa92
authored
[FEAT] FCM 푸시 알림 및 이메일 알림 기본 설계 구현 (#340)
<!--
## PR 제목 컨벤션
[TYPE] 설명 (#이슈번호)
예시:
- [FEAT] 회원가입 API 구현 (#14)
- [FIX] 이미지 업로드 시 NPE 수정 (#23)
- [REFACTOR] 토큰 로직 분리 (#8)
- [DOCS] ERD 스키마 업데이트 (#6)
- [CHORE] CI/CD 파이프라인 추가 (#3)
- [RELEASE] v1.0.0 배포 (#30)
TYPE: FEAT, FIX, DOCS, REFACTOR, TEST, CHORE, RENAME, REMOVE, RELEASE
-->
## Summary
<!-- 변경 사항을 간단히 설명해주세요 -->
비즈니스 이벤트 기반 알림 시스템을 구현했습니다. 제안 수신, 캠페인 매칭 등 이벤트 발생 시 웹 푸시(FCM) 및 이메일 알림을
발송하고, 알림 페이지 API를 제공합니다. Outbox 패턴을 사용하여 비즈니스 트랜잭션과 완전히 분리되었으며, 재시도 정책과
장애 격리 메커니즘이 포함되어 있습니다.
## Changes
<!-- 변경된 내용을 목록으로 작성해주세요 -->
### 도메인 레이어
- **Notification 엔티티**: 알림 원장 (읽음 처리, 소프트 삭제 지원)
- **NotificationDelivery 엔티티**: 채널별 발송 추적
(PENDING/IN_PROGRESS/SENT/FAILED 상태, 재시도 관리)
- **FcmToken 엔티티**: FCM 디바이스 토큰 저장소 (다중 기기 지원, 토큰 재할당)
- **NotificationKind enum**: 알림 종류 정의 (PROPOSAL_RECEIVED,
CAMPAIGN_MATCHED 등)
- **DeliveryStatus enum**: 발송 상태 정의 (PENDING, IN_PROGRESS, SENT, FAILED)
### 애플리케이션 레이어
- **NotificationService**: 알림 생성 및 읽음 처리
- **NotificationQueryService**: 알림 목록 조회 (필터링, 날짜별 그룹핑, 페이징)
- **NotificationDeliveryProcessor**: 개별 발송 처리 (장애 격리, REQUIRES_NEW 트랜잭션)
- **FcmTokenService**: FCM 토큰 등록/삭제 관리
- **NotificationChannelResolver**: 알림 종류별 채널 결정 (PUSH/EMAIL)
- **NotificationMessageTemplateService**: 알림 메시지 템플릿 생성
### 인프라스트럭처 레이어
- **NotificationEventListener**: 비즈니스 이벤트 구독 및 알림 생성
(`@TransactionalEventListener(AFTER_COMMIT)`)
- **NotificationDeliveryWorker**: 비동기 발송 워커 (`@Scheduled`, 30초마다 실행)
- **FcmNotificationSender**: FCM 웹 푸시 발송 (Firebase Admin SDK)
- **EmailNotificationSender**: 이메일 발송 (Spring Mail, HTML 템플릿)
- **FirebaseConfig**: Firebase Admin SDK 초기화 (선택적, 파일 없어도 동작)
### 프레젠테이션 레이어
- **NotificationController**: 알림 목록 조회, 읽음 처리 API
- **FcmTokenController**: FCM 토큰 등록/삭제 API
- **NotificationSwagger**: API 문서화 인터페이스
- **FcmTokenSwagger**: FCM 토큰 API 문서화 인터페이스
### 이벤트 정의 (데모데이 이후용)
- **CampaignCompletedEvent**: 캠페인 완료 이벤트 (리스너만 정의, 발행은 추후)
- **SettlementReadyEvent**: 정산 준비 이벤트 (리스너만 정의, 발행은 추후)
- **AutoConfirmedEvent**: 자동 확정 이벤트 (리스너만 정의, 발행은 추후)
### 설정 파일
- **application.yml**: 로컬 개발용 기본값 설정 (FCM, SMTP)
- **application-dev.yml**: dev 환경 설정 (환경변수 참조)
- **application-prod.yml**: prod 환경 설정 (환경변수 참조)
- **.gitignore**: Firebase 키 파일 제외 설정
## Type of Change
<!-- 해당하는 항목에 x 표시해주세요 -->
- [ ] Bug fix (기존 기능에 영향을 주지 않는 버그 수정)
- [x] New feature (기존 기능에 영향을 주지 않는 새로운 기능 추가)
- [ ] Breaking change (기존 기능에 영향을 주는 수정)
- [ ] Refactoring (기능 변경 없는 코드 개선)
- [ ] Documentation (문서 수정)
- [ ] Chore (빌드, 설정 등 기타 변경)
- [ ] Release (develop → main 배포)
## Related Issues
<!-- 관련 이슈 번호를 작성해주세요 (예: Closes #123, Fixes #456) -->
Closes #218
Closes #219
## 참고 사항
<!-- 리뷰어가 알아야 할 추가 정보가 있다면 작성해주세요 -->1 parent c5a1abb commit 36dfa92
File tree
27 files changed
+1092
-11
lines changed- .github/workflows
- src/main
- java/com/example/RealMatch
- business/application/event
- notification
- application
- event
- service
- domain
- entity
- repository
- exception
- infrastructure
- config
- sender
- worker
- presentation
- controller
- dto/request
- swagger
- resources
27 files changed
+1092
-11
lines changed| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
93 | 93 | | |
94 | 94 | | |
95 | 95 | | |
| 96 | + | |
96 | 97 | | |
97 | 98 | | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
98 | 108 | | |
99 | 109 | | |
100 | 110 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
8 | 8 | | |
9 | 9 | | |
10 | 10 | | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
11 | 16 | | |
12 | 17 | | |
13 | 18 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
83 | 83 | | |
84 | 84 | | |
85 | 85 | | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
86 | 92 | | |
87 | 93 | | |
88 | 94 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
58 | 58 | | |
59 | 59 | | |
60 | 60 | | |
| 61 | + | |
| 62 | + | |
61 | 63 | | |
62 | 64 | | |
63 | 65 | | |
| |||
Lines changed: 12 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
Lines changed: 12 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
Lines changed: 13 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
Lines changed: 126 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
8 | 8 | | |
9 | 9 | | |
10 | 10 | | |
| 11 | + | |
11 | 12 | | |
| 13 | + | |
12 | 14 | | |
13 | 15 | | |
| 16 | + | |
14 | 17 | | |
15 | 18 | | |
16 | 19 | | |
| |||
222 | 225 | | |
223 | 226 | | |
224 | 227 | | |
| 228 | + | |
| 229 | + | |
| 230 | + | |
| 231 | + | |
| 232 | + | |
| 233 | + | |
| 234 | + | |
| 235 | + | |
| 236 | + | |
| 237 | + | |
| 238 | + | |
| 239 | + | |
| 240 | + | |
| 241 | + | |
| 242 | + | |
| 243 | + | |
| 244 | + | |
| 245 | + | |
| 246 | + | |
| 247 | + | |
| 248 | + | |
| 249 | + | |
| 250 | + | |
| 251 | + | |
| 252 | + | |
| 253 | + | |
| 254 | + | |
| 255 | + | |
| 256 | + | |
| 257 | + | |
| 258 | + | |
| 259 | + | |
| 260 | + | |
| 261 | + | |
| 262 | + | |
| 263 | + | |
| 264 | + | |
| 265 | + | |
| 266 | + | |
| 267 | + | |
| 268 | + | |
| 269 | + | |
| 270 | + | |
| 271 | + | |
| 272 | + | |
| 273 | + | |
| 274 | + | |
| 275 | + | |
| 276 | + | |
| 277 | + | |
| 278 | + | |
| 279 | + | |
| 280 | + | |
| 281 | + | |
| 282 | + | |
| 283 | + | |
| 284 | + | |
| 285 | + | |
| 286 | + | |
| 287 | + | |
| 288 | + | |
| 289 | + | |
| 290 | + | |
| 291 | + | |
| 292 | + | |
| 293 | + | |
| 294 | + | |
| 295 | + | |
| 296 | + | |
| 297 | + | |
| 298 | + | |
| 299 | + | |
| 300 | + | |
| 301 | + | |
| 302 | + | |
| 303 | + | |
| 304 | + | |
| 305 | + | |
| 306 | + | |
| 307 | + | |
| 308 | + | |
| 309 | + | |
| 310 | + | |
| 311 | + | |
| 312 | + | |
| 313 | + | |
| 314 | + | |
| 315 | + | |
| 316 | + | |
| 317 | + | |
| 318 | + | |
| 319 | + | |
| 320 | + | |
| 321 | + | |
| 322 | + | |
| 323 | + | |
| 324 | + | |
| 325 | + | |
| 326 | + | |
| 327 | + | |
| 328 | + | |
| 329 | + | |
| 330 | + | |
| 331 | + | |
| 332 | + | |
| 333 | + | |
| 334 | + | |
| 335 | + | |
| 336 | + | |
| 337 | + | |
| 338 | + | |
| 339 | + | |
| 340 | + | |
| 341 | + | |
| 342 | + | |
| 343 | + | |
| 344 | + | |
| 345 | + | |
| 346 | + | |
| 347 | + | |
| 348 | + | |
| 349 | + | |
| 350 | + | |
225 | 351 | | |
226 | 352 | | |
227 | 353 | | |
| |||
Lines changed: 64 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
0 commit comments