mirror of
https://github.com/hwanny1128/HGZero.git
synced 2026-06-12 22:59:10 +00:00
add notification
This commit is contained in:
@@ -0,0 +1,623 @@
|
||||
# Notification Service - 백엔드 개발 결과서
|
||||
|
||||
## 1. 개요
|
||||
|
||||
### 1.1 서비스 설명
|
||||
- **서비스명**: Notification Service
|
||||
- **목적**: 회의 초대 및 Todo 할당 알림 발송 서비스
|
||||
- **아키텍처 패턴**: Layered Architecture
|
||||
- **주요 기능**:
|
||||
- Azure Event Hubs를 통한 이벤트 기반 알림 발송
|
||||
- 이메일 템플릿 기반 알림 생성
|
||||
- 사용자별 알림 설정 관리
|
||||
- 재시도 메커니즘 (Exponential Backoff)
|
||||
- 중복 발송 방지 (Idempotency)
|
||||
|
||||
### 1.2 개발 기간
|
||||
- **시작일**: 2025-10-23
|
||||
- **완료일**: 2025-10-23
|
||||
- **개발자**: 준호 (Backend Developer)
|
||||
|
||||
---
|
||||
|
||||
## 2. 기술 스택
|
||||
|
||||
### 2.1 프레임워크 및 라이브러리
|
||||
- **Spring Boot**: 3.3.0
|
||||
- **Java**: 21
|
||||
- **Spring Data JPA**: 3.3.0
|
||||
- **Spring Security**: 6.3.0
|
||||
- **Spring Mail**: 3.3.0
|
||||
- **Spring Retry**: 2.0.6
|
||||
- **Thymeleaf**: 3.1.2
|
||||
- **Azure Event Hubs**: 5.18.4
|
||||
- **Azure Storage Blob**: 12.26.1
|
||||
- **PostgreSQL Driver**: 42.7.3
|
||||
- **SpringDoc OpenAPI**: 2.5.0
|
||||
- **Lombok**: 1.18.32
|
||||
|
||||
### 2.2 데이터베이스
|
||||
- **DBMS**: PostgreSQL 16.4
|
||||
- **Host**: 4.230.159.143:5432
|
||||
- **Database**: notificationdb
|
||||
- **User**: hgzerouser
|
||||
|
||||
### 2.3 메시지 큐
|
||||
- **Azure Event Hubs**: 이벤트 기반 알림 처리
|
||||
- **Consumer Group**: notification-service
|
||||
- **Checkpoint Store**: Azure Blob Storage
|
||||
|
||||
### 2.4 이메일 발송
|
||||
- **SMTP**: Gmail SMTP 또는 사용자 정의 SMTP
|
||||
- **Port**: 587 (TLS)
|
||||
- **Template Engine**: Thymeleaf
|
||||
|
||||
---
|
||||
|
||||
## 3. 구현 내용
|
||||
|
||||
### 3.1 패키지 구조
|
||||
|
||||
```
|
||||
notification/
|
||||
└── src/main/java/com/unicorn/hgzero/notification/
|
||||
├── NotificationApplication.java # Spring Boot 메인 클래스
|
||||
│
|
||||
├── domain/ # Domain Layer
|
||||
│ ├── Notification.java # 알림 Entity
|
||||
│ ├── NotificationRecipient.java # 수신자 Entity
|
||||
│ └── NotificationSetting.java # 알림 설정 Entity
|
||||
│
|
||||
├── repository/ # Data Access Layer
|
||||
│ ├── NotificationRepository.java
|
||||
│ ├── NotificationRecipientRepository.java
|
||||
│ └── NotificationSettingRepository.java
|
||||
│
|
||||
├── service/ # Business Logic Layer
|
||||
│ ├── NotificationService.java # 알림 비즈니스 로직
|
||||
│ ├── EmailTemplateService.java # 템플릿 렌더링
|
||||
│ └── EmailClient.java # 이메일 발송
|
||||
│
|
||||
├── controller/ # Presentation Layer
|
||||
│ ├── NotificationController.java # 알림 조회 API
|
||||
│ └── NotificationSettingsController.java # 설정 API
|
||||
│
|
||||
├── event/ # Event Handler Layer
|
||||
│ ├── EventHandler.java # Event Hub 핸들러
|
||||
│ ├── event/
|
||||
│ │ ├── MeetingCreatedEvent.java # 회의 생성 이벤트 DTO
|
||||
│ │ └── TodoAssignedEvent.java # Todo 할당 이벤트 DTO
|
||||
│ └── processor/
|
||||
│ └── EventProcessorService.java # Processor 라이프사이클
|
||||
│
|
||||
├── dto/ # Data Transfer Objects
|
||||
│ ├── request/
|
||||
│ │ └── UpdateSettingsRequest.java
|
||||
│ └── response/
|
||||
│ ├── NotificationResponse.java
|
||||
│ ├── NotificationListResponse.java
|
||||
│ └── SettingsResponse.java
|
||||
│
|
||||
├── config/ # Configuration Layer
|
||||
│ ├── EventHubConfig.java # Event Hub 설정
|
||||
│ ├── BlobStorageConfig.java # Blob Storage 설정
|
||||
│ ├── RetryConfig.java # 재시도 정책
|
||||
│ ├── SecurityConfig.java # Spring Security
|
||||
│ ├── SwaggerConfig.java # Swagger 설정
|
||||
│ └── EmailConfig.java # Email 설정
|
||||
│
|
||||
└── exception/ # Exception Handling
|
||||
└── (향후 추가 예정)
|
||||
```
|
||||
|
||||
### 3.2 구현된 주요 클래스
|
||||
|
||||
#### 3.2.1 Domain Layer (Entity)
|
||||
|
||||
**Notification.java** (notification/src/main/java/com/unicorn/hgzero/notification/domain/Notification.java:1)
|
||||
- 알림 기본 정보 관리
|
||||
- 수신자 목록 (OneToMany)
|
||||
- 중복 방지를 위한 eventId (unique)
|
||||
- 상태 추적 (PENDING, PROCESSING, SENT, FAILED, PARTIAL)
|
||||
|
||||
**NotificationRecipient.java** (notification/src/main/java/com/unicorn/hgzero/notification/domain/NotificationRecipient.java:1)
|
||||
- 수신자별 발송 상태 추적
|
||||
- 재시도 로직 지원 (retryCount, nextRetryAt)
|
||||
- 발송 성공/실패 처리 메서드
|
||||
|
||||
**NotificationSetting.java** (notification/src/main/java/com/unicorn/hgzero/notification/domain/NotificationSetting.java:1)
|
||||
- 사용자별 알림 설정
|
||||
- 채널 활성화 (email, SMS, push)
|
||||
- 알림 유형별 활성화
|
||||
- 방해 금지 시간대 (DND)
|
||||
|
||||
#### 3.2.2 Repository Layer
|
||||
|
||||
**NotificationRepository.java** (notification/src/main/java/com/unicorn/hgzero/notification/repository/NotificationRepository.java:1)
|
||||
- JpaRepository 확장
|
||||
- 커스텀 쿼리 메서드:
|
||||
- findByEventId() - 중복 체크
|
||||
- findByReferenceIdAndReferenceType() - 참조 조회
|
||||
- findByStatusIn() - 배치 처리
|
||||
- countByStatusAndCreatedAtBetween() - 통계
|
||||
|
||||
**NotificationRecipientRepository.java** (notification/src/main/java/com/unicorn/hgzero/notification/repository/NotificationRecipientRepository.java:1)
|
||||
- 수신자 관리
|
||||
- 커스텀 쿼리 메서드:
|
||||
- findByNotificationId() - 알림별 수신자
|
||||
- findByStatusAndNextRetryAtBefore() - 재시도 대상
|
||||
- findByRecipientEmail() - 사용자 히스토리
|
||||
|
||||
**NotificationSettingRepository.java** (notification/src/main/java/com/unicorn/hgzero/notification/repository/NotificationSettingRepository.java:1)
|
||||
- 알림 설정 관리
|
||||
- 커스텀 쿼리 메서드:
|
||||
- findByUserId() - 사용자 설정 조회
|
||||
- findByEmailEnabledAndInvitationEnabled() - 발송 대상 필터링
|
||||
|
||||
#### 3.2.3 Service Layer
|
||||
|
||||
**NotificationService.java** (notification/src/main/java/com/unicorn/hgzero/notification/service/NotificationService.java:1)
|
||||
- 핵심 비즈니스 로직
|
||||
- 주요 메서드:
|
||||
- sendMeetingInvitation() - 회의 초대 알림 발송
|
||||
- sendTodoAssignment() - Todo 할당 알림 발송
|
||||
- canSendNotification() - 알림 발송 가능 여부 확인
|
||||
- 기능:
|
||||
- 이벤트 중복 체크 (eventId)
|
||||
- 사용자 알림 설정 확인
|
||||
- 템플릿 렌더링 및 이메일 발송
|
||||
- 수신자별 상태 추적
|
||||
|
||||
**EmailTemplateService.java** (notification/src/main/java/com/unicorn/hgzero/notification/service/EmailTemplateService.java:1)
|
||||
- Thymeleaf 템플릿 렌더링
|
||||
- 주요 메서드:
|
||||
- renderMeetingInvitation() - 회의 초대 템플릿
|
||||
- renderTodoAssigned() - Todo 할당 템플릿
|
||||
- renderReminder() - 리마인더 템플릿
|
||||
|
||||
**EmailClient.java** (notification/src/main/java/com/unicorn/hgzero/notification/service/EmailClient.java:1)
|
||||
- SMTP 이메일 발송
|
||||
- 재시도 메커니즘 (@Retryable)
|
||||
- Exponential Backoff (5분 → 15분 → 30분)
|
||||
- HTML 및 텍스트 이메일 지원
|
||||
|
||||
#### 3.2.4 Controller Layer
|
||||
|
||||
**NotificationController.java** (notification/src/main/java/com/unicorn/hgzero/notification/controller/NotificationController.java:1)
|
||||
- 알림 조회 API
|
||||
- 엔드포인트:
|
||||
- GET /notifications - 알림 목록 조회
|
||||
- GET /notifications/{id} - 특정 알림 조회
|
||||
- GET /notifications/statistics - 통계 조회
|
||||
|
||||
**NotificationSettingsController.java** (notification/src/main/java/com/unicorn/hgzero/notification/controller/NotificationSettingsController.java:1)
|
||||
- 알림 설정 API
|
||||
- 엔드포인트:
|
||||
- GET /notifications/settings - 설정 조회
|
||||
- PUT /notifications/settings - 설정 업데이트
|
||||
|
||||
#### 3.2.5 Event Handler Layer
|
||||
|
||||
**EventHandler.java** (notification/src/main/java/com/unicorn/hgzero/notification/event/EventHandler.java:1)
|
||||
- Consumer<EventContext> 구현
|
||||
- 이벤트 수신 및 처리
|
||||
- 토픽별 라우팅 (meeting, todo)
|
||||
- 이벤트 유형별 처리 (MeetingCreated, TodoAssigned)
|
||||
- Checkpoint 업데이트
|
||||
|
||||
**EventProcessorService.java** (notification/src/main/java/com/unicorn/hgzero/notification/event/processor/EventProcessorService.java:1)
|
||||
- EventProcessorClient 라이프사이클 관리
|
||||
- @PostConstruct - 시작
|
||||
- @PreDestroy - 종료
|
||||
- @Retryable - 재시도 지원
|
||||
|
||||
#### 3.2.6 Config Layer
|
||||
|
||||
**EventHubConfig.java** (notification/src/main/java/com/unicorn/hgzero/notification/config/EventHubConfig.java:1)
|
||||
- EventProcessorClient Bean 생성
|
||||
- BlobCheckpointStore 설정
|
||||
- 오류 핸들러 등록
|
||||
|
||||
**BlobStorageConfig.java** (notification/src/main/java/com/unicorn/hgzero/notification/config/BlobStorageConfig.java:1)
|
||||
- Blob Container Async Client
|
||||
- Checkpoint 저장소 연결
|
||||
|
||||
**RetryConfig.java** (notification/src/main/java/com/unicorn/hgzero/notification/config/RetryConfig.java:1)
|
||||
- @EnableRetry
|
||||
- RetryTemplate 구성
|
||||
- Exponential Backoff Policy
|
||||
|
||||
**SecurityConfig.java** (notification/src/main/java/com/unicorn/hgzero/notification/config/SecurityConfig.java:1)
|
||||
- Spring Security 설정
|
||||
- CORS 설정
|
||||
- Stateless 세션 관리
|
||||
|
||||
**SwaggerConfig.java** (notification/src/main/java/com/unicorn/hgzero/notification/config/SwaggerConfig.java:1)
|
||||
- OpenAPI 3.0 설정
|
||||
- Swagger UI 구성
|
||||
|
||||
**EmailConfig.java** (notification/src/main/java/com/unicorn/hgzero/notification/config/EmailConfig.java:1)
|
||||
- JavaMailSender Bean
|
||||
- SMTP 설정
|
||||
|
||||
---
|
||||
|
||||
## 4. 데이터베이스 설계
|
||||
|
||||
### 4.1 테이블 구조
|
||||
|
||||
#### notifications (알림 테이블)
|
||||
```sql
|
||||
CREATE TABLE notifications (
|
||||
notification_id VARCHAR(36) PRIMARY KEY,
|
||||
event_id VARCHAR(100) UNIQUE NOT NULL,
|
||||
reference_id VARCHAR(36) NOT NULL,
|
||||
reference_type VARCHAR(20) NOT NULL,
|
||||
notification_type VARCHAR(30) NOT NULL,
|
||||
title VARCHAR(500) NOT NULL,
|
||||
message TEXT,
|
||||
status VARCHAR(20) NOT NULL,
|
||||
channel VARCHAR(20) NOT NULL,
|
||||
sent_count INTEGER NOT NULL DEFAULT 0,
|
||||
failed_count INTEGER NOT NULL DEFAULT 0,
|
||||
created_at TIMESTAMP NOT NULL,
|
||||
sent_at TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE INDEX idx_notification_reference ON notifications(reference_id, reference_type);
|
||||
CREATE INDEX idx_notification_created_at ON notifications(created_at);
|
||||
```
|
||||
|
||||
#### notification_recipients (수신자 테이블)
|
||||
```sql
|
||||
CREATE TABLE notification_recipients (
|
||||
recipient_id VARCHAR(36) PRIMARY KEY,
|
||||
notification_id VARCHAR(36) NOT NULL,
|
||||
recipient_user_id VARCHAR(100) NOT NULL,
|
||||
recipient_name VARCHAR(200) NOT NULL,
|
||||
recipient_email VARCHAR(320) NOT NULL,
|
||||
status VARCHAR(20) NOT NULL,
|
||||
retry_count INTEGER NOT NULL DEFAULT 0,
|
||||
sent_at TIMESTAMP,
|
||||
error_message VARCHAR(1000),
|
||||
next_retry_at TIMESTAMP,
|
||||
created_at TIMESTAMP NOT NULL,
|
||||
updated_at TIMESTAMP,
|
||||
FOREIGN KEY (notification_id) REFERENCES notifications(notification_id)
|
||||
);
|
||||
|
||||
CREATE INDEX idx_recipient_notification ON notification_recipients(notification_id);
|
||||
CREATE INDEX idx_recipient_email ON notification_recipients(recipient_email);
|
||||
CREATE INDEX idx_recipient_status ON notification_recipients(status);
|
||||
```
|
||||
|
||||
#### notification_settings (알림 설정 테이블)
|
||||
```sql
|
||||
CREATE TABLE notification_settings (
|
||||
user_id VARCHAR(100) PRIMARY KEY,
|
||||
email_enabled BOOLEAN NOT NULL DEFAULT TRUE,
|
||||
sms_enabled BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
push_enabled BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
invitation_enabled BOOLEAN NOT NULL DEFAULT TRUE,
|
||||
todo_assigned_enabled BOOLEAN NOT NULL DEFAULT TRUE,
|
||||
todo_reminder_enabled BOOLEAN NOT NULL DEFAULT TRUE,
|
||||
meeting_reminder_enabled BOOLEAN NOT NULL DEFAULT TRUE,
|
||||
minutes_updated_enabled BOOLEAN NOT NULL DEFAULT TRUE,
|
||||
todo_completed_enabled BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
dnd_enabled BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
dnd_start_time TIME,
|
||||
dnd_end_time TIME,
|
||||
created_at TIMESTAMP NOT NULL,
|
||||
updated_at TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE UNIQUE INDEX idx_setting_user_id ON notification_settings(user_id);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. API 명세
|
||||
|
||||
### 5.1 알림 조회 API
|
||||
|
||||
#### 알림 목록 조회
|
||||
- **URL**: GET /notifications
|
||||
- **Query Parameters**:
|
||||
- referenceType: MEETING | TODO (optional)
|
||||
- notificationType: INVITATION | TODO_ASSIGNED | ... (optional)
|
||||
- status: PENDING | SENT | FAILED | PARTIAL (optional)
|
||||
- startDate: ISO DateTime (optional)
|
||||
- endDate: ISO DateTime (optional)
|
||||
- **Response**: List<NotificationListResponse>
|
||||
|
||||
#### 알림 상세 조회
|
||||
- **URL**: GET /notifications/{notificationId}
|
||||
- **Path Parameter**: notificationId (String)
|
||||
- **Response**: NotificationResponse
|
||||
|
||||
#### 알림 통계 조회
|
||||
- **URL**: GET /notifications/statistics
|
||||
- **Query Parameters**:
|
||||
- startDate: ISO DateTime (required)
|
||||
- endDate: ISO DateTime (required)
|
||||
- **Response**: { sent, failed, partial, total }
|
||||
|
||||
### 5.2 알림 설정 API
|
||||
|
||||
#### 알림 설정 조회
|
||||
- **URL**: GET /notifications/settings
|
||||
- **Query Parameter**: userId (String, required)
|
||||
- **Response**: SettingsResponse
|
||||
|
||||
#### 알림 설정 업데이트
|
||||
- **URL**: PUT /notifications/settings
|
||||
- **Query Parameter**: userId (String, required)
|
||||
- **Request Body**: UpdateSettingsRequest
|
||||
- **Response**: SettingsResponse
|
||||
|
||||
---
|
||||
|
||||
## 6. 이벤트 처리 흐름
|
||||
|
||||
### 6.1 회의 초대 알림 발송
|
||||
|
||||
```
|
||||
1. Meeting Service → Event Hub (MeetingCreatedEvent)
|
||||
2. Event Hub → NotificationService (EventHandler.accept())
|
||||
3. EventHandler → NotificationService.sendMeetingInvitation()
|
||||
4. NotificationService:
|
||||
- 중복 체크 (eventId)
|
||||
- Notification 엔티티 생성
|
||||
- 각 참석자별:
|
||||
- 알림 설정 확인
|
||||
- NotificationRecipient 생성
|
||||
- EmailTemplateService.renderMeetingInvitation()
|
||||
- EmailClient.sendHtmlEmail()
|
||||
- 상태 업데이트 (SENT/FAILED)
|
||||
- Notification 상태 업데이트 (SENT/PARTIAL/FAILED)
|
||||
5. EventHandler → eventContext.updateCheckpoint()
|
||||
```
|
||||
|
||||
### 6.2 Todo 할당 알림 발송
|
||||
|
||||
```
|
||||
1. Meeting/AI Service → Event Hub (TodoAssignedEvent)
|
||||
2. Event Hub → NotificationService (EventHandler.accept())
|
||||
3. EventHandler → NotificationService.sendTodoAssignment()
|
||||
4. NotificationService:
|
||||
- 중복 체크 (eventId)
|
||||
- Notification 엔티티 생성
|
||||
- 알림 설정 확인 (assignee)
|
||||
- NotificationRecipient 생성
|
||||
- EmailTemplateService.renderTodoAssigned()
|
||||
- EmailClient.sendHtmlEmail()
|
||||
- 상태 업데이트 (SENT/FAILED)
|
||||
5. EventHandler → eventContext.updateCheckpoint()
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 7. 재시도 메커니즘
|
||||
|
||||
### 7.1 재시도 정책
|
||||
- **최대 재시도 횟수**: 3회
|
||||
- **Backoff 전략**: Exponential Backoff
|
||||
- **초기 대기 시간**: 5분 (300,000ms)
|
||||
- **최대 대기 시간**: 30분 (1,800,000ms)
|
||||
- **배수**: 2.0
|
||||
|
||||
### 7.2 재시도 시나리오
|
||||
|
||||
1. **이메일 발송 실패 시**:
|
||||
- EmailClient의 @Retryable 어노테이션 적용
|
||||
- 1차 실패 → 5분 후 재시도
|
||||
- 2차 실패 → 10분 후 재시도
|
||||
- 3차 실패 → 20분 후 재시도
|
||||
- 최종 실패 → NotificationRecipient 상태를 FAILED로 변경
|
||||
|
||||
2. **Event Processor 시작 실패 시**:
|
||||
- EventProcessorService의 @Retryable 적용
|
||||
- 최대 3번 재시도 (2초, 4초, 8초 대기)
|
||||
|
||||
---
|
||||
|
||||
## 8. 설정 파일
|
||||
|
||||
### 8.1 application.yml
|
||||
- **위치**: notification/src/main/resources/application.yml
|
||||
- **주요 설정**:
|
||||
- 데이터베이스 연결 (PostgreSQL)
|
||||
- Azure Event Hubs 연결
|
||||
- Azure Blob Storage 연결
|
||||
- SMTP 설정
|
||||
- Thymeleaf 템플릿
|
||||
- Actuator
|
||||
- Logging
|
||||
- SpringDoc OpenAPI
|
||||
|
||||
### 8.2 환경 변수 (필수)
|
||||
```bash
|
||||
# 데이터베이스
|
||||
DB_PASSWORD=<PostgreSQL 비밀번호>
|
||||
|
||||
# Azure Event Hub
|
||||
AZURE_EVENTHUB_CONNECTION_STRING=<Event Hub 연결 문자열>
|
||||
|
||||
# Azure Blob Storage
|
||||
AZURE_STORAGE_CONNECTION_STRING=<Blob Storage 연결 문자열>
|
||||
|
||||
# 이메일
|
||||
MAIL_USERNAME=<SMTP 사용자명>
|
||||
MAIL_PASSWORD=<SMTP 비밀번호>
|
||||
|
||||
# JWT (향후 추가)
|
||||
JWT_SECRET=<JWT 비밀 키>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 9. 빌드 및 실행
|
||||
|
||||
### 9.1 빌드 방법
|
||||
|
||||
#### IntelliJ IDEA 사용
|
||||
1. IntelliJ에서 프로젝트 열기
|
||||
2. Gradle 탭에서 notification → Tasks → build → build 더블클릭
|
||||
3. 또는 우측 상단 Build → Build Project
|
||||
|
||||
#### 커맨드 라인 (Gradle 설치 필요)
|
||||
```bash
|
||||
# Gradle Wrapper 생성 (프로젝트 루트에서)
|
||||
gradle wrapper
|
||||
|
||||
# 빌드
|
||||
./gradlew :notification:build
|
||||
|
||||
# 빌드 결과 확인
|
||||
ls notification/build/libs/
|
||||
```
|
||||
|
||||
### 9.2 실행 방법
|
||||
|
||||
#### IntelliJ IDEA 사용
|
||||
1. NotificationApplication.java 파일 열기
|
||||
2. main() 메서드 좌측의 실행 버튼 클릭
|
||||
3. 또는 Run → Run 'NotificationApplication'
|
||||
|
||||
#### JAR 파일 실행
|
||||
```bash
|
||||
java -jar notification/build/libs/notification.jar
|
||||
```
|
||||
|
||||
### 9.3 서버 포트
|
||||
- **기본 포트**: 8084
|
||||
- **변경 방법**: 환경 변수 SERVER_PORT 설정
|
||||
|
||||
---
|
||||
|
||||
## 10. 테스트
|
||||
|
||||
### 10.1 API 테스트 (Swagger UI)
|
||||
1. 서버 실행 후 브라우저에서 접속:
|
||||
```
|
||||
http://localhost:8084/swagger-ui.html
|
||||
```
|
||||
|
||||
2. API 엔드포인트 테스트:
|
||||
- GET /notifications - 알림 목록 조회
|
||||
- GET /notifications/{id} - 특정 알림 조회
|
||||
- GET /notifications/settings - 알림 설정 조회
|
||||
- PUT /notifications/settings - 알림 설정 업데이트
|
||||
|
||||
### 10.2 이벤트 발행 테스트
|
||||
1. Meeting Service에서 MeetingCreatedEvent 발행
|
||||
2. Notification Service 로그 확인:
|
||||
```
|
||||
이벤트 수신 - Topic: meeting, EventType: MeetingCreated
|
||||
회의 초대 알림 처리 시작 - MeetingId: xxx, EventId: xxx
|
||||
회의 초대 알림 발송 성공 - Email: xxx@xxx.com
|
||||
```
|
||||
|
||||
### 10.3 Health Check
|
||||
```bash
|
||||
curl http://localhost:8084/actuator/health
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 11. 향후 개선 사항
|
||||
|
||||
### 11.1 기능 개선
|
||||
1. **SMS 발송 지원**: 현재 이메일만 지원, SMS 발송 기능 추가
|
||||
2. **Push 알림 지원**: 모바일 Push 알림 기능 추가
|
||||
3. **리마인더 스케줄링**: 회의 및 Todo 리마인더 자동 발송
|
||||
4. **배치 알림 발송**: 대량 알림 발송 최적화
|
||||
5. **알림 템플릿 관리**: 템플릿 동적 관리 및 다국어 지원
|
||||
|
||||
### 11.2 성능 개선
|
||||
1. **비동기 이메일 발송**: @Async를 사용한 비동기 처리
|
||||
2. **캐싱 적용**: 알림 설정 캐싱으로 DB 부하 감소
|
||||
3. **배치 처리**: 대량 수신자 알림의 배치 처리
|
||||
4. **Connection Pool 최적화**: HikariCP 설정 최적화
|
||||
|
||||
### 11.3 모니터링 개선
|
||||
1. **메트릭 수집**: Prometheus 메트릭 추가
|
||||
2. **로그 집계**: ELK Stack 연동
|
||||
3. **알림 대시보드**: Grafana 대시보드 구성
|
||||
4. **알림 실패 알람**: 발송 실패 시 관리자 알림
|
||||
|
||||
---
|
||||
|
||||
## 12. 문제 해결 가이드
|
||||
|
||||
### 12.1 이메일 발송 실패
|
||||
**증상**: 이메일이 발송되지 않음
|
||||
|
||||
**원인 및 해결방법**:
|
||||
1. SMTP 인증 정보 확인:
|
||||
```bash
|
||||
MAIL_USERNAME=<이메일 주소>
|
||||
MAIL_PASSWORD=<앱 비밀번호>
|
||||
```
|
||||
|
||||
2. Gmail 사용 시 앱 비밀번호 생성:
|
||||
- Google 계정 → 보안 → 2단계 인증 활성화
|
||||
- 앱 비밀번호 생성
|
||||
|
||||
3. 방화벽 확인:
|
||||
- 포트 587 (TLS) 또는 465 (SSL) 개방 확인
|
||||
|
||||
### 12.2 Event Hub 연결 실패
|
||||
**증상**: 이벤트를 수신하지 못함
|
||||
|
||||
**원인 및 해결방법**:
|
||||
1. 연결 문자열 확인:
|
||||
```bash
|
||||
AZURE_EVENTHUB_CONNECTION_STRING=<연결 문자열>
|
||||
```
|
||||
|
||||
2. Consumer Group 확인:
|
||||
```yaml
|
||||
azure:
|
||||
eventhub:
|
||||
consumer-group: notification-service
|
||||
```
|
||||
|
||||
3. Event Hub 방화벽 설정 확인
|
||||
|
||||
### 12.3 데이터베이스 연결 실패
|
||||
**증상**: 애플리케이션 시작 실패
|
||||
|
||||
**원인 및 해결방법**:
|
||||
1. PostgreSQL 서버 상태 확인
|
||||
2. 연결 정보 확인:
|
||||
```yaml
|
||||
datasource:
|
||||
url: jdbc:postgresql://4.230.159.143:5432/notificationdb
|
||||
username: hgzerouser
|
||||
password: ${DB_PASSWORD}
|
||||
```
|
||||
|
||||
3. 방화벽 확인: 포트 5432 개방 확인
|
||||
|
||||
---
|
||||
|
||||
## 13. 참고 자료
|
||||
|
||||
### 13.1 문서
|
||||
- [백엔드개발가이드](claude/dev-backend.md)
|
||||
- [패키지구조도](develop/dev/package-structure-notification.md)
|
||||
- [API설계서](design/backend/api/API설계서.md)
|
||||
- [데이터베이스설치결과서](develop/database/exec/db-exec-dev.md)
|
||||
|
||||
### 13.2 외부 라이브러리
|
||||
- [Spring Boot Documentation](https://spring.io/projects/spring-boot)
|
||||
- [Azure Event Hubs Java SDK](https://learn.microsoft.com/en-us/azure/event-hubs/event-hubs-java-get-started-send)
|
||||
- [Spring Retry](https://github.com/spring-projects/spring-retry)
|
||||
- [Thymeleaf](https://www.thymeleaf.org/)
|
||||
|
||||
---
|
||||
|
||||
**작성일**: 2025-10-23
|
||||
**작성자**: 준호 (Backend Developer)
|
||||
**버전**: 1.0
|
||||
@@ -0,0 +1,146 @@
|
||||
# Notification Service - 패키지 구조도
|
||||
|
||||
## 아키텍처 패턴
|
||||
- **Layered Architecture**: 단순하고 명확한 계층 구조
|
||||
|
||||
## 패키지 구조
|
||||
|
||||
```
|
||||
notification/
|
||||
└── src/
|
||||
└── main/
|
||||
├── java/
|
||||
│ └── com/
|
||||
│ └── unicorn/
|
||||
│ └── hgzero/
|
||||
│ └── notification/
|
||||
│ ├── NotificationApplication.java
|
||||
│ │
|
||||
│ ├── domain/ # Domain Layer
|
||||
│ │ ├── Notification.java # 알림 Entity
|
||||
│ │ ├── NotificationRecipient.java # 수신자 Entity
|
||||
│ │ └── NotificationSetting.java # 알림 설정 Entity
|
||||
│ │
|
||||
│ ├── repository/ # Data Access Layer
|
||||
│ │ ├── NotificationRepository.java
|
||||
│ │ ├── NotificationRecipientRepository.java
|
||||
│ │ └── NotificationSettingRepository.java
|
||||
│ │
|
||||
│ ├── service/ # Business Logic Layer
|
||||
│ │ ├── NotificationService.java # 알림 비즈니스 로직
|
||||
│ │ ├── EmailTemplateService.java # 이메일 템플릿 렌더링
|
||||
│ │ └── EmailClient.java # 이메일 발송 클라이언트
|
||||
│ │
|
||||
│ ├── controller/ # Presentation Layer
|
||||
│ │ ├── NotificationController.java # Public API
|
||||
│ │ └── NotificationSettingsController.java # 설정 API
|
||||
│ │
|
||||
│ ├── event/ # Event Handler Layer
|
||||
│ │ ├── EventHandler.java # Event Hub 이벤트 핸들러
|
||||
│ │ ├── event/
|
||||
│ │ │ ├── MeetingCreatedEvent.java # 회의 생성 이벤트
|
||||
│ │ │ └── TodoAssignedEvent.java # Todo 할당 이벤트
|
||||
│ │ └── processor/
|
||||
│ │ └── EventProcessorService.java # Processor 라이프사이클
|
||||
│ │
|
||||
│ ├── dto/ # Data Transfer Objects
|
||||
│ │ ├── request/
|
||||
│ │ │ ├── SendNotificationRequest.java
|
||||
│ │ │ └── UpdateSettingsRequest.java
|
||||
│ │ └── response/
|
||||
│ │ ├── NotificationResponse.java
|
||||
│ │ ├── NotificationListResponse.java
|
||||
│ │ └── SettingsResponse.java
|
||||
│ │
|
||||
│ ├── config/ # Configuration Layer
|
||||
│ │ ├── EventHubConfig.java # Event Hub 설정
|
||||
│ │ ├── BlobStorageConfig.java # Blob Storage 설정
|
||||
│ │ ├── RetryConfig.java # 재시도 정책 설정
|
||||
│ │ ├── SecurityConfig.java # Spring Security 설정
|
||||
│ │ ├── SwaggerConfig.java # Swagger 설정
|
||||
│ │ └── EmailConfig.java # Email 설정
|
||||
│ │
|
||||
│ └── exception/ # Exception Handling
|
||||
│ ├── GlobalExceptionHandler.java
|
||||
│ ├── NotificationException.java
|
||||
│ └── EventProcessingException.java
|
||||
│
|
||||
└── resources/
|
||||
├── application.yml # 메인 설정 파일
|
||||
├── application-dev.yml # 개발 환경 설정
|
||||
├── application-prod.yml # 운영 환경 설정
|
||||
└── templates/ # Email Templates
|
||||
├── meeting-invitation.html # 회의 초대 템플릿
|
||||
├── todo-assigned.html # Todo 할당 템플릿
|
||||
└── reminder.html # 리마인더 템플릿
|
||||
```
|
||||
|
||||
## 주요 클래스 역할
|
||||
|
||||
### Domain Layer
|
||||
- **Notification**: 알림 정보 엔티티 (알림ID, 유형, 상태, 발송일시)
|
||||
- **NotificationRecipient**: 수신자별 알림 상태 (발송완료, 실패, 재시도)
|
||||
- **NotificationSetting**: 사용자별 알림 설정 (채널, 유형, 방해금지 시간대)
|
||||
|
||||
### Repository Layer
|
||||
- **NotificationRepository**: 알림 이력 조회/저장
|
||||
- **NotificationRecipientRepository**: 수신자별 상태 관리
|
||||
- **NotificationSettingRepository**: 알림 설정 관리
|
||||
|
||||
### Service Layer
|
||||
- **NotificationService**: 알림 발송 비즈니스 로직, 중복 방지, 재시도 관리
|
||||
- **EmailTemplateService**: Thymeleaf 템플릿 렌더링
|
||||
- **EmailClient**: SMTP 이메일 발송, 에러 처리
|
||||
|
||||
### Controller Layer
|
||||
- **NotificationController**: 알림 발송 API, 알림 이력 조회 API
|
||||
- **NotificationSettingsController**: 알림 설정 조회/업데이트 API
|
||||
|
||||
### Event Handler Layer
|
||||
- **EventHandler**: Event Hub 이벤트 수신 및 처리 (Consumer<EventContext> 구현)
|
||||
- **EventProcessorService**: EventProcessorClient 라이프사이클 관리
|
||||
- **MeetingCreatedEvent**: 회의 생성 이벤트 DTO
|
||||
- **TodoAssignedEvent**: Todo 할당 이벤트 DTO
|
||||
|
||||
### Config Layer
|
||||
- **EventHubConfig**: EventProcessorClient Bean 생성, CheckpointStore 설정
|
||||
- **BlobStorageConfig**: Azure Blob Storage 연결 설정
|
||||
- **RetryConfig**: @EnableRetry, ExponentialBackOffPolicy 설정
|
||||
- **SecurityConfig**: JWT 인증, CORS 설정
|
||||
- **SwaggerConfig**: OpenAPI 문서화 설정
|
||||
- **EmailConfig**: JavaMailSender 설정
|
||||
|
||||
## 의존성 흐름
|
||||
```
|
||||
Controller → Service → Repository → Entity
|
||||
↓
|
||||
EmailClient
|
||||
↓
|
||||
EmailTemplateService
|
||||
|
||||
EventHandler → Service → Repository
|
||||
```
|
||||
|
||||
## 기술 스택
|
||||
- **Framework**: Spring Boot 3.3.0, Java 21
|
||||
- **Database**: PostgreSQL (JPA/Hibernate)
|
||||
- **Messaging**: Azure Event Hubs
|
||||
- **Storage**: Azure Blob Storage (Checkpoint)
|
||||
- **Email**: Spring Mail (SMTP)
|
||||
- **Template**: Thymeleaf
|
||||
- **Retry**: Spring Retry
|
||||
- **Security**: Spring Security + JWT
|
||||
- **Documentation**: SpringDoc OpenAPI
|
||||
|
||||
## 특징
|
||||
1. **Layered Architecture**: 계층 분리로 명확한 역할과 책임
|
||||
2. **Event-Driven**: Azure Event Hubs 기반 비동기 처리
|
||||
3. **Retry Mechanism**: Exponential Backoff 기반 재시도
|
||||
4. **Template Engine**: Thymeleaf로 동적 이메일 생성
|
||||
5. **Idempotency**: 이벤트 ID 기반 중복 발송 방지
|
||||
6. **Monitoring**: Actuator Health Check, Metrics
|
||||
|
||||
---
|
||||
|
||||
**작성일**: 2025-10-23
|
||||
**작성자**: 준호 (Backend Developer)
|
||||
Reference in New Issue
Block a user