kt-event-marketing/design/backend/logical/logical-architecture.md
2025-10-22 10:48:55 +09:00

42 KiB

KT AI 기반 소상공인 이벤트 자동 생성 서비스 - 논리 아키텍처

문서 정보

버전 이력

  • v1.0 (2025-10-21): 초기 마이크로서비스 아키텍처 설계
  • v2.0 (2025-10-22): CQRS 패턴 및 Event-Driven 아키텍처 전환, Resilience 패턴 전면 적용

목차

  1. 개요
  2. 서비스 아키텍처
  3. 주요 사용자 플로우
  4. 데이터 흐름 및 캐싱 전략
  5. 확장성 및 성능 고려사항
  6. 보안 고려사항
  7. 논리 아키텍처 다이어그램

1. 개요

1.1 설계 원칙

본 논리 아키텍처는 다음 원칙을 기반으로 설계되었습니다:

유저스토리 기반 설계

  • 20개 유저스토리와 정확히 매칭
  • 불필요한 추가 기능 배제
  • 비즈니스 요구사항 우선 반영

CQRS (Command Query Responsibility Segregation)

  • 읽기/쓰기 분리: Command Service와 Query Service로 책임 분리
  • 독립적 확장: 읽기와 쓰기 부하에 따라 독립적으로 확장
  • 성능 최적화: Query Service는 읽기 최적화 데이터 모델 사용
  • 이벤트 소싱 준비: 도메인 이벤트 기반 상태 동기화

Event-Driven 아키텍처

  • 비동기 메시징: Event Bus(Kafka/SQS)를 통한 서비스 간 통신
  • 느슨한 결합: 서비스 간 직접 의존성 제거
  • 확장성: 이벤트 구독자 추가로 기능 확장 용이
  • 장애 격리: 이벤트 발행/구독 실패 시 서비스 독립성 유지

Resilience 패턴 적용

  • Circuit Breaker: 외부 API 장애 시 빠른 실패 및 복구 (Hystrix/Resilience4j)
  • Retry Pattern: 일시적 장애 시 자동 재시도 (지수 백오프)
  • Timeout Pattern: 응답 시간 제한으로 리소스 점유 방지
  • Bulkhead Pattern: 리소스 격리로 장애 전파 차단
  • Fallback Pattern: 장애 시 대체 로직 실행 (캐시 응답 등)

1.2 핵심 컴포넌트 정의

Command Services (쓰기 전용)

  1. User Service: 사용자 인증 및 매장정보 관리

    • 회원가입/로그인 (JWT 발급)
    • 프로필 수정
    • 사업자번호 검증 (외부 API 연동)
  2. Event Command Service: 이벤트 생성/수정/삭제

    • 이벤트 생성 플로우 오케스트레이션
    • 도메인 이벤트 발행 (EventCreated, EventPublished)
    • 이벤트 상태 변경
  3. Participation Command Service: 참여 및 당첨자 관리

    • 참여 접수 및 검증
    • 당첨자 추첨 실행
    • 도메인 이벤트 발행 (ParticipantRegistered, WinnerSelected)

Query Services (읽기 전용)

  1. Event Query Service: 이벤트 조회 최적화

    • 이벤트 목록/상세 조회
    • 이벤트 검색 및 필터링
    • 읽기 최적화 데이터 모델 (비정규화)
  2. Participation Query Service: 참여자/당첨자 조회

    • 참여자 목록 조회
    • 당첨자 조회
    • 읽기 최적화 집계 데이터
  3. Analytics Query Service: 실시간 성과 분석

    • 대시보드 데이터 조회
    • 채널별 성과 집계
    • ROI 계산 및 분석

Async Services (비동기 처리)

  1. AI Service: AI 기반 이벤트 추천

    • Job Queue를 통한 비동기 처리
    • Circuit Breaker 적용 (외부 AI API)
    • 결과 캐싱 (Redis)
  2. Content Service: SNS 이미지 생성

    • Job Queue를 통한 비동기 처리
    • Circuit Breaker 적용 (외부 이미지 API)
    • CDN 업로드 및 캐싱
  3. Distribution Service: 다중 채널 배포

    • Event Bus를 통한 EventPublished 구독
    • 병렬 배포 및 Circuit Breaker 적용
    • 배포 완료 이벤트 발행 (DistributionCompleted)

