From fb55fd85a0a7a2ac06654dd74c9c972768956cfb Mon Sep 17 00:00:00 2001 From: cherry2250 Date: Thu, 23 Oct 2025 14:22:56 +0900 Subject: [PATCH] =?UTF-8?q?=EB=85=BC=EB=A6=AC=20=EC=95=84=ED=82=A4?= =?UTF-8?q?=ED=85=8D=EC=B2=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 주요 변경사항: - User Service 사업자번호 검증 로직 삭제 (국세청 API 제거) - User Service → Event Service 회원정보 제공 API 추가 - Redis 기반 서비스 간 데이터 공유 구조로 변경 - AI Service → Redis 저장 → Content Service 읽기 - Participation Service 참여자 목록 조회 기능 추가 - WinnerSelected 이벤트 토픽 제거 (3개 토픽으로 축소) - Redis → Event DB 저장 로직 추가 (이벤트 publish 시) - AI/Content Service Timeout 5분으로 변경 (30초/20초 → 300초) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- .../backend/logical/logical-architecture.md | 87 ++++++++----------- .../backend/logical/logical-architecture.mmd | 30 ++++--- 2 files changed, 56 insertions(+), 61 deletions(-) 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