mirror of
https://github.com/ktds-dg0501/kt-event-marketing.git
synced 2025-12-06 20:46:24 +00:00
✨ 주요 기능 - Azure 기반 물리아키텍처 설계 (개발환경/운영환경) - 7개 마이크로서비스 물리 구조 설계 - 네트워크 아키텍처 다이어그램 작성 (Mermaid) - 환경별 비교 분석 및 마스터 인덱스 문서 📁 생성 파일 - design/backend/physical/physical-architecture.md (마스터) - design/backend/physical/physical-architecture-dev.md (개발환경) - design/backend/physical/physical-architecture-prod.md (운영환경) - design/backend/physical/*.mmd (4개 Mermaid 다이어그램) 🎯 핵심 성과 - 비용 최적화: 개발환경 월 $143, 운영환경 월 $2,860 - 확장성: 개발환경 100명 → 운영환경 10,000명 (100배) - 가용성: 개발환경 95% → 운영환경 99.9% - 보안: 다층 보안 아키텍처 (L1~L4) 🛠️ 기술 스택 - Azure Kubernetes Service (AKS) - Azure Database for PostgreSQL Flexible - Azure Cache for Redis Premium - Azure Service Bus Premium - Application Gateway + WAF 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
539 lines
14 KiB
Markdown
539 lines
14 KiB
Markdown
# Event Service 클래스 설계서
|
|
|
|
## 1. 개요
|
|
|
|
### 1.1 목적
|
|
Event Service의 Clean Architecture 기반 클래스 설계를 정의합니다.
|
|
|
|
### 1.2 설계 원칙
|
|
- **아키텍처 패턴**: Clean Architecture
|
|
- **패키지 그룹**: com.kt.event
|
|
- **의존성 방향**: Presentation → Application → Domain ← Infrastructure
|
|
|
|
### 1.3 핵심 특징
|
|
- 복잡한 이벤트 생명주기 관리 (DRAFT → PUBLISHED → ENDED)
|
|
- 상태 머신 패턴 적용
|
|
- AI 서비스 비동기 연동 (Kafka)
|
|
- Content Service 동기 연동 (Feign)
|
|
- Redis 캐시 활용
|
|
|
|
---
|
|
|
|
## 2. 계층별 구조
|
|
|
|
### 2.1 Domain Layer (핵심 비즈니스 로직)
|
|
|
|
#### 2.1.1 Entity
|
|
**Event (이벤트 집합 루트)**
|
|
```java
|
|
- 책임: 이벤트 전체 생명주기 관리
|
|
- 상태: DRAFT, PUBLISHED, ENDED
|
|
- 비즈니스 규칙:
|
|
* DRAFT 상태에서만 수정 가능
|
|
* 배포 시 필수 데이터 검증 (이벤트명, 기간, 이미지, 채널)
|
|
* 상태 전이 제약 (DRAFT → PUBLISHED → ENDED)
|
|
- 관계:
|
|
* 1:N GeneratedImage (생성된 이미지)
|
|
* 1:N AiRecommendation (AI 추천안)
|
|
```
|
|
|
|
**AiRecommendation (AI 추천 엔티티)**
|
|
```java
|
|
- 책임: AI가 생성한 이벤트 기획안 관리
|
|
- 속성: 이벤트명, 설명, 프로모션 유형, 타겟 고객
|
|
- 선택 상태: isSelected (단일 선택)
|
|
```
|
|
|
|
**GeneratedImage (생성 이미지 엔티티)**
|
|
```java
|
|
- 책임: 이벤트별 생성된 이미지 관리
|
|
- 속성: 이미지 URL, 스타일, 플랫폼
|
|
- 선택 상태: isSelected (단일 선택)
|
|
```
|
|
|
|
**Job (비동기 작업 엔티티)**
|
|
```java
|
|
- 책임: AI 추천, 이미지 생성 등 비동기 작업 상태 관리
|
|
- 상태: PENDING, PROCESSING, COMPLETED, FAILED
|
|
- 진행률: 0~100 (progress)
|
|
- 결과: Redis 키 (resultKey) 또는 에러 메시지
|
|
```
|
|
|
|
#### 2.1.2 Enums
|
|
- **EventStatus**: DRAFT, PUBLISHED, ENDED
|
|
- **JobStatus**: PENDING, PROCESSING, COMPLETED, FAILED
|
|
- **JobType**: AI_RECOMMENDATION, IMAGE_GENERATION
|
|
|
|
#### 2.1.3 Repository Interfaces
|
|
- **EventRepository**: 이벤트 조회, 필터링, 페이징
|
|
- **AiRecommendationRepository**: AI 추천 관리
|
|
- **GeneratedImageRepository**: 이미지 관리
|
|
- **JobRepository**: 작업 상태 관리
|
|
|
|
---
|
|
|
|
### 2.2 Application Layer (유스케이스)
|
|
|
|
#### 2.2.1 Services
|
|
|
|
**EventService (핵심 오케스트레이터)**
|
|
```java
|
|
책임:
|
|
- 이벤트 전체 생명주기 조율
|
|
- AI 서비스 연동 (Kafka 비동기)
|
|
- Content 서비스 연동 (Feign 동기)
|
|
- 트랜잭션 경계 관리
|
|
|
|
주요 유스케이스:
|
|
1. createEvent(): 이벤트 생성 (Step 1: 목적 선택)
|
|
2. requestAiRecommendations(): AI 추천 요청 (Step 2)
|
|
3. selectRecommendation(): AI 추천 선택
|
|
4. requestImageGeneration(): 이미지 생성 요청 (Step 3)
|
|
5. selectImage(): 이미지 선택
|
|
6. selectChannels(): 배포 채널 선택 (Step 4)
|
|
7. publishEvent(): 이벤트 배포 (Step 5)
|
|
8. endEvent(): 이벤트 종료
|
|
```
|
|
|
|
**JobService (작업 관리)**
|
|
```java
|
|
책임:
|
|
- 비동기 작업 상태 조회
|
|
- 작업 진행률 업데이트
|
|
- 작업 완료/실패 처리
|
|
|
|
주요 유스케이스:
|
|
1. createJob(): 작업 생성
|
|
2. getJobStatus(): 작업 상태 조회
|
|
3. updateJobProgress(): 진행률 업데이트
|
|
4. completeJob(): 작업 완료 처리
|
|
5. failJob(): 작업 실패 처리
|
|
```
|
|
|
|
#### 2.2.2 DTOs
|
|
|
|
**Request DTOs**
|
|
- SelectObjectiveRequest: 목적 선택
|
|
- AiRecommendationRequest: AI 추천 요청 (매장 정보 포함)
|
|
- SelectRecommendationRequest: AI 추천 선택 + 커스터마이징
|
|
- ImageGenerationRequest: 이미지 생성 요청 (스타일, 플랫폼)
|
|
- SelectImageRequest: 이미지 선택
|
|
- ImageEditRequest: 이미지 편집
|
|
- SelectChannelsRequest: 배포 채널 선택
|
|
- UpdateEventRequest: 이벤트 수정
|
|
|
|
**Response DTOs**
|
|
- EventCreatedResponse: 이벤트 생성 응답
|
|
- EventDetailResponse: 이벤트 상세 (이미지, 추천 포함)
|
|
- JobAcceptedResponse: 작업 접수 응답
|
|
- JobStatusResponse: 작업 상태 응답
|
|
- ImageGenerationResponse: 이미지 생성 응답
|
|
|
|
**Kafka Message DTOs**
|
|
- AIEventGenerationJobMessage: AI 작업 메시지
|
|
- ImageGenerationJobMessage: 이미지 생성 작업 메시지
|
|
- EventCreatedMessage: 이벤트 생성 이벤트
|
|
|
|
---
|
|
|
|
### 2.3 Infrastructure Layer (기술 구현)
|
|
|
|
#### 2.3.1 Kafka (비동기 메시징)
|
|
|
|
**AIJobKafkaProducer**
|
|
```java
|
|
책임: AI 추천 생성 작업 발행
|
|
토픽: ai-event-generation-job
|
|
메시지: AIEventGenerationJobMessage
|
|
```
|
|
|
|
**AIJobKafkaConsumer**
|
|
```java
|
|
책임: AI 작업 결과 수신 및 처리
|
|
처리: COMPLETED, FAILED, PROCESSING 상태별 분기
|
|
수동 커밋: Acknowledgment 사용
|
|
```
|
|
|
|
**ImageJobKafkaConsumer**
|
|
```java
|
|
책임: 이미지 생성 작업 결과 수신
|
|
처리: 생성된 이미지 DB 저장
|
|
```
|
|
|
|
**EventKafkaProducer**
|
|
```java
|
|
책임: 이벤트 생성 이벤트 발행
|
|
토픽: event-created
|
|
용도: Distribution Service 연동
|
|
```
|
|
|
|
#### 2.3.2 Client (외부 서비스 연동)
|
|
|
|
**ContentServiceClient (Feign)**
|
|
```java
|
|
대상: Content Service (포트 8082)
|
|
API: POST /api/v1/content/images/generate
|
|
요청: ContentImageGenerationRequest
|
|
응답: ContentJobResponse (Job ID 반환)
|
|
```
|
|
|
|
#### 2.3.3 Config
|
|
|
|
**RedisConfig**
|
|
```java
|
|
책임: Redis 연결 설정
|
|
용도:
|
|
- AI 추천 결과 임시 저장
|
|
- 이미지 생성 결과 임시 저장
|
|
- Job 결과 캐싱
|
|
```
|
|
|
|
---
|
|
|
|
### 2.4 Presentation Layer (API)
|
|
|
|
#### 2.4.1 Controllers
|
|
|
|
**EventController**
|
|
```java
|
|
Base Path: /api/v1/events
|
|
|
|
주요 엔드포인트:
|
|
1. POST /objectives - 이벤트 목적 선택 (생성)
|
|
2. GET /events - 이벤트 목록 조회 (페이징, 필터링)
|
|
3. GET /events/{id} - 이벤트 상세 조회
|
|
4. DELETE /events/{id} - 이벤트 삭제
|
|
5. POST /events/{id}/publish - 이벤트 배포
|
|
6. POST /events/{id}/end - 이벤트 종료
|
|
7. POST /events/{id}/ai-recommendations - AI 추천 요청
|
|
8. PUT /events/{id}/recommendations - AI 추천 선택
|
|
9. POST /events/{id}/images - 이미지 생성 요청
|
|
10. PUT /events/{id}/images/{imageId}/select - 이미지 선택
|
|
11. PUT /events/{id}/images/{imageId}/edit - 이미지 편집
|
|
12. PUT /events/{id}/channels - 배포 채널 선택
|
|
13. PUT /events/{id} - 이벤트 수정
|
|
```
|
|
|
|
**JobController**
|
|
```java
|
|
Base Path: /api/v1/jobs
|
|
|
|
엔드포인트:
|
|
1. GET /jobs/{id} - 작업 상태 조회
|
|
```
|
|
|
|
---
|
|
|
|
## 3. 핵심 플로우
|
|
|
|
### 3.1 이벤트 생성 플로우
|
|
|
|
```
|
|
1. 목적 선택 (POST /objectives)
|
|
→ Event 생성 (DRAFT 상태)
|
|
|
|
2. AI 추천 요청 (POST /events/{id}/ai-recommendations)
|
|
→ Job 생성 (AI_RECOMMENDATION)
|
|
→ Kafka 메시지 발행 (ai-event-generation-job)
|
|
→ AI Service 처리
|
|
→ Kafka 메시지 수신 (결과)
|
|
→ Redis 캐시 저장
|
|
→ Job 완료 처리
|
|
|
|
3. AI 추천 선택 (PUT /events/{id}/recommendations)
|
|
→ Redis에서 추천 목록 조회
|
|
→ 선택 + 커스터마이징 적용
|
|
→ Event 업데이트 (eventName, description, period)
|
|
|
|
4. 이미지 생성 요청 (POST /events/{id}/images)
|
|
→ Content Service 호출 (Feign)
|
|
→ Job ID 반환
|
|
→ 폴링으로 상태 확인
|
|
|
|
5. 이미지 선택 (PUT /events/{id}/images/{imageId}/select)
|
|
→ Event.selectedImageId 업데이트
|
|
→ GeneratedImage.isSelected = true
|
|
|
|
6. 배포 채널 선택 (PUT /events/{id}/channels)
|
|
→ Event.channels 업데이트
|
|
|
|
7. 이벤트 배포 (POST /events/{id}/publish)
|
|
→ 필수 데이터 검증
|
|
→ 상태 변경 (DRAFT → PUBLISHED)
|
|
→ Kafka 메시지 발행 (event-created)
|
|
```
|
|
|
|
### 3.2 상태 머신 다이어그램
|
|
|
|
```
|
|
DRAFT → publish() → PUBLISHED → end() → ENDED
|
|
↑ |
|
|
| ↓
|
|
└─────── (수정 불가) ─────┘
|
|
```
|
|
|
|
**상태별 제약:**
|
|
- DRAFT: 모든 수정 가능, 삭제 가능
|
|
- PUBLISHED: 수정 불가, 삭제 불가, 종료만 가능
|
|
- ENDED: 모든 변경 불가 (읽기 전용)
|
|
|
|
---
|
|
|
|
## 4. 비동기 작업 처리
|
|
|
|
### 4.1 Job 생명주기
|
|
|
|
```
|
|
PENDING → start() → PROCESSING → complete() → COMPLETED
|
|
↓
|
|
fail() → FAILED
|
|
```
|
|
|
|
### 4.2 작업 유형별 처리
|
|
|
|
**AI_RECOMMENDATION (AI 추천 생성)**
|
|
- 발행: AIJobKafkaProducer
|
|
- 수신: AIJobKafkaConsumer
|
|
- 결과: Redis 캐시 (추천 목록)
|
|
- 시간: 10~30초
|
|
|
|
**IMAGE_GENERATION (이미지 생성)**
|
|
- 발행: EventService → ContentServiceClient
|
|
- 수신: ImageJobKafkaConsumer (Content Service에서 발행)
|
|
- 결과: GeneratedImage 엔티티 (DB 저장)
|
|
- 시간: 30~60초
|
|
|
|
---
|
|
|
|
## 5. 패키지 구조
|
|
|
|
```
|
|
com.kt.event.eventservice
|
|
├── domain/
|
|
│ ├── entity/
|
|
│ │ ├── Event.java
|
|
│ │ ├── AiRecommendation.java
|
|
│ │ ├── GeneratedImage.java
|
|
│ │ └── Job.java
|
|
│ ├── enums/
|
|
│ │ ├── EventStatus.java
|
|
│ │ ├── JobStatus.java
|
|
│ │ └── JobType.java
|
|
│ └── repository/
|
|
│ ├── EventRepository.java
|
|
│ ├── AiRecommendationRepository.java
|
|
│ ├── GeneratedImageRepository.java
|
|
│ └── JobRepository.java
|
|
├── application/
|
|
│ ├── service/
|
|
│ │ ├── EventService.java
|
|
│ │ └── JobService.java
|
|
│ └── dto/
|
|
│ ├── request/
|
|
│ │ ├── SelectObjectiveRequest.java
|
|
│ │ ├── AiRecommendationRequest.java
|
|
│ │ ├── SelectRecommendationRequest.java
|
|
│ │ ├── ImageGenerationRequest.java
|
|
│ │ ├── SelectImageRequest.java
|
|
│ │ ├── ImageEditRequest.java
|
|
│ │ ├── SelectChannelsRequest.java
|
|
│ │ └── UpdateEventRequest.java
|
|
│ ├── response/
|
|
│ │ ├── EventCreatedResponse.java
|
|
│ │ ├── EventDetailResponse.java
|
|
│ │ ├── JobAcceptedResponse.java
|
|
│ │ ├── JobStatusResponse.java
|
|
│ │ ├── ImageGenerationResponse.java
|
|
│ │ └── ImageEditResponse.java
|
|
│ └── kafka/
|
|
│ ├── AIEventGenerationJobMessage.java
|
|
│ ├── ImageGenerationJobMessage.java
|
|
│ └── EventCreatedMessage.java
|
|
├── infrastructure/
|
|
│ ├── kafka/
|
|
│ │ ├── AIJobKafkaProducer.java
|
|
│ │ ├── AIJobKafkaConsumer.java
|
|
│ │ ├── ImageJobKafkaConsumer.java
|
|
│ │ └── EventKafkaProducer.java
|
|
│ ├── client/
|
|
│ │ └── ContentServiceClient.java (Feign)
|
|
│ ├── client.dto/
|
|
│ │ ├── ContentImageGenerationRequest.java
|
|
│ │ └── ContentJobResponse.java
|
|
│ └── config/
|
|
│ └── RedisConfig.java
|
|
├── presentation/
|
|
│ └── controller/
|
|
│ ├── EventController.java
|
|
│ └── JobController.java
|
|
└── config/
|
|
├── SecurityConfig.java
|
|
├── KafkaConfig.java
|
|
└── DevAuthenticationFilter.java
|
|
```
|
|
|
|
---
|
|
|
|
## 6. 의존성 방향
|
|
|
|
### 6.1 Clean Architecture 계층
|
|
|
|
```
|
|
Presentation Layer (EventController)
|
|
↓ depends on
|
|
Application Layer (EventService)
|
|
↓ depends on
|
|
Domain Layer (Event, EventRepository)
|
|
↑ implements
|
|
Infrastructure Layer (EventRepositoryImpl, Kafka, Feign)
|
|
```
|
|
|
|
### 6.2 핵심 원칙
|
|
1. **Domain Layer는 외부 의존성 없음** (순수 비즈니스 로직)
|
|
2. **Application Layer는 Domain을 조율** (유스케이스)
|
|
3. **Infrastructure Layer는 Domain 인터페이스 구현** (기술 세부사항)
|
|
4. **Presentation Layer는 Application 호출** (API 엔드포인트)
|
|
|
|
---
|
|
|
|
## 7. 주요 설계 패턴
|
|
|
|
### 7.1 Domain 패턴
|
|
- **Aggregate Root**: Event (경계 내 일관성 보장)
|
|
- **State Machine**: EventStatus, JobStatus (상태 전이 제약)
|
|
- **Value Object**: StoreInfo, Customizations (불변 값)
|
|
|
|
### 7.2 Application 패턴
|
|
- **Service Layer**: EventService, JobService (유스케이스 조율)
|
|
- **DTO Pattern**: Request/Response 분리 (계층 간 데이터 전송)
|
|
- **Repository Pattern**: EventRepository (영속성 추상화)
|
|
|
|
### 7.3 Infrastructure 패턴
|
|
- **Adapter Pattern**: ContentServiceClient (외부 서비스 연동)
|
|
- **Producer/Consumer**: Kafka 메시징 (비동기 통신)
|
|
- **Cache-Aside**: Redis 캐싱 (성능 최적화)
|
|
|
|
---
|
|
|
|
## 8. 트랜잭션 경계
|
|
|
|
### 8.1 @Transactional 적용 위치
|
|
```java
|
|
EventService:
|
|
- createEvent() - 쓰기
|
|
- deleteEvent() - 쓰기
|
|
- publishEvent() - 쓰기
|
|
- endEvent() - 쓰기
|
|
- updateEvent() - 쓰기
|
|
- requestAiRecommendations() - 쓰기 (Job 생성)
|
|
- selectRecommendation() - 쓰기
|
|
- selectImage() - 쓰기
|
|
- selectChannels() - 쓰기
|
|
|
|
JobService:
|
|
- createJob() - 쓰기
|
|
- updateJobProgress() - 쓰기
|
|
- completeJob() - 쓰기
|
|
- failJob() - 쓰기
|
|
```
|
|
|
|
### 8.2 읽기 전용 트랜잭션
|
|
```java
|
|
@Transactional(readOnly = true):
|
|
- getEvent()
|
|
- getEvents()
|
|
- getJobStatus()
|
|
```
|
|
|
|
---
|
|
|
|
## 9. 보안 및 인증
|
|
|
|
### 9.1 인증 방식
|
|
- **개발 환경**: DevAuthenticationFilter (Header 기반)
|
|
- **운영 환경**: JWT 인증 (JwtAuthenticationFilter)
|
|
|
|
### 9.2 인가 처리
|
|
```java
|
|
@AuthenticationPrincipal UserPrincipal
|
|
- userId: 요청자 ID
|
|
- storeId: 매장 ID
|
|
|
|
검증:
|
|
- Event는 userId로 소유권 확인
|
|
- EventRepository.findByEventIdAndUserId() 사용
|
|
```
|
|
|
|
---
|
|
|
|
## 10. 에러 처리
|
|
|
|
### 10.1 공통 에러 코드
|
|
```java
|
|
ErrorCode:
|
|
- EVENT_001: 이벤트를 찾을 수 없음
|
|
- EVENT_002: 이벤트 수정/삭제 불가 (상태 제약)
|
|
- EVENT_003: 선택한 리소스를 찾을 수 없음
|
|
- JOB_001: 작업을 찾을 수 없음
|
|
- JOB_002: 작업 상태 변경 불가
|
|
```
|
|
|
|
### 10.2 예외 처리
|
|
```java
|
|
Domain Layer:
|
|
- IllegalStateException (상태 전이 제약 위반)
|
|
- IllegalArgumentException (비즈니스 규칙 위반)
|
|
|
|
Application Layer:
|
|
- BusinessException (비즈니스 로직 에러)
|
|
|
|
Infrastructure Layer:
|
|
- InfraException (외부 시스템 에러)
|
|
```
|
|
|
|
---
|
|
|
|
## 11. 테스트 전략
|
|
|
|
### 11.1 단위 테스트
|
|
```java
|
|
Domain Layer:
|
|
- Event 상태 전이 로직
|
|
- 비즈니스 규칙 검증
|
|
|
|
Application Layer:
|
|
- EventService 유스케이스
|
|
- DTO 변환 로직
|
|
```
|
|
|
|
### 11.2 통합 테스트
|
|
```java
|
|
Infrastructure Layer:
|
|
- Kafka Producer/Consumer
|
|
- Feign Client
|
|
- Redis 캐싱
|
|
|
|
Presentation Layer:
|
|
- REST API 엔드포인트
|
|
- 인증/인가
|
|
```
|
|
|
|
---
|
|
|
|
## 12. 파일 정보
|
|
|
|
### 12.1 다이어그램 파일
|
|
- **상세 다이어그램**: `design/backend/class/event-service.puml`
|
|
- **요약 다이어그램**: `design/backend/class/event-service-simple.puml`
|
|
|
|
### 12.2 참조 문서
|
|
- 공통 컴포넌트: `design/backend/class/common-base.puml`
|
|
- API 설계서: `design/backend/api/spec/event-service-api.yaml`
|
|
- 데이터 설계서: `design/backend/database/event-service-schema.sql`
|
|
|
|
---
|
|
|
|
**작성일**: 2025-10-29
|
|
**작성자**: Backend Architect (Claude Code)
|
|
**버전**: 1.0.0
|