diff --git a/design/backend/logical/logical-architecture.md b/design/backend/logical/logical-architecture.md
index ed517f9..949ef44 100644
--- a/design/backend/logical/logical-architecture.md
+++ b/design/backend/logical/logical-architecture.md
@@ -65,7 +65,7 @@
1. **User Service**: 사용자 인증 및 매장정보 관리
- 회원가입/로그인 (JWT 발급)
- 프로필 CRUD
- - 사업자번호 검증 (국세청 API, Circuit Breaker)
+ - Event Service로 회원정보 제공
2. **Event Service**: 이벤트 전체 생명주기 관리
- 이벤트 생성/수정/삭제/조회
@@ -78,7 +78,7 @@
- 참여 접수 및 중복 체크
- 참여자 목록 조회
- 당첨자 추첨 및 조회
- - Kafka Event 발행 (ParticipantRegistered, WinnerSelected)
+ - Kafka Event 발행 (ParticipantRegistered)
4. **Analytics Service**: 실시간 성과 분석 및 대시보드
- 대시보드 데이터 조회 (Redis 캐싱)
@@ -89,13 +89,13 @@
#### Async Services (비동기 처리)
1. **AI Service**: AI 기반 이벤트 추천
- Kafka Job 구독 (ai 이벤트 생성)
- - 외부 AI API 호출 (Circuit Breaker, Timeout 30초)
- - 결과 캐싱 (Redis, TTL 24시간)
+ - 외부 AI API 호출 (Circuit Breaker, Timeout 5분)
+ - 결과 Redis 저장 (TTL 24시간)
2. **Content Service**: SNS 이미지 생성
- - Kafka Job 구독 (이미지 생성)
- - 외부 이미지 생성 API 호출 (Circuit Breaker, Timeout 20초)
- - CDN 업로드 및 캐싱 (Redis, TTL 7일)
+ - Redis에서 AI 데이터 읽기
+ - 외부 이미지 생성 API 호출 (Circuit Breaker, Timeout 5분)
+ - 생성된 이미지 Redis 저장 (CDN URL, TTL 7일)
3. **Distribution Service**: 다중 채널 배포 (동기)
- REST API 제공 (Event Service에서 호출)
@@ -106,7 +106,6 @@
**Event Topics** (도메인 이벤트):
- **EventCreated**: 이벤트 생성 시
- **ParticipantRegistered**: 참여자 등록 시
-- **WinnerSelected**: 당첨자 선정 시
- **DistributionCompleted**: 배포 완료 시
**Job Topics** (비동기 작업):
@@ -124,7 +123,6 @@
- User DB, Event DB, Participation DB, Analytics DB
#### External Systems
-- **국세청 API**: 사업자번호 검증
- **AI APIs**: Claude/GPT-4 (트렌드 분석)
- **이미지 생성 APIs**: Stable Diffusion/DALL-E
- **배포 채널 APIs**: 우리동네TV, 링고비즈, 지니TV, SNS APIs (비동기 배포)
@@ -139,20 +137,17 @@
**핵심 책임**:
- 회원가입/로그인 (JWT 토큰 발급)
- 프로필 CRUD (매장 정보 포함)
-- 사업자번호 검증 (국세청 API 연동)
- 세션 관리
+- Event Service로 회원정보 제공
**관련 유저스토리**: UFR-USER-010, 020, 030, 040
-**Resilience 패턴**:
-- **Circuit Breaker**: 국세청 API 호출 시 (실패율 50% 초과 시 Open)
-- **Retry**: 최대 3회 재시도 (지수 백오프: 1초, 2초, 4초)
-- **Timeout**: 5초
-- **Fallback**: 사업자번호 검증 스킵 (수동 확인 안내)
+**서비스 간 호출**:
+- **Event Service**: 회원정보 조회 API 제공 (매장 정보 포함)
**데이터 저장**:
- User DB: users, stores 테이블
-- Redis: 세션 정보 (TTL 7일), 사업자번호 검증 결과 (TTL 7일)
+- Redis: 세션 정보 (TTL 7일)
#### Event Service
**핵심 책임**:
@@ -189,7 +184,7 @@
- 이벤트 참여 접수 및 검증
- 참여자 목록 조회
- 당첨자 추첨 및 조회
-- Kafka Event 발행 (ParticipantRegistered, WinnerSelected)
+- Kafka Event 발행 (ParticipantRegistered)
**관련 유저스토리**: UFR-PART-010, 020, 030
@@ -198,14 +193,12 @@
- Payload: participantId, eventId, phoneNumber, registeredAt
- 구독자: Analytics Service
-2. **WinnerSelected**: 당첨자 선정 시
- - Payload: winnerId, eventId, selectedAt
- - 구독자: (추후 확장 가능)
-
**주요 기능**:
- 중복 참여 체크 (전화번호 기반)
+- 참여자 목록 조회 (페이지네이션 지원)
- 난수 기반 무작위 추첨
- 매장 방문 고객 가산점 적용
+- 당첨자 조회
**데이터 저장**:
- Participation DB: participants, winners 테이블
@@ -252,13 +245,13 @@
**Resilience 패턴**:
- **Circuit Breaker**: AI API 호출 시 (실패율 50% 초과 시 Open)
-- **Timeout**: 30초
+- **Timeout**: 5분 (300초)
- **Fallback**: 캐시된 이전 추천 결과 + 안내 메시지
- **Cache-Aside**: Redis 캐싱 (TTL 24시간)
**처리 시간**:
- 캐시 HIT: 0.1초
-- 캐시 MISS: 10초 이내 (비동기 처리)
+- 캐시 MISS: 5분 이내 (비동기 처리)
**데이터 저장**:
- Redis: AI 추천 결과 (TTL 24시간)
@@ -272,18 +265,18 @@
**관련 유저스토리**: UFR-CONT-010, 020
-**Kafka Job 구독**:
-- **이미지 생성**: 이미지 생성 작업 요청
+**데이터 읽기**:
+- Redis에서 AI Service가 저장한 이벤트 데이터 읽기
**Resilience 패턴**:
- **Circuit Breaker**: 이미지 생성 API 호출 시 (실패율 50% 초과 시 Open)
-- **Timeout**: 20초
+- **Timeout**: 5분 (300초)
- **Fallback**: 기본 템플릿 이미지 제공
- **Cache-Aside**: Redis 캐싱 (TTL 7일)
**처리 시간**:
- 캐시 HIT: 0.1초
-- 캐시 MISS: 5초 이내 (비동기 처리)
+- 캐시 MISS: 5분 이내 (비동기 처리)
**데이터 저장**:
- Redis: 이미지 생성 결과 (CDN URL, TTL 7일)
@@ -335,7 +328,6 @@
|---------|--------|--------|---------|------|
| **EventCreated** | Event Service | Analytics Service | eventId, storeId, title, objective, createdAt | 이벤트 생성 시 통계 초기화 |
| **ParticipantRegistered** | Participation Service | Analytics Service | participantId, eventId, phoneNumber, registeredAt | 참여자 등록 시 실시간 통계 업데이트 |
-| **WinnerSelected** | Participation Service | - | winnerId, eventId, selectedAt | 당첨자 선정 기록 |
| **DistributionCompleted** | Distribution Service | Analytics Service | eventId, distributedChannels, completedAt | 배포 완료 시 통계 업데이트 |
#### Job Topics (비동기 작업)
@@ -429,9 +421,8 @@
- **설정**:
| 서비스 | Timeout | 이유 |
|--------|---------|------|
- | User Service (국세청 API) | 5초 | 빠른 검증 필요 |
- | AI Service (AI API) | 30초 | 복잡한 분석 작업 |
- | Content Service (이미지 API) | 20초 | 이미지 생성 시간 고려 |
+ | AI Service (AI API) | 5분 (300초) | 복잡한 분석 작업 |
+ | Content Service (이미지 API) | 5분 (300초) | 이미지 생성 시간 고려 |
| Distribution Service (채널 APIs) | 10초 | 빠른 배포 필요 |
**4. Bulkhead 패턴**
@@ -449,7 +440,6 @@
- **전략**:
| 서비스 | Fallback 전략 |
|--------|---------------|
- | User Service | 사업자번호 검증 스킵 (수동 확인 안내) |
| AI Service | 캐시된 이전 추천 결과 + 안내 메시지 |
| Content Service | 기본 템플릿 이미지 제공 |
| Distribution Service | 실패 채널 스킵 + 알림 |
@@ -497,8 +487,8 @@
│ AI Service (Background) │
│ - Kafka ai 이벤트 생성 토픽 구독 │
│ - Redis 캐시 확인 (Cache-Aside) │
- │ - 캐시 MISS: Claude API 호출 (10초) [Circuit Breaker] │
- │ - 결과 캐싱 (TTL 24시간) │
+ │ - 캐시 MISS: Claude API 호출 (5분) [Circuit Breaker] │
+ │ - AI 추천 결과를 Redis에 저장 (TTL 24시간) │
│ - Job 상태 완료로 업데이트 │
└─────────────────────────────────────────────────────────────┘
@@ -509,20 +499,13 @@
└─────────────────────────────────────────────────────────────┘
3. [SNS 이미지 생성]
- ┌─────────────────────────────────────────────────────────────┐
- │ Client → Event Service │
- │ - POST /api/events/{id}/content-generation │
- │ - Kafka 이미지 생성 토픽 발행 (이미지 생성 요청) │
- │ - Job ID 즉시 반환 (0.1초) │
- └─────────────────────────────────────────────────────────────┘
-
┌─────────────────────────────────────────────────────────────┐
│ Content Service (Background) │
- │ - Kafka 이미지 생성 토픽 구독 │
- │ - Redis 캐시 확인 │
- │ - 캐시 MISS: Stable Diffusion API (5초) [Circuit Breaker] │
+ │ - Redis에서 AI Service가 저장한 이벤트 데이터 읽기 │
+ │ - Redis 캐시 확인 (이미지 생성 여부) │
+ │ - 캐시 MISS: Stable Diffusion API (5분) [Circuit Breaker] │
│ - 이미지 CDN 업로드 │
- │ - CDN URL 캐싱 (TTL 7일) │
+ │ - 생성된 이미지 URL을 Redis에 저장 (TTL 7일) │
│ - Job 상태 완료로 업데이트 │
└─────────────────────────────────────────────────────────────┘
@@ -536,6 +519,8 @@
┌─────────────────────────────────────────────────────────────┐
│ Client → Event Service │
│ - POST /api/events/{id}/publish │
+ │ - Redis의 이벤트 관련 정보(AI 추천, 이미지 URL)를 조회 │
+ │ - Event DB에 이벤트 정보 저장 │
│ - Event 상태 변경 (DRAFT → PUBLISHED) │
└─────────────────────────────────────────────────────────────┘
@@ -591,7 +576,6 @@
│ - POST /api/events/{id}/draw-winners │
│ - 난수 기반 무작위 추첨 │
│ - Winners DB에 저장 │
- │ - WinnerSelected 이벤트 발행 → Kafka │
└─────────────────────────────────────────────────────────────┘
```
@@ -679,8 +663,8 @@
| 서비스 | 캐시 키 패턴 | 데이터 타입 | TTL | 예상 크기 | 히트율 목표 |
|--------|-------------|-----------|-----|----------|-----------|
| User | `user:session:{token}` | String | 7일 | 1KB | - |
-| User | `user:business:{사업자번호}` | String | 7일 | 0.5KB | 90% |
| AI | `ai:recommendation:{업종}:{지역}:{목적}` | Hash | 24시간 | 10KB | 80% |
+| AI | `ai:event:{이벤트ID}` | Hash | 24시간 | 10KB | - |
| Content | `content:image:{이벤트ID}:{스타일}` | String | 7일 | 0.2KB (URL) | 80% |
| Analytics | `analytics:dashboard:{이벤트ID}` | Hash | 5분 | 5KB | 95% |
| AI | `job:{jobId}` | Hash | 1시간 | 1KB | - |
@@ -857,13 +841,16 @@
### B. 주요 결정사항
1. **Kafka 통합 메시징 플랫폼 채택**: Event Bus와 Job Queue를 Kafka로 통합하여 운영 복잡도 감소
2. **Event-Driven 아키텍처 채택**: Kafka를 통한 서비스 간 느슨한 결합 및 비동기 통신
-3. **도메인 이벤트 정의**: 4개 Event Topics (EventCreated, ParticipantRegistered, WinnerSelected, DistributionCompleted)
+3. **도메인 이벤트 정의**: 3개 Event Topics (EventCreated, ParticipantRegistered, DistributionCompleted)
4. **Job Topics 정의**: 2개 Job Topics (ai 이벤트 생성, 이미지 생성)로 장시간 비동기 작업 처리
5. **Resilience 패턴 전면 적용**: Circuit Breaker, Retry, Timeout, Bulkhead, Fallback
6. **At-Least-Once Delivery**: Kafka 메시지 보장 및 멱등성 설계
7. **Cache-Aside 패턴**: AI/이미지 생성 결과 캐싱으로 응답 시간 90% 개선
-8. **동기 배포**: Event Service가 Distribution Service를 REST API로 직접 호출하여 다중 채널 배포 동기 처리
-9. **서비스별 독립 Database**: Database-per-Service 패턴으로 서비스 독립성 보장
+8. **Redis 기반 서비스 간 데이터 공유**: AI Service → Redis → Content Service 데이터 흐름
+9. **Redis to DB 영구 저장**: 이벤트 생성 완료 시 Redis 데이터를 Event DB에 저장
+10. **동기 배포**: Event Service가 Distribution Service를 REST API로 직접 호출하여 다중 채널 배포 동기 처리
+11. **서비스별 독립 Database**: Database-per-Service 패턴으로 서비스 독립성 보장
+12. **장시간 작업 Timeout 조정**: AI/Content Service Timeout을 5분으로 설정하여 복잡한 생성 작업 지원
### C. 향후 개선 방안 (Phase 2 이후)
1. **Event Sourcing 완전 적용**: 모든 상태 변경을 이벤트로 저장하여 시간 여행 및 감사 추적 강화
diff --git a/design/backend/logical/logical-architecture.mmd b/design/backend/logical/logical-architecture.mmd
index e93b0e6..d84f619 100644
--- a/design/backend/logical/logical-architecture.mmd
+++ b/design/backend/logical/logical-architecture.mmd
@@ -3,34 +3,35 @@ graph TB
%% Services
subgraph "Services"
- UserSvc["User Service
• 회원가입/로그인
• 프로필 관리
• 사업자번호 검증
[Circuit Breaker]"]
- EventSvc["Event Service
• 이벤트 생성/수정/삭제
• 플로우 오케스트레이션
• AI/이미지 작업 요청
• 배포 작업 요청"]
- PartSvc["Participation
Service
• 참여 접수
• 당첨자 추첨"]
+ UserSvc["User Service
• 회원가입/로그인
• 프로필 관리
• 회원정보 제공"]
+ EventSvc["Event Service
• 이벤트 생성/수정/삭제
• 플로우 오케스트레이션
• AI 작업 요청
• 배포 작업 요청
• Redis → DB 저장"]
+ PartSvc["Participation
Service
• 참여 접수
• 참여자 목록
• 당첨자 추첨"]
AnalSvc["Analytics Service
• 실시간 대시보드
• 성과 분석
• 채널별 통계
[Circuit Breaker]"]
end
%% Async Services
subgraph "Async Services"
- AISvc["AI Service
• 트렌드 분석
• 이벤트 추천
[Circuit Breaker]
[Timeout: 30s]"]
- ContentSvc["Content Service
• SNS 이미지 생성
• 3가지 스타일
[Circuit Breaker]
[Timeout: 20s]"]
+ AISvc["AI Service
• 트렌드 분석
• 이벤트 추천
• Redis 저장
[Circuit Breaker]
[Timeout: 5분]"]
+ ContentSvc["Content Service
• Redis 데이터 읽기
• SNS 이미지 생성
• Redis 저장
[Circuit Breaker]
[Timeout: 5분]"]
DistSvc["Distribution
Service
• 다중 채널 배포
[Circuit Breaker]
[Retry: 3회]
[Bulkhead]"]
end
%% Kafka (Event Bus + Job Queue)
- Kafka["Kafka
━━━━━━━━━━
• EventCreated
• ParticipantRegistered
• WinnerSelected
• DistributionCompleted
━━━━━━━━━━
• ai 이벤트 생성
• 이미지 생성"]
+ Kafka["Kafka
━━━━━━━━━━
• EventCreated
• ParticipantRegistered
• DistributionCompleted
━━━━━━━━━━
• ai 이벤트 생성"]
%% External System
- External["외부시스템
[Circuit Breaker]
━━━━━━━━━━
• 국세청 API
• AI API
• 이미지 생성 API
• 배포 채널 APIs
(비동기)"]
+ External["외부시스템
[Circuit Breaker]
━━━━━━━━━━
• AI API
• 이미지 생성 API
• 배포 채널 APIs
(비동기)"]
+
+ %% Redis
+ Redis["Redis Cache
━━━━━━━━━━
• AI 결과
• 이미지 URL
• 이벤트 데이터"]
%% Event Publishing
EventSvc ==>|"EventCreated
발행"| Kafka
PartSvc ==>|"ParticipantRegistered
발행"| Kafka
- PartSvc ==>|"WinnerSelected
발행"| Kafka
DistSvc ==>|"DistributionCompleted
발행"| Kafka
%% Job Publishing (비동기 작업 요청)
EventSvc -->|"ai 이벤트 생성 발행"| Kafka
- EventSvc -->|"이미지 생성 발행"| Kafka
%% Event Subscription
Kafka -.->|"EventCreated
구독"| AnalSvc
@@ -39,13 +40,18 @@ graph TB
%% Job Subscription
Kafka -.->|"ai 이벤트 생성 구독"| AISvc
- Kafka -.->|"이미지 생성 구독"| ContentSvc
%% Service to Service (동기 호출)
EventSvc -->|"다중 채널 배포
[Circuit Breaker]"| DistSvc
+ EventSvc -->|"회원정보 조회"| UserSvc
+
+ %% Redis Interactions
+ AISvc -->|"AI 결과 저장"| Redis
+ ContentSvc -->|"AI 데이터 읽기"| Redis
+ ContentSvc -->|"이미지 URL 저장"| Redis
+ EventSvc -->|"Redis → DB 저장"| Redis
%% Services to External (Resilience 패턴)
- UserSvc -->|"사업자번호 검증
[Retry: 3회]"| External
AISvc -->|"트렌드 분석/추천"| External
ContentSvc -->|"이미지 생성"| External
DistSvc -->|"다중 채널 배포
(비동기)"| External
@@ -56,8 +62,10 @@ graph TB
classDef async fill:#8B5CF6,stroke:#7C3AED,stroke-width:3px,color:#fff
classDef kafka fill:#F59E0B,stroke:#D97706,stroke-width:3px
classDef external fill:#E5E7EB,stroke:#9CA3AF,stroke-width:2px
+ classDef cache fill:#EF4444,stroke:#DC2626,stroke-width:3px
class UserSvc,EventSvc,PartSvc,AnalSvc service
class AISvc,ContentSvc,DistSvc async
class Kafka kafka
class External external
+ class Redis cache