Event Bus (Kafka/SQS)

  • 도메인 이벤트 발행/구독: 서비스 간 비동기 통신
  • 이벤트 종류:
    • EventCreated: 이벤트 생성 시
    • EventPublished: 이벤트 배포 승인 시
    • ParticipantRegistered: 참여자 등록 시
    • WinnerSelected: 당첨자 선정 시
    • DistributionCompleted: 배포 완료 시
  • 보장 수준: At-Least-Once Delivery

Job Queue (RabbitMQ)

  • 장시간 비동기 작업: AI 추천, 이미지 생성
  • Priority Queue: 작업 우선순위 관리
  • Dead Letter Queue: 실패 작업 처리

Data Layer

  • Redis Cache: 세션, AI 결과, 이미지 URL, 대시보드 캐싱
  • PostgreSQL: 서비스별 독립 데이터베이스
    • User DB, Event Write DB, Event Read DB, Participation Write DB, Participation Read DB, Analytics DB
  • 읽기 전용 복제본: Query Service 성능 최적화

External Systems

  • 국세청 API: 사업자번호 검증
  • AI APIs: Claude/GPT-4 (트렌드 분석)
  • 이미지 생성 APIs: Stable Diffusion/DALL-E
  • 배포 채널 APIs: 우리동네TV, 링고비즈, 지니TV, SNS APIs

2. 서비스 아키텍처

2.1 CQRS 패턴 적용

설계 원칙

  • Command와 Query 분리: 쓰기와 읽기 책임을 독립된 서비스로 분리
  • 독립적 확장: 읽기/쓰기 부하에 따라 독립적으로 스케일링
  • 최적화된 데이터 모델: Query Service는 비정규화된 읽기 최적화 모델 사용
  • 이벤트 동기화: Command Service가 발행한 도메인 이벤트로 Query Service 동기화

2.2 Command Services (쓰기 전용)

User Service

핵심 책임:

  • 회원가입/로그인 (JWT 토큰 발급)
  • 프로필 수정 (매장 정보 포함)
  • 사업자번호 검증 (국세청 API 연동)
  • 세션 관리

관련 유저스토리: UFR-USER-010, 020, 030, 040

Resilience 패턴:

  • Circuit Breaker: 국세청 API 호출 시 (실패율 5% 초과 시 Open)
  • Retry: 최대 3회 재시도 (지수 백오프: 1초, 2초, 4초)
  • Timeout: 5초
  • Fallback: 사업자번호 검증 스킵 (수동 확인 안내)

데이터 저장:

  • User DB: users, stores 테이블
  • Redis: 세션 정보 (TTL 7일), 사업자번호 검증 결과 (TTL 7일)

Event Command Service

핵심 책임:

  • 이벤트 생성/수정/삭제
  • 이벤트 생성 플로우 오케스트레이션
  • 도메인 이벤트 발행 (EventCreated, EventPublished)

관련 유저스토리: UFR-EVENT-010, 020, 030, 040, 050, 060, 070

도메인 이벤트:

  1. EventCreated: 이벤트 생성 완료 시

    • Payload: eventId, storeId, title, objective, createdAt
    • 구독자: Event Query Service, Analytics Query Service
  2. EventPublished: 이벤트 배포 승인 시

    • Payload: eventId, distributionChannels, publishedAt
    • 구독자: Distribution Service

주요 플로우:

  1. 이벤트 목적 선택 → Event DB 저장
  2. AI 추천 요청 → Job Queue 발행
  3. 이미지 생성 요청 → Job Queue 발행
  4. 배포 승인 → EventPublished 이벤트 발행

데이터 저장:

  • Event Write DB: events, event_objectives, event_prizes 테이블

Participation Command Service

핵심 책임:

  • 이벤트 참여 접수 및 검증
  • 당첨자 추첨 실행
  • 도메인 이벤트 발행 (ParticipantRegistered, WinnerSelected)

관련 유저스토리: UFR-PART-010, 020, 030

