주요 변경사항: - 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 <noreply@anthropic.com>
40 KiB
KT AI 기반 소상공인 이벤트 자동 생성 서비스 - 논리 아키텍처
문서 정보
- 작성일: 2025-10-21
- 최종 수정일: 2025-10-22
- 버전: 2.0 (CQRS + Event-Driven 전환)
- 작성자: System Architect
- 관련 문서:
버전 이력
- v1.0 (2025-10-21): 초기 마이크로서비스 아키텍처 설계
- v2.0 (2025-10-22): CQRS 패턴 및 Event-Driven 아키텍처 전환, Resilience 패턴 전면 적용
- v2.1 (2025-10-22): 서비스 구조 간소화, Kafka 통합 (Event Bus + Job Queue), Distribution 비동기 처리
- v2.2 (2025-10-22): Distribution Service 동기 호출 전환 (REST API 직접 호출)
목차
1. 개요
1.1 설계 원칙
본 논리 아키텍처는 다음 원칙을 기반으로 설계되었습니다:
유저스토리 기반 설계
- 20개 유저스토리와 정확히 매칭
- 불필요한 추가 기능 배제
- 비즈니스 요구사항 우선 반영
Event-Driven 아키텍처
- Kafka 기반 통합: Event Bus와 Job Queue를 Kafka로 통합
- 비동기 메시징: Kafka Topics를 통한 서비스 간 통신
- 느슨한 결합: 서비스 간 직접 의존성 제거
- 확장성: 이벤트 구독자 추가로 기능 확장 용이
- 장애 격리: 이벤트 발행/구독 실패 시 서비스 독립성 유지
Kafka 통합 전략
- Event Topics: 도메인 이벤트 발행/구독 (EventCreated, ParticipantRegistered 등)
- Job Topics: 비동기 작업 요청/처리 (ai 이벤트 생성, 이미지 생성)
- 단일 메시징 플랫폼: 운영 복잡도 감소 및 일관된 메시지 처리
Resilience 패턴 적용
- Circuit Breaker: 외부 API 장애 시 빠른 실패 및 복구 (Hystrix/Resilience4j)
- Retry Pattern: 일시적 장애 시 자동 재시도 (지수 백오프)
- Timeout Pattern: 응답 시간 제한으로 리소스 점유 방지
- Bulkhead Pattern: 리소스 격리로 장애 전파 차단
- Fallback Pattern: 장애 시 대체 로직 실행 (캐시 응답 등)
1.2 핵심 컴포넌트 정의
Core Services
-
User Service: 사용자 인증 및 매장정보 관리
- 회원가입/로그인 (JWT 발급)
- 프로필 CRUD
- Event Service로 회원정보 제공
-
Event Service: 이벤트 전체 생명주기 관리
- 이벤트 생성/수정/삭제/조회
- 이벤트 생성 플로우 오케스트레이션
- Kafka Job 발행 (AI, 이미지)
- Distribution Service 동기 호출 (배포)
- Kafka Event 발행 (EventCreated)
-
Participation Service: 참여 및 당첨자 관리
- 참여 접수 및 중복 체크
- 참여자 목록 조회
- 당첨자 추첨 및 조회
- Kafka Event 발행 (ParticipantRegistered)
-
Analytics Service: 실시간 성과 분석 및 대시보드
- 대시보드 데이터 조회 (Redis 캐싱)
- Kafka Event 구독 (EventCreated, ParticipantRegistered, DistributionCompleted)
- 외부 채널 통계 수집 (Circuit Breaker + Fallback)
- ROI 계산 및 성과 분석
Async Services (비동기 처리)
-
AI Service: AI 기반 이벤트 추천
- Kafka Job 구독 (ai 이벤트 생성)
- 외부 AI API 호출 (Circuit Breaker, Timeout 5분)
- 결과 Redis 저장 (TTL 24시간)
-
Content Service: SNS 이미지 생성
- Redis에서 AI 데이터 읽기
- 외부 이미지 생성 API 호출 (Circuit Breaker, Timeout 5분)
- 생성된 이미지 Redis 저장 (CDN URL, TTL 7일)
-
Distribution Service: 다중 채널 배포 (동기)
- REST API 제공 (Event Service에서 호출)
- 병렬 배포 (Circuit Breaker, Retry, Bulkhead)
- Kafka Event 발행 (DistributionCompleted)
Kafka (통합 메시징 플랫폼)
Event Topics (도메인 이벤트):
- EventCreated: 이벤트 생성 시
- ParticipantRegistered: 참여자 등록 시
- DistributionCompleted: 배포 완료 시
Job Topics (비동기 작업):
- ai 이벤트 생성: AI 추천 작업
- 이미지 생성: 이미지 생성 작업
특징:
- At-Least-Once Delivery 보장
- Partition Key 기반 순서 보장
- Dead Letter Queue 지원
Data Layer
- Redis Cache: 세션, AI 결과, 이미지 URL, 대시보드 캐싱
- PostgreSQL: 서비스별 독립 데이터베이스
- User DB, Event DB, Participation DB, Analytics DB
External Systems
- AI APIs: Claude/GPT-4 (트렌드 분석)
- 이미지 생성 APIs: Stable Diffusion/DALL-E
- 배포 채널 APIs: 우리동네TV, 링고비즈, 지니TV, SNS APIs (비동기 배포)
2. 서비스 아키텍처
2.1 서비스별 책임
User Service
핵심 책임:
- 회원가입/로그인 (JWT 토큰 발급)
- 프로필 CRUD (매장 정보 포함)
- 세션 관리
- Event Service로 회원정보 제공
관련 유저스토리: UFR-USER-010, 020, 030, 040
서비스 간 호출:
- Event Service: 회원정보 조회 API 제공 (매장 정보 포함)
데이터 저장:
- User DB: users, stores 테이블
- Redis: 세션 정보 (TTL 7일)
Event Service
핵심 책임:
- 이벤트 생성/수정/삭제/조회
- 이벤트 생성 플로우 오케스트레이션
- Kafka Job 발행 (AI, 이미지, 배포)
- Kafka Event 발행 (EventCreated)
관련 유저스토리: UFR-EVENT-010, 020, 030, 040, 050, 060, 070
Kafka 이벤트 발행:
- EventCreated: 이벤트 생성 완료 시
- Payload: eventId, storeId, title, objective, createdAt
- 구독자: Analytics Service
Kafka Job 발행:
- ai 이벤트 생성: AI 추천 요청
- 이미지 생성: 이미지 생성 요청
서비스 간 호출:
- Distribution Service: 다중 채널 배포 (동기 호출, Circuit Breaker 적용)
주요 플로우:
- 이벤트 목적 선택 → Event DB 저장 → EventCreated 발행
- AI 추천 요청 → ai 이벤트 생성 발행
- 이미지 생성 요청 → 이미지 생성 발행
- 배포 승인 → Distribution Service 동기 호출
데이터 저장:
- Event DB: events, event_objectives, event_prizes 테이블
Participation Service
핵심 책임:
- 이벤트 참여 접수 및 검증
- 참여자 목록 조회
- 당첨자 추첨 및 조회
- Kafka Event 발행 (ParticipantRegistered)
관련 유저스토리: UFR-PART-010, 020, 030
Kafka 이벤트 발행:
- ParticipantRegistered: 참여자 등록 시
- Payload: participantId, eventId, phoneNumber, registeredAt
- 구독자: Analytics Service
주요 기능:
- 중복 참여 체크 (전화번호 기반)
- 참여자 목록 조회 (페이지네이션 지원)
- 난수 기반 무작위 추첨
- 매장 방문 고객 가산점 적용
- 당첨자 조회
데이터 저장:
- Participation DB: participants, winners 테이블
Analytics Service
핵심 책임:
- 실시간 성과 대시보드 조회
- 채널별 성과 분석 및 통계
- ROI 계산 및 성과 집계
관련 유저스토리: UFR-ANAL-010
Kafka 이벤트 구독:
- EventCreated: 이벤트 기본 정보 초기화
- ParticipantRegistered: 참여자 수 실시간 증가
- DistributionCompleted: 배포 완료 통계 업데이트
Resilience 패턴:
- Circuit Breaker: 외부 채널 API 조회 시 (실패율 50% 초과 시 Open)
- Fallback: 캐시된 이전 데이터 반환
- Cache-Aside: Redis 캐싱 (TTL 5분)
데이터 통합:
- Event Service: 이벤트 정보 조회 (DB 직접 또는 REST)
- Participation Service: 참여자/당첨자 데이터 조회
- 외부 APIs: 우리동네TV, 지니TV, SNS 통계 수집
데이터 저장:
- Analytics DB: event_stats, channel_stats
- Redis: 대시보드 데이터 (TTL 5분)
2.2 Async Services (비동기 처리)
AI Service
핵심 책임:
- 업종/지역/시즌 트렌드 분석
- 3가지 이벤트 기획안 자동 생성
- 예상 성과 계산
관련 유저스토리: UFR-AI-010
Kafka Job 구독:
- ai 이벤트 생성: AI 추천 작업 요청
Resilience 패턴:
- Circuit Breaker: AI API 호출 시 (실패율 50% 초과 시 Open)
- Timeout: 5분 (300초)
- Fallback: 캐시된 이전 추천 결과 + 안내 메시지
- Cache-Aside: Redis 캐싱 (TTL 24시간)
처리 시간:
- 캐시 HIT: 0.1초
- 캐시 MISS: 5분 이내 (비동기 처리)
데이터 저장:
- Redis: AI 추천 결과 (TTL 24시간)
- Redis: Job 상태 정보 (TTL 1시간)
Content Service
핵심 책임:
- 3가지 스타일 SNS 이미지 자동 생성
- 플랫폼별 이미지 최적화
- 이미지 편집 기능
관련 유저스토리: UFR-CONT-010, 020
데이터 읽기:
- Redis에서 AI Service가 저장한 이벤트 데이터 읽기
Resilience 패턴:
- Circuit Breaker: 이미지 생성 API 호출 시 (실패율 50% 초과 시 Open)
- Timeout: 5분 (300초)
- Fallback: 기본 템플릿 이미지 제공
- Cache-Aside: Redis 캐싱 (TTL 7일)
처리 시간:
- 캐시 HIT: 0.1초
- 캐시 MISS: 5분 이내 (비동기 처리)
데이터 저장:
- Redis: 이미지 생성 결과 (CDN URL, TTL 7일)
- CDN: 생성된 이미지 파일
Distribution Service
핵심 책임:
- 다중 채널 병렬 배포 (동기)
- 배포 상태 모니터링
- Kafka Event 발행 (DistributionCompleted)
관련 유저스토리: UFR-DIST-010, 020
주요 API:
POST /api/distribution/distribute: 다중 채널 배포 요청 (Event Service에서 호출)
Kafka 이벤트 발행:
- DistributionCompleted: 배포 완료 시
- Payload: eventId, distributedChannels, completedAt
- 구독자: Analytics Service
Resilience 패턴:
- Circuit Breaker: 각 외부 채널 API별 독립 적용 (실패율 50% 초과 시 Open)
- Retry: 최대 3회 재시도 (지수 백오프: 1초, 2초, 4초)
- Bulkhead: 채널별 스레드 풀 격리 (장애 전파 방지)
- Fallback: 실패 채널 스킵 + 알림
처리 시간: 1분 이내 (모든 채널 배포 완료)
배포 채널:
- 우리동네TV API (영상 업로드)
- 링고비즈 API (연결음 업데이트)
- 지니TV API (TV 광고 등록)
- SNS APIs (Instagram, Naver, Kakao 자동 포스팅)
데이터 저장:
- Event DB: distribution_logs 테이블
2.3 Kafka 통신 전략
Kafka 아키텍처
기술 스택: Apache Kafka (Event Topics + Job Topics 통합) 보장 수준: At-Least-Once Delivery 메시지 포맷: JSON
Event Topics (도메인 이벤트)
| 토픽명 | 발행자 | 구독자 | Payload | 용도 |
|---|---|---|---|---|
| EventCreated | Event Service | Analytics Service | eventId, storeId, title, objective, createdAt | 이벤트 생성 시 통계 초기화 |
| ParticipantRegistered | Participation Service | Analytics Service | participantId, eventId, phoneNumber, registeredAt | 참여자 등록 시 실시간 통계 업데이트 |
| DistributionCompleted | Distribution Service | Analytics Service | eventId, distributedChannels, completedAt | 배포 완료 시 통계 업데이트 |
Job Topics (비동기 작업)
| 토픽명 | 발행자 | 구독자 | Payload | 용도 |
|---|---|---|---|---|
| ai 이벤트 생성 | Event Service | AI Service | eventId, objective, industry, region | AI 트렌드 분석 및 이벤트 추천 요청 |
| 이미지 생성 | Event Service | Content Service | eventId, content, style | SNS 이미지 생성 요청 (3가지 스타일) |
통신 패턴별 설계
1. Event Topics (도메인 이벤트)
- 사용 시나리오: 서비스 간 상태 변경 알림 및 동기화
- 통신 방식: Kafka Pub/Sub
- 장점:
- 서비스 독립성 보장
- 장애 격리
- 확장 용이
- 단점:
- 최종 일관성 (Eventual Consistency)
- 디버깅 복잡도 증가
2. Job Topics (비동기 작업)
- 사용 시나리오: 장시간 작업 (AI 추천, 이미지 생성)
- 통신 방식: Kafka 메시지 큐
- 패턴: Asynchronous Request-Reply
- 처리 플로우:
- Event Service → Kafka Job Topic: Job 발행
- Async Service → Kafka: Job 수신 및 처리
- Client → Event Service: Job 상태 폴링 (5초 간격)
- Async Service → Redis: 결과 캐싱
- Event Service → Client: 완료 응답
3. 서비스 간 동기 호출
- 사용 시나리오: 다중 채널 배포 (Distribution Service)
- 통신 방식: REST API (HTTP/JSON)
- 패턴: Synchronous Request-Reply
- 처리 플로우:
- Event Service → Distribution Service: POST /api/distribution/distribute
- Distribution Service: 다중 채널 병렬 배포 (1분 이내)
- Distribution Service → Event Service: 배포 완료 응답
- Distribution Service → Kafka: DistributionCompleted 이벤트 발행
- Resilience: Circuit Breaker 적용 (실패율 50% 초과 시 Open)
4. 데이터베이스 직접 조회
- 사용 시나리오: Analytics Service가 이벤트/참여 데이터 필요 시
- 패턴: Database-per-Service 원칙 유지, 필요 시 이벤트로 데이터 동기화
- 통신 방식: Kafka 이벤트 구독 → Analytics DB 저장 → 로컬 조회
- 특징: 서비스 간 직접 API 호출 최소화
Cache-Aside 전략
| 서비스 | 캐시 키 패턴 | TTL | 히트율 목표 | 효과 |
|---|---|---|---|---|
| AI Service | ai:recommendation:{업종}:{지역}:{목적} |
24시간 | 80% | 10초 → 0.1초 (99% 개선) |
| Content Service | content:image:{이벤트ID}:{스타일} |
7일 | 80% | 5초 → 0.1초 (98% 개선) |
| User Service | user:business:{사업자번호} |
7일 | 90% | - |
| Analytics Query | analytics:dashboard:{이벤트ID} |
5분 | 95% | 3초 → 0.5초 (83% 개선) |
Resilience 패턴 적용
1. Circuit Breaker 패턴
- 적용 대상: 모든 외부 API 호출
- 라이브러리: Resilience4j 또는 Hystrix
- 설정:
circuit-breaker: failure-rate-threshold: 50% # 실패율 50% 초과 시 Open slow-call-rate-threshold: 50% # 느린 호출 50% 초과 시 Open slow-call-duration-threshold: 5s # 5초 초과 시 느린 호출로 간주 wait-duration-in-open-state: 30s # Open 상태 30초 유지 후 Half-Open permitted-calls-in-half-open: 3 # Half-Open 상태에서 3개 요청 테스트
2. Retry 패턴
- 적용 대상: 일시적 장애가 예상되는 외부 API
- 재시도 전략: 지수 백오프 (Exponential Backoff)
- 설정:
retry: max-attempts: 3 # 최대 3회 재시도 wait-duration: 1s # 초기 대기 시간 1초 exponential-backoff-multiplier: 2 # 2배씩 증가 (1초, 2초, 4초) retry-exceptions: - java.net.SocketTimeoutException - java.net.ConnectException
3. Timeout 패턴
- 적용 대상: 모든 외부 API 호출
- 설정:
서비스 Timeout 이유 AI Service (AI API) 5분 (300초) 복잡한 분석 작업 Content Service (이미지 API) 5분 (300초) 이미지 생성 시간 고려 Distribution Service (채널 APIs) 10초 빠른 배포 필요
4. Bulkhead 패턴
- 적용 대상: Distribution Service (다중 채널 배포)
- 목적: 채널별 리소스 격리로 장애 전파 차단
- 설정:
bulkhead: max-concurrent-calls: 10 # 채널당 최대 10개 동시 호출 max-wait-duration: 0s # 대기 없이 즉시 실패
5. Fallback 패턴
- 적용 대상: 모든 외부 API 호출
- 전략:
서비스 Fallback 전략 AI Service 캐시된 이전 추천 결과 + 안내 메시지 Content Service 기본 템플릿 이미지 제공 Distribution Service 실패 채널 스킵 + 알림 Analytics Service 캐시된 이전 데이터 반환
이벤트 순서 보장
- Kafka Partition Key: eventId 기준으로 파티션 할당
- 동일 이벤트의 모든 이벤트: 동일 파티션 → 순서 보장
- 다른 이벤트: 독립적 처리 → 병렬 처리 가능
이벤트 재처리 (At-Least-Once)
- 멱등성 보장: 구독자는 동일 이벤트 중복 처리 시 멱등성 유지
- 방법: 이벤트 ID 기반 중복 체크 (Redis Set 사용)
3. 주요 사용자 플로우
3.1 이벤트 생성 플로우 (Event-Driven + Kafka)
1. [이벤트 목적 선택]
┌─────────────────────────────────────────────────────────────┐
│ Client → Event Service │
│ - POST /api/events (목적, 매장 정보) │
│ - Event DB에 저장 │
│ - EventCreated 이벤트 발행 → Kafka │
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ Kafka → Analytics Service │
│ - EventCreated 이벤트 구독 │
│ - Analytics DB에 기본 통계 초기화 │
└─────────────────────────────────────────────────────────────┘
2. [AI 이벤트 추천]
┌─────────────────────────────────────────────────────────────┐
│ Client → Event Service │
│ - POST /api/events/{id}/ai-recommendations │
│ - Kafka ai 이벤트 생성 토픽 발행 (AI 작업 요청) │
│ - Job ID 즉시 반환 (0.1초) │
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ AI Service (Background) │
│ - Kafka ai 이벤트 생성 토픽 구독 │
│ - Redis 캐시 확인 (Cache-Aside) │
│ - 캐시 MISS: Claude API 호출 (5분) [Circuit Breaker] │
│ - AI 추천 결과를 Redis에 저장 (TTL 24시간) │
│ - Job 상태 완료로 업데이트 │
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ Client (Polling) │
│ - GET /api/jobs/{id} (5초 간격) │
│ - 완료 시: AI 추천 결과 반환 (3가지 옵션) │
└─────────────────────────────────────────────────────────────┘
3. [SNS 이미지 생성]
┌─────────────────────────────────────────────────────────────┐
│ Content Service (Background) │
│ - Redis에서 AI Service가 저장한 이벤트 데이터 읽기 │
│ - Redis 캐시 확인 (이미지 생성 여부) │
│ - 캐시 MISS: Stable Diffusion API (5분) [Circuit Breaker] │
│ - 이미지 CDN 업로드 │
│ - 생성된 이미지 URL을 Redis에 저장 (TTL 7일) │
│ - Job 상태 완료로 업데이트 │
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ Client (Polling) │
│ - GET /api/jobs/{id} (3초 간격) │
│ - 완료 시: 3가지 스타일 이미지 URL 반환 │
└─────────────────────────────────────────────────────────────┘
4. [최종 승인 및 배포]
┌─────────────────────────────────────────────────────────────┐
│ Client → Event Service │
│ - POST /api/events/{id}/publish │
│ - Redis의 이벤트 관련 정보(AI 추천, 이미지 URL)를 조회 │
│ - Event DB에 이벤트 정보 저장 │
│ - Event 상태 변경 (DRAFT → PUBLISHED) │
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ Event Service → Distribution Service │
│ - POST /api/distribution/distribute (동기 호출) │
│ - 다중 채널 병렬 배포 [Circuit Breaker + Bulkhead] │
│ * 우리동네TV API (영상 업로드) [Retry: 3회] │
│ * 링고비즈 API (연결음 업데이트) [Retry: 3회] │
│ * 지니TV API (광고 등록) [Retry: 3회] │
│ * SNS APIs (Instagram, Naver, Kakao) [Retry: 3회] │
│ - 배포 완료: DistributionCompleted 이벤트 발행 → Kafka │
│ - Event Service로 배포 완료 응답 (1분 이내) │
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ Kafka → Analytics Service │
│ - DistributionCompleted 이벤트 구독 │
│ - Analytics DB 배포 통계 업데이트 │
│ - 대시보드 캐시 무효화 (다음 조회 시 갱신) │
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ Event Service → Client │
│ - 배포 완료 응답 반환 │
└─────────────────────────────────────────────────────────────┘
3.2 고객 참여 플로우 (Event-Driven)
1. [이벤트 참여]
┌─────────────────────────────────────────────────────────────┐
│ Client → Participation Service │
│ - POST /api/events/{id}/participate │
│ - 중복 참여 체크 (전화번호 기반) │
│ - Participation DB에 저장 │
│ - ParticipantRegistered 이벤트 발행 → Kafka │
│ - 응모 번호 즉시 반환 │
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ Kafka → Analytics Service │
│ - ParticipantRegistered 이벤트 구독 │
│ - 실시간 참여자 수 증가 │
│ - Analytics DB에 참여 통계 업데이트 │
│ - 대시보드 캐시 무효화 │
└─────────────────────────────────────────────────────────────┘
2. [당첨자 추첨]
┌─────────────────────────────────────────────────────────────┐
│ Client → Participation Service │
│ - POST /api/events/{id}/draw-winners │
│ - 난수 기반 무작위 추첨 │
│ - Winners DB에 저장 │
└─────────────────────────────────────────────────────────────┘
3.3 성과 분석 플로우 (Event-Driven)
1. [실시간 대시보드 조회]
┌─────────────────────────────────────────────────────────────┐
│ Client → Analytics Service │
│ - GET /api/events/{id}/analytics │
│ - Redis 캐시 확인 (TTL 5분) │
│ * 캐시 HIT: 즉시 반환 (0.5초) │
│ * 캐시 MISS: 아래 데이터 통합 │
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ Analytics Service (데이터 통합) │
│ - Analytics DB: 이벤트/참여 통계 조회 (로컬 DB) │
│ - 외부 APIs: 채널별 노출/클릭 수 [Circuit Breaker + Fallback] │
│ * 우리동네TV API (조회수) │
│ * 지니TV API (광고 노출 수) │
│ * SNS APIs (좋아요, 댓글, 공유 수) │
│ - Redis 캐싱 (TTL 5분) │
│ - 대시보드 데이터 반환 │
└─────────────────────────────────────────────────────────────┘
2. [실시간 업데이트 (Event 구독)]
┌─────────────────────────────────────────────────────────────┐
│ Analytics Service (Background) │
│ - EventCreated 구독: 이벤트 기본 정보 초기화 │
│ - ParticipantRegistered 구독: 참여자 수 실시간 증가 │
│ - DistributionCompleted 구독: 배포 채널 통계 업데이트 │
│ - 캐시 무효화: 다음 조회 시 최신 데이터 갱신 │
└─────────────────────────────────────────────────────────────┘
3.4 플로우 특징
Kafka 통합 이점
- 단일 메시징 플랫폼: Event Bus와 Job Queue를 Kafka로 통합, 운영 복잡도 감소
- 일관된 메시지 처리: 모든 비동기 통신이 Kafka를 통해 이루어져 모니터링 및 디버깅 용이
- 확장성: Kafka의 높은 처리량으로 대규모 이벤트 처리 지원
Event-Driven 이점
- 느슨한 결합: 서비스 간 직접 의존성 제거
- 장애 격리: 한 서비스 장애가 다른 서비스에 영향 없음
- 확장 용이: 새로운 구독자 추가로 기능 확장
- 비동기 처리: 사용자 응답 시간 단축
Resilience 이점
- Circuit Breaker: 외부 API 장애 시 빠른 실패 및 복구
- Retry: 일시적 장애 자동 복구
- Fallback: 장애 시에도 서비스 지속 (Graceful Degradation)
- Bulkhead: 리소스 격리로 장애 전파 차단
4. 데이터 흐름 및 캐싱 전략
4.1 데이터 흐름
읽기 플로우 (Cache-Aside 패턴)
1. Application → Cache 확인
- Cache HIT: 캐시된 데이터 즉시 반환
- Cache MISS:
2. Application → Database/External API 조회
3. Database/External API → Application 데이터 반환
4. Application → Cache 데이터 저장 (TTL 설정)
5. Application → Client 데이터 반환
쓰기 플로우 (Write-Through 패턴)
1. Application → Database 쓰기
2. Database → Application 성공 응답
3. Application → Cache 무효화 또는 업데이트
4. Application → Client 성공 응답
4.2 캐싱 전략
Redis 캐시 구조
| 서비스 | 캐시 키 패턴 | 데이터 타입 | TTL | 예상 크기 | 히트율 목표 |
|---|---|---|---|---|---|
| User | user:session:{token} |
String | 7일 | 1KB | - |
| 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 | - |
| Content | job:{jobId} |
Hash | 1시간 | 1KB | - |
Redis 메모리 산정
- 예상 동시 사용자: 100명
- 예상 이벤트 수: 50개
- 예상 캐시 항목 수: 10,000개
- 예상 총 메모리: 약 50MB (운영 환경 2GB 할당)
캐시 무효화 전략
- TTL 기반 자동 만료: 대부분의 캐시
- 수동 무효화: 이벤트 수정/삭제 시 관련 캐시 삭제
- Lazy 무효화: 데이터 변경 시 다음 조회 시점에 갱신
4.3 데이터베이스 전략
서비스별 독립 데이터베이스
- User DB: users, stores
- Event DB: events, event_objectives, event_prizes, distribution_logs
- Participation DB: participants, winners
- Analytics DB: event_stats, channel_stats
데이터 일관성 전략
- Eventual Consistency: 서비스 간 데이터는 최종 일관성 보장
- Strong Consistency: 서비스 내부 트랜잭션은 강한 일관성 보장
- Saga 패턴: 이벤트 생성 플로우 (보상 트랜잭션)
5. 확장성 및 성능 고려사항
5.1 수평 확장 전략
서비스별 확장 전략
| 서비스 | 초기 인스턴스 | 확장 조건 | 최대 인스턴스 | Auto-scaling 메트릭 |
|---|---|---|---|---|
| User | 2 | CPU > 70% | 5 | CPU, 메모리 |
| Event | 2 | CPU > 70% | 10 | CPU, 메모리 |
| AI | 1 | Job Queue > 10 | 3 | Queue 길이 |
| Content | 1 | Job Queue > 10 | 3 | Queue 길이 |
| Distribution | 2 | CPU > 70% | 5 | CPU, 메모리 |
| Participation | 1 | CPU > 70% | 3 | CPU, 메모리 |
| Analytics | 1 | CPU > 70% | 3 | CPU, 메모리 |
Redis Cluster
- 초기 구성: 3 노드 (Master 3, Replica 3)
- 확장: 노드 추가를 통한 수평 확장
- HA: Redis Sentinel을 통한 자동 Failover
Database Replication
- Primary-Replica 구조: 읽기 부하 분산
- 읽기 확장: Read Replica 추가 (필요 시)
- 쓰기 확장: Sharding (Phase 2 이후)
5.2 성능 목표
응답 시간 목표
| 기능 | 목표 시간 | 캐시 HIT | 캐시 MISS |
|---|---|---|---|
| 로그인 | 0.5초 | - | - |
| 이벤트 목록 조회 | 0.3초 | - | - |
| AI 트렌드 분석 + 추천 | 0.1초 | ✅ | 10초 (비동기) |
| SNS 이미지 생성 | 0.1초 | ✅ | 5초 (비동기) |
| 다중 채널 배포 | 1분 | - | - |
| 대시보드 로딩 | 0.5초 | ✅ | 3초 |
처리량 목표
- 동시 사용자: 100명 (MVP 목표)
- API 요청: 1,000 req/min
- AI 작업: 10 jobs/min
- 이미지 생성: 10 jobs/min
5.3 성능 최적화 기법
Frontend 최적화
- Code Splitting: 페이지별 번들 분할
- Lazy Loading: 차트 라이브러리 지연 로딩
- CDN: 정적 자산 CDN 배포
- Compression: Gzip/Brotli 압축
Backend 최적화
- Connection Pooling: 데이터베이스 연결 풀 관리
- Query Optimization: 인덱스 최적화, N+1 쿼리 방지
- Batch Processing: 대량 데이터 일괄 처리
- Pagination: 목록 조회 페이지네이션
Cache 최적화
- Multi-Level Caching: Browser Cache → CDN → Redis → Database
- Cache Warming: 자주 사용되는 데이터 사전 로딩
- Cache Preloading: 피크 시간 전 캐시 준비
6. 보안 고려사항
6.1 인증 및 인가
JWT 기반 인증
- 토큰 발급: User Service에서 로그인 시 JWT 토큰 발급
- 토큰 검증: API Gateway에서 모든 요청의 JWT 토큰 검증
- 토큰 저장: Redis에 세션 정보 저장 (TTL 7일)
- 토큰 갱신: Refresh Token 패턴 (선택)
역할 기반 접근 제어 (RBAC)
- 역할: OWNER (매장 사장님), CUSTOMER (이벤트 참여자)
- 권한 관리: API별 필요 역할 정의
- API Gateway 검증: 요청자의 역할 확인
6.2 데이터 보안
민감 정보 암호화
- 비밀번호: bcrypt 해싱 (Cost Factor: 10)
- 사업자번호: AES-256 암호화 저장
- 개인정보: 전화번호 마스킹 (010-****-1234)
전송 보안
- HTTPS: 모든 통신 TLS 1.3 암호화
- API Key: 외부 API 호출 시 안전한 Key 관리 (AWS Secrets Manager)
데이터 접근 통제
- Database: 서비스별 독립 계정, 최소 권한 원칙
- Redis: 비밀번호 설정, ACL 적용
- 백업: 암호화된 백업 저장
6.3 보안 모니터링
위협 탐지
- Rate Limiting: API Gateway에서 사용자당 100 req/min
- Brute Force 방지: 로그인 5회 실패 시 계정 잠금 (삭제됨, 향후 추가 가능)
- SQL Injection 방지: Prepared Statement 사용
- XSS 방지: 입력 데이터 Sanitization
로깅 및 감사
- Access Log: 모든 API 요청 로깅
- Audit Log: 민감 작업 (로그인, 이벤트 생성, 당첨자 추첨) 감사 로그
- 중앙집중식 로깅: ELK Stack 또는 CloudWatch Logs
7. 논리 아키텍처 다이어그램
논리 아키텍처 다이어그램은 별도 Mermaid 파일로 작성되었습니다.
파일 위치: logical-architecture.mmd
다이어그램 확인 방법:
- https://mermaid.live/edit 접속
logical-architecture.mmd파일 내용 붙여넣기- 다이어그램 시각적 확인
다이어그램 구성:
- Services: 4개 핵심 서비스 (User, Event, Participation, Analytics)
- Async Services: 3개 비동기 서비스 (AI, Content, Distribution)
- Kafka: Event Topics + Job Topics 통합 메시징 플랫폼
- External System: 통합된 외부 시스템 (국세청 API, AI API, 이미지 생성 API, 배포 채널 APIs)
의존성 표현:
- 굵은 화살표 (==>): Kafka Event Topics 발행
- 실선 화살표 (-->): Kafka Job Topics 발행 또는 외부 시스템 호출
- 점선 화살표 (-.->): Kafka 구독
부록
A. 참고 문서
B. 주요 결정사항
- Kafka 통합 메시징 플랫폼 채택: Event Bus와 Job Queue를 Kafka로 통합하여 운영 복잡도 감소
- Event-Driven 아키텍처 채택: Kafka를 통한 서비스 간 느슨한 결합 및 비동기 통신
- 도메인 이벤트 정의: 3개 Event Topics (EventCreated, ParticipantRegistered, DistributionCompleted)
- Job Topics 정의: 2개 Job Topics (ai 이벤트 생성, 이미지 생성)로 장시간 비동기 작업 처리
- Resilience 패턴 전면 적용: Circuit Breaker, Retry, Timeout, Bulkhead, Fallback
- At-Least-Once Delivery: Kafka 메시지 보장 및 멱등성 설계
- Cache-Aside 패턴: AI/이미지 생성 결과 캐싱으로 응답 시간 90% 개선
- Redis 기반 서비스 간 데이터 공유: AI Service → Redis → Content Service 데이터 흐름
- Redis to DB 영구 저장: 이벤트 생성 완료 시 Redis 데이터를 Event DB에 저장
- 동기 배포: Event Service가 Distribution Service를 REST API로 직접 호출하여 다중 채널 배포 동기 처리
- 서비스별 독립 Database: Database-per-Service 패턴으로 서비스 독립성 보장
- 장시간 작업 Timeout 조정: AI/Content Service Timeout을 5분으로 설정하여 복잡한 생성 작업 지원
C. 향후 개선 방안 (Phase 2 이후)
- Event Sourcing 완전 적용: 모든 상태 변경을 이벤트로 저장하여 시간 여행 및 감사 추적 강화
- Saga 패턴 적용: 복잡한 분산 트랜잭션 보상 로직 체계화
- Service Mesh 도입: Istio를 통한 서비스 간 통신 관찰성 및 보안 강화
- Database Sharding: Event/Participation Write DB 샤딩으로 쓰기 확장성 개선
- WebSocket 기반 실시간 푸시: 대시보드 실시간 업데이트 (폴링 대체)
- GraphQL API Gateway: 클라이언트 맞춤형 데이터 조회 최적화
- Dead Letter Queue 고도화: 실패 이벤트 재처리 및 알림 자동화
문서 버전: 2.2 최종 수정일: 2025-10-22 작성자: System Architect 변경 사항: Distribution Service 동기 호출 전환 (REST API 직접 호출)