도메인 이벤트:

  1. ParticipantRegistered: 참여자 등록 시

    • Payload: participantId, eventId, phoneNumber, registeredAt
    • 구독자: Participation Query Service, Analytics Query Service
  2. WinnerSelected: 당첨자 선정 시

    • Payload: winnerId, eventId, selectedAt
    • 구독자: Participation Query Service

주요 기능:

  • 중복 참여 체크 (전화번호 기반)
  • 난수 기반 무작위 추첨
  • 매장 방문 고객 가산점 적용

데이터 저장:

  • Participation Write DB: participants, winners 테이블

2.3 Query Services (읽기 전용)

Event Query Service

핵심 책임:

  • 이벤트 목록/상세 조회
  • 이벤트 검색 및 필터링
  • 읽기 최적화 데이터 제공

이벤트 구독:

  • EventCreated: 읽기 DB에 이벤트 데이터 동기화

데이터 모델:

  • 비정규화: 조인 없이 단일 쿼리로 조회 가능
  • 인덱스 최적화: storeId, status, createdAt

데이터 저장:

  • Event Read DB: events_view (비정규화 테이블)

Participation Query Service

핵심 책임:

  • 참여자 목록 조회
  • 당첨자 조회
  • 집계 데이터 제공

이벤트 구독:

  • ParticipantRegistered: 참여자 데이터 동기화
  • WinnerSelected: 당첨자 데이터 동기화

데이터 모델:

  • 집계 테이블: 이벤트별 참여자 수, 당첨자 수 사전 계산

데이터 저장:

  • Participation Read DB: participants_view, winners_view, event_participant_stats

Analytics Query Service

핵심 책임:

  • 실시간 성과 대시보드
  • 채널별 성과 분석
  • ROI 계산

관련 유저스토리: UFR-ANAL-010

이벤트 구독:

  • EventCreated: 이벤트 기본 정보 동기화
  • ParticipantRegistered: 참여자 수 실시간 업데이트
  • DistributionCompleted: 배포 통계 업데이트

Resilience 패턴:

  • Circuit Breaker: 외부 채널 API 조회 시
  • Fallback: 캐시된 이전 데이터 반환
  • Cache-Aside: Redis 캐싱 (TTL 5분)

데이터 통합:

  • Event Query Service: 이벤트 정보
  • Participation Query Service: 참여자/당첨자 데이터
  • Distribution Service: 배포 통계
  • 외부 APIs: 우리동네TV, 지니TV, SNS 통계

데이터 저장:

  • Analytics DB: event_stats, channel_stats
  • Redis: 대시보드 데이터 (TTL 5분)

2.4 Async Services (비동기 처리)

AI Service

핵심 책임:

  • 업종/지역/시즌 트렌드 분석
  • 3가지 이벤트 기획안 자동 생성
  • 예상 성과 계산

관련 유저스토리: UFR-AI-010

Resilience 패턴:

  • Circuit Breaker: AI API 호출 시 (실패율 10% 초과 시 Open)
  • Timeout: 30초
  • Fallback: 캐시된 이전 추천 결과 + 안내 메시지
  • Cache-Aside: Redis 캐싱 (TTL 24시간)

처리 시간:

  • 캐시 HIT: 0.1초
  • 캐시 MISS: 10초 이내 (비동기 Job 처리)

데이터 저장:

  • Redis: AI 추천 결과 (TTL 24시간)
  • Redis: Job 상태 정보 (TTL 1시간)

Content Service

핵심 책임:

  • 3가지 스타일 SNS 이미지 자동 생성
  • 플랫폼별 이미지 최적화
  • 이미지 편집 기능

관련 유저스토리: UFR-CONT-010, 020

Resilience 패턴:

  • Circuit Breaker: 이미지 생성 API 호출 시
  • Timeout: 20초
  • Fallback: 기본 템플릿 이미지 제공
  • Cache-Aside: Redis 캐싱 (TTL 7일)

처리 시간:

  • 캐시 HIT: 0.1초
  • 캐시 MISS: 5초 이내 (비동기 Job 처리)

데이터 저장:

  • Redis: 이미지 생성 결과 (CDN URL, TTL 7일)
  • CDN: 생성된 이미지 파일

Distribution Service

핵심 책임:

  • 다중 채널 동시 배포
  • 배포 상태 모니터링
  • 도메인 이벤트 발행 (DistributionCompleted)

관련 유저스토리: UFR-DIST-010, 020

이벤트 구독:

  • EventPublished: 배포 작업 시작 트리거

도메인 이벤트:

  • DistributionCompleted: 배포 완료 시
    • Payload: eventId, distributedChannels, completedAt
    • 구독자: Analytics Query Service

Resilience 패턴:

  • Circuit Breaker: 각 외부 채널 API별 독립 적용
  • Retry: 최대 3회 재시도 (지수 백오프)
  • Bulkhead: 채널별 스레드 풀 격리 (장애 전파 방지)
  • Fallback: 실패 채널 스킵 + 알림

처리 시간: 1분 이내 (모든 채널 배포 완료)

데이터 저장:

  • Event Read DB: distribution_logs 테이블

2.5 Event-Driven 통신 전략

Event Bus 아키텍처

기술 스택: Kafka 또는 AWS SQS 보장 수준: At-Least-Once Delivery 메시지 포맷: JSON

도메인 이벤트 정의

이벤트명 발행자 구독자 Payload 용도
EventCreated Event Command Event Query
Analytics Query
eventId, storeId, title, objective, createdAt 이벤트 생성 동기화
EventPublished Event Command Distribution Service eventId, distributionChannels, publishedAt 배포 작업 트리거
ParticipantRegistered Participation Command Participation Query
Analytics Query
participantId, eventId, phoneNumber, registeredAt 참여자 등록 동기화
WinnerSelected Participation Command Participation Query winnerId, eventId, selectedAt 당첨자 선정 동기화
DistributionCompleted Distribution Service Analytics Query eventId, distributedChannels, completedAt 배포 완료 통계 업데이트

통신 패턴별 설계

1. Event-Driven 통신 (비동기 메시징)

  • 사용 시나리오: 서비스 간 상태 동기화, 느슨한 결합 필요 시
  • 장점:
    • 서비스 독립성 보장
    • 장애 격리
    • 확장 용이
  • 단점:
    • 최종 일관성 (Eventual Consistency)
    • 디버깅 복잡도 증가

2. Job Queue 통신 (비동기 작업)

  • 사용 시나리오: 장시간 작업 (AI 추천, 이미지 생성)
  • 기술 스택: RabbitMQ
  • 패턴: Asynchronous Request-Reply
  • 처리 플로우:
    1. Command Service → Job Queue: Job 발행
    2. Async Service → Job Queue: Job 수신 및 처리
    3. Client → Command Service: Job 상태 폴링 (5초 간격)
    4. Async Service → Redis: 결과 캐싱
    5. Command Service → Client: 완료 응답

3. Query Service 간 통신

  • 사용 시나리오: Analytics Query가 다른 Query Service 데이터 필요 시
  • 패턴: Cache-Aside
  • 통신 방식: REST API (HTTP/JSON)
  • 특징: 읽기 전용이므로 직접 호출 허용

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 이유
    User Service (국세청 API) 5초 빠른 검증 필요
    AI Service (AI API) 30초 복잡한 분석 작업
    Content Service (이미지 API) 20초 이미지 생성 시간 고려
    Distribution Service (채널 APIs) 10초 빠른 배포 필요

4. Bulkhead 패턴

  • 적용 대상: Distribution Service (다중 채널 배포)
  • 목적: 채널별 리소스 격리로 장애 전파 차단
  • 설정:
    bulkhead:
      max-concurrent-calls: 10           # 채널당 최대 10개 동시 호출
      max-wait-duration: 0s              # 대기 없이 즉시 실패
    

5. Fallback 패턴

  • 적용 대상: 모든 외부 API 호출
  • 전략:
    서비스 Fallback 전략
    User Service 사업자번호 검증 스킵 (수동 확인 안내)
    AI Service 캐시된 이전 추천 결과 + 안내 메시지
    Content Service 기본 템플릿 이미지 제공
    Distribution Service 실패 채널 스킵 + 알림
    Analytics Query 캐시된 이전 데이터 반환

이벤트 순서 보장

  • Kafka Partition Key: eventId 기준으로 파티션 할당
  • 동일 이벤트의 모든 이벤트: 동일 파티션 → 순서 보장
  • 다른 이벤트: 독립적 처리 → 병렬 처리 가능

이벤트 재처리 (At-Least-Once)

  • 멱등성 보장: 구독자는 동일 이벤트 중복 처리 시 멱등성 유지
  • 방법: 이벤트 ID 기반 중복 체크 (Redis Set 사용)

3. 주요 사용자 플로우

3.1 이벤트 생성 플로우 (CQRS + Event-Driven)

1. [이벤트 목적 선택]
   ┌─────────────────────────────────────────────────────────────┐
   │ Client → Event Command Service                              │
   │ - POST /api/events (목적, 매장 정보)                         │
   │ - Event Write DB에 저장                                      │
   │ - EventCreated 이벤트 발행 → Event Bus                       │
   └─────────────────────────────────────────────────────────────┘

   ┌─────────────────────────────────────────────────────────────┐
   │ Event Bus → Event Query Service                             │
   │ - EventCreated 이벤트 구독                                   │
   │ - Event Read DB에 동기화 (비정규화)                          │
   └─────────────────────────────────────────────────────────────┘

   ┌─────────────────────────────────────────────────────────────┐
   │ Event Bus → Analytics Query Service                         │
   │ - EventCreated 이벤트 구독                                   │
   │ - Analytics DB에 기본 통계 초기화                            │
   └─────────────────────────────────────────────────────────────┘

2. [AI 이벤트 추천]
   ┌─────────────────────────────────────────────────────────────┐
   │ Client → Event Command Service                              │
   │ - POST /api/events/{id}/ai-recommendations                  │
   │ - Job Queue 발행 (AI 작업 요청)                              │
   │ - Job ID 즉시 반환 (0.1초)                                   │
   └─────────────────────────────────────────────────────────────┘

   ┌─────────────────────────────────────────────────────────────┐
   │ AI Service (Background)                                      │
   │ - Job Queue 구독                                             │
   │ - Redis 캐시 확인 (Cache-Aside)                              │
   │ - 캐시 MISS: Claude API 호출 (10초) [Circuit Breaker]        │
   │ - 결과 캐싱 (TTL 24시간)                                      │
   │ - Job 상태 완료로 업데이트                                    │
   └─────────────────────────────────────────────────────────────┘

   ┌─────────────────────────────────────────────────────────────┐
   │ Client (Polling)                                             │
   │ - GET /api/jobs/{id} (5초 간격)                              │
   │ - 완료 시: AI 추천 결과 반환 (3가지 옵션)                     │
   └─────────────────────────────────────────────────────────────┘

3. [SNS 이미지 생성]
   ┌─────────────────────────────────────────────────────────────┐
   │ Client → Event Command Service                              │
   │ - POST /api/events/{id}/content-generation                  │
   │ - Job Queue 발행 (이미지 생성 요청)                           │
   │ - Job ID 즉시 반환 (0.1초)                                   │
   └─────────────────────────────────────────────────────────────┘

   ┌─────────────────────────────────────────────────────────────┐
   │ Content Service (Background)                                 │
   │ - Job Queue 구독                                             │
   │ - Redis 캐시 확인                                            │
   │ - 캐시 MISS: Stable Diffusion API (5초) [Circuit Breaker]   │
   │ - 이미지 CDN 업로드                                          │
   │ - CDN URL 캐싱 (TTL 7일)                                     │
   │ - Job 상태 완료로 업데이트                                    │
   └─────────────────────────────────────────────────────────────┘

   ┌─────────────────────────────────────────────────────────────┐
   │ Client (Polling)                                             │
   │ - GET /api/jobs/{id} (3초 간격)                              │
   │ - 완료 시: 3가지 스타일 이미지 URL 반환                       │
   └─────────────────────────────────────────────────────────────┘

4. [최종 승인 및 배포]
   ┌─────────────────────────────────────────────────────────────┐
   │ Client → Event Command Service                              │
   │ - POST /api/events/{id}/publish                             │
   │ - Event 상태 변경 (DRAFT → PUBLISHED)                       │
   │ - EventPublished 이벤트 발행 → Event Bus                     │
   └─────────────────────────────────────────────────────────────┘

   ┌─────────────────────────────────────────────────────────────┐
   │ Event Bus → Distribution Service                            │
   │ - EventPublished 이벤트 구독                                 │
   │ - 다중 채널 병렬 배포 시작 [Circuit Breaker + Bulkhead]      │
   │   * 우리동네TV API (영상 업로드) [Retry: 3회]                │
   │   * 링고비즈 API (연결음 업데이트) [Retry: 3회]              │
   │   * 지니TV API (광고 등록) [Retry: 3회]                      │
   │   * SNS APIs (Instagram, Naver, Kakao) [Retry: 3회]         │
   │ - 배포 완료: DistributionCompleted 이벤트 발행               │
   └─────────────────────────────────────────────────────────────┘

   ┌─────────────────────────────────────────────────────────────┐
   │ Event Bus → Analytics Query Service                         │
   │ - DistributionCompleted 이벤트 구독                          │
   │ - Analytics DB 배포 통계 업데이트                            │
   │ - 대시보드 캐시 무효화 (다음 조회 시 갱신)                    │
   └─────────────────────────────────────────────────────────────┘

3.2 고객 참여 플로우 (Event-Driven)

1. [이벤트 참여]
   ┌─────────────────────────────────────────────────────────────┐
   │ Client → Participation Command Service                      │
   │ - POST /api/events/{id}/participate                         │
   │ - 중복 참여 체크 (전화번호 기반)                              │
   │ - Participation Write DB에 저장                              │
   │ - ParticipantRegistered 이벤트 발행 → Event Bus             │
   │ - 응모 번호 즉시 반환                                         │
   └─────────────────────────────────────────────────────────────┘

   ┌─────────────────────────────────────────────────────────────┐
   │ Event Bus → Participation Query Service                     │
   │ - ParticipantRegistered 이벤트 구독                          │
   │ - Participation Read DB에 동기화                             │
   │ - 이벤트별 참여자 수 집계 테이블 업데이트                      │
   └─────────────────────────────────────────────────────────────┘

   ┌─────────────────────────────────────────────────────────────┐
   │ Event Bus → Analytics Query Service                         │
   │ - ParticipantRegistered 이벤트 구독                          │
   │ - 실시간 참여자 수 증가                                       │
   │ - 대시보드 캐시 무효화                                        │
   └─────────────────────────────────────────────────────────────┘

2. [당첨자 추첨]
   ┌─────────────────────────────────────────────────────────────┐
   │ Client → Participation Command Service                      │
   │ - POST /api/events/{id}/draw-winners                        │
   │ - 난수 기반 무작위 추첨                                       │
   │ - Winners Write DB에 저장                                    │
   │ - WinnerSelected 이벤트 발행 → Event Bus                     │
   └─────────────────────────────────────────────────────────────┘

   ┌─────────────────────────────────────────────────────────────┐
   │ Event Bus → Participation Query Service                     │
   │ - WinnerSelected 이벤트 구독                                 │
   │ - Winners Read DB에 동기화                                   │
   └─────────────────────────────────────────────────────────────┘

3.3 성과 분석 플로우 (Query Service + Event 구독)

1. [실시간 대시보드 조회]
   ┌─────────────────────────────────────────────────────────────┐
   │ Client → Analytics Query Service                            │
   │ - GET /api/events/{id}/analytics                            │
   │ - Redis 캐시 확인 (TTL 5분)                                  │
   │   * 캐시 HIT: 즉시 반환 (0.5초)                              │
   │   * 캐시 MISS: 아래 데이터 통합                               │
   └─────────────────────────────────────────────────────────────┘

   ┌─────────────────────────────────────────────────────────────┐
   │ Analytics Query Service (데이터 통합)                        │
   │ - Analytics DB: 이벤트 통계 조회                             │
   │ - Event Query Service: 이벤트 정보 조회 (REST)               │
   │ - Participation Query Service: 참여자/당첨자 조회 (REST)     │
   │ - 외부 APIs: 채널별 노출/클릭 수 [Circuit Breaker + Fallback] │
   │   * 우리동네TV API (조회수)                                  │
   │   * 지니TV API (광고 노출 수)                                │
   │   * SNS APIs (좋아요, 댓글, 공유 수)                          │
   │ - Redis 캐싱 (TTL 5분)                                       │
   │ - 대시보드 데이터 반환                                        │
   └─────────────────────────────────────────────────────────────┘

2. [실시간 업데이트 (Event 구독)]
   ┌─────────────────────────────────────────────────────────────┐
   │ Analytics Query Service (Background)                        │
   │ - EventCreated 구독: 이벤트 기본 정보 초기화                 │
   │ - ParticipantRegistered 구독: 참여자 수 실시간 증가          │
   │ - DistributionCompleted 구독: 배포 채널 통계 업데이트         │
   │ - 캐시 무효화: 다음 조회 시 최신 데이터 갱신                  │
   └─────────────────────────────────────────────────────────────┘

3.4 플로우 특징

CQRS 이점

  • Command Service: 쓰기 작업에 집중, 트랜잭션 보장
  • Query Service: 읽기 최적화 데이터 모델, 빠른 조회
  • 독립적 확장: 읽기/쓰기 부하에 따라 독립 스케일링

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 -
User user:business:{사업자번호} String 7일 0.5KB 90%
AI ai:recommendation:{업종}:{지역}:{목적} Hash 24시간 10KB 80%
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

다이어그램 확인 방법:

  1. https://mermaid.live/edit 접속
  2. logical-architecture.mmd 파일 내용 붙여넣기
  3. 다이어그램 시각적 확인

다이어그램 구성:

  • Client Layer: Web/Mobile Client
  • Gateway Layer: API Gateway
  • Service Layer: 7개 마이크로서비스
  • Data Layer: Redis Cache, Message Queue, Databases
  • External APIs: 7개 외부 API

의존성 표현:

  • 실선 화살표 (→): 동기적 의존성
  • 점선 화살표 (-.->): 비동기 의존성 또는 캐시 접근
  • 화살표 레이블: 의존성 목적 명시

부록

A. 참고 문서

B. 주요 결정사항

  1. CQRS 패턴 채택: 읽기/쓰기 책임 분리로 독립적 확장 및 성능 최적화
  2. Event-Driven 아키텍처 채택: Event Bus(Kafka/SQS)를 통한 서비스 간 느슨한 결합
  3. 도메인 이벤트 정의: 5개 핵심 이벤트로 서비스 간 상태 동기화
  4. Resilience 패턴 전면 적용: Circuit Breaker, Retry, Timeout, Bulkhead, Fallback
  5. At-Least-Once Delivery: 이벤트 보장 수준 및 멱등성 설계
  6. Cache-Aside 패턴: AI/이미지 생성 결과 캐싱으로 응답 시간 90% 개선
  7. Job Queue 분리: RabbitMQ로 장시간 비동기 작업 처리
  8. 서비스별 독립 Database: Command/Query별 독립 DB로 CQRS 지원

C. 향후 개선 방안 (Phase 2 이후)

  1. Event Sourcing 완전 적용: 모든 상태 변경을 이벤트로 저장하여 시간 여행 및 감사 추적 강화
  2. Saga 패턴 적용: 복잡한 분산 트랜잭션 보상 로직 체계화
  3. Service Mesh 도입: Istio를 통한 서비스 간 통신 관찰성 및 보안 강화
  4. Database Sharding: Event/Participation Write DB 샤딩으로 쓰기 확장성 개선
  5. WebSocket 기반 실시간 푸시: 대시보드 실시간 업데이트 (폴링 대체)
  6. GraphQL API Gateway: 클라이언트 맞춤형 데이터 조회 최적화
  7. Dead Letter Queue 고도화: 실패 이벤트 재처리 및 알림 자동화

문서 버전: 2.0 최종 수정일: 2025-10-22 작성자: System Architect 변경 사항: CQRS 패턴 및 Event-Driven 아키텍처 전환, Resilience 패턴 전면 적용