# KT AI 기반 소상공인 이벤트 자동 생성 서비스 - 클라우드 아키텍처 패턴 적용 방안

## 문서 정보
- **작성일**: 2025-10-22
- **버전**: 3.0 (Azure Kubernetes 기반)
- **적용 패턴**: 4개 핵심 패턴
- **인프라 환경**: Azure Kubernetes Service (AKS)
- **목표**: 빠른 MVP 출시와 안정적 서비스 제공

---

## 1. 요구사항 분석

### 1.1 기능적 요구사항

**User 서비스**
- 회원가입/로그인 및 프로필 관리
- 사업자번호 검증 (국세청 API)

**Event 서비스**
- 이벤트 CRUD 및 상태 관리
- 이벤트 목적 선택 → AI 추천 → 콘텐츠 생성 → 배포 → 분석 플로우

**AI 서비스**
- 트렌드 분석 (업종/지역/시즌)
- 3가지 이벤트 기획안 자동 생성
- Claude API/GPT-4 API 연동

**Content 서비스**
- 3가지 스타일 SNS 이미지 자동 생성
- Stable Diffusion/DALL-E API 연동
- 플랫폼별 이미지 최적화 (Instagram, Naver, Kakao)

**Distribution 서비스**
- 다중 채널 동시 배포 (우리동네TV, 링고비즈, 지니TV, SNS)
- 7개 외부 API 연동

**Participation 서비스**
- 이벤트 참여 접수 및 당첨자 추첨

**Analytics 서비스**
- 실시간 성과 대시보드
- 채널별 성과 분석

### 1.2 비기능적 요구사항

**성능 요구사항**
- AI 트렌드 분석 + 이벤트 추천: **10초 이내**
- SNS 이미지 생성: **5초 이내**
- 대시보드 데이터 업데이트: **5분 간격**
- 다중 채널 배포: **1분 이내**

**가용성 요구사항**
- 시스템 가용성: **99% 이상** (MVP 목표)
- 외부 API 장애 시 서비스 지속 가능

**확장성 요구사항**
- 초기 사용자: **100명**
- 동시 이벤트: **50개**
- 캐시 히트율: **80% 이상**

**보안 요구사항**
- JWT 기반 인증/인가
- API Gateway를 통한 중앙집중식 보안

### 1.3 외부 API 의존성

| 서비스 | 외부 API | 용도 | 응답시간 |
|--------|----------|------|----------|
| User | 국세청 사업자등록정보 진위확인 API | 사업자번호 검증 | 2-3초 |
| AI | Claude API / GPT-4 API | 트렌드 분석 및 이벤트 추천 | 5-10초 |
| Content | Stable Diffusion / DALL-E API | SNS 이미지 생성 | 3-5초 |
| Distribution | 우리동네TV API | 영상 업로드 및 송출 | 1-2초 |
| Distribution | 링고비즈 API | 연결음 업데이트 | 1초 |
| Distribution | 지니TV 광고 API | 광고 등록 | 1-2초 |
| Distribution | SNS API (Instagram, Naver, Kakao) | 자동 포스팅 | 1-3초 |

---

## 2. 적용 패턴 개요

### 2.1 선정된 4가지 핵심 패턴

| 패턴 | 적용 목적 | Azure 서비스 | 우선순위 |
|------|----------|-------------|---------|
| **Cache-Aside** | AI 응답 시간 단축 및 비용 절감 | Azure Cache for Redis | 🔴 Critical |
| **API Gateway** | 중앙집중식 보안 및 라우팅 | Azure API Management / Nginx Ingress | 🔴 Critical |
| **Asynchronous Request-Reply** | 장시간 작업 응답 시간 개선 | Azure Service Bus / RabbitMQ | 🔴 Critical |
| **Circuit Breaker** | 외부 API 장애 격리 | Resilience4j / Polly | 🟡 Optional |

### 2.2 Azure Kubernetes 환경 고려사항

**인프라 구성**:
- **AKS (Azure Kubernetes Service)**: 컨테이너 오케스트레이션
- **Azure Cache for Redis**: 분산 캐시
- **Azure Container Registry (ACR)**: 컨테이너 이미지 저장소
- **Azure Database for PostgreSQL**: 관계형 데이터베이스
- **Azure Service Bus**: 메시지 큐 (Optional, RabbitMQ 대체 가능)
- **Azure Monitor + Application Insights**: 모니터링 및 로깅
- **Azure API Management**: API Gateway (Optional, Nginx Ingress 대체 가능)

**개발 환경 vs 운영 환경**:
- **개발 환경**: AKS 개발 클러스터, Redis Standard tier, PostgreSQL Basic tier
- **운영 환경**: AKS 운영 클러스터 (다중 노드), Redis Premium tier (HA), PostgreSQL General Purpose (HA)

---

## 3. 패턴별 상세 설계

### 3.1 Cache-Aside 패턴

#### 3.1.1 개요

**목적**: AI API 호출 비용 절감 및 응답 시간 단축

**적용 대상**:
- AI 서비스: 트렌드 분석 결과, 이벤트 추천 결과
- Content 서비스: 생성된 SNS 이미지
- User 서비스: 사업자번호 검증 결과

#### 3.1.2 Azure 구현 방식

**Azure Cache for Redis 구성**:
```yaml
# 개발 환경
tier: Standard
capacity: C1 (1GB)
availability: Single instance

# 운영 환경
tier: Premium
capacity: P1 (6GB)
availability: Zone redundant (고가용성)
```

**동작 흐름**:
```
1. 요청 수신 → Redis GET {key}
2. Cache HIT:
   - 즉시 반환 (응답 시간 ~100ms)
3. Cache MISS:
   - 외부 API 호출 (응답 시간 5-10초)
   - Redis SET {key} {value} EX {TTL}
   - 결과 반환
```

**캐시 키 설계**:
```
ai:trend:{industry}:{region}:{season}
ai:recommendation:{industry}:{region}:{purpose}
content:image:{event_id}:{style}
user:business:{business_number}
```

**TTL 정책**:
- AI 트렌드 분석: **24시간** (트렌드 변화 주기 고려)
- AI 이벤트 추천: **12시간** (빈번한 업데이트)
- 생성 이미지: **7일** (재사용 가능성)
- 사업자번호 검증: **30일** (변경 빈도 낮음)

#### 3.1.3 Kubernetes 배포

```yaml
# redis-deployment.yaml (개발/운영 공통)
apiVersion: v1
kind: Service
metadata:
  name: redis-cache
spec:
  type: LoadBalancer
  ports:
  - port: 6379
  selector:
    app: redis

---
# Azure Cache for Redis 연결 시 Secret
apiVersion: v1
kind: Secret
metadata:
  name: redis-secret
type: Opaque
data:
  connection-string: <base64-encoded-connection-string>
```

#### 3.1.4 기대 효과

| 지표 | Before | After (캐시 히트) | 개선율 |
|------|--------|-----------------|--------|
| AI 응답 시간 | 10초 | 0.1초 | **99%** |
| 이미지 생성 시간 | 5초 | 0.1초 | **98%** |
| AI API 비용 | $600/월 | $120/월 | **80% 절감** |
| 이미지 API 비용 | $600/월 | $120/월 | **80% 절감** |

---

### 3.2 API Gateway 패턴

#### 3.2.1 개요

**목적**: 중앙집중식 인증, 라우팅, Rate Limiting

**주요 기능**:
1. **인증/인가**: JWT 토큰 검증
2. **라우팅**: URL 기반 서비스 라우팅
3. **Rate Limiting**: API 호출 제한
4. **로깅**: 중앙집중식 접근 로그
5. **SSL 종료**: HTTPS 처리

#### 3.2.2 Azure 구현 옵션

**옵션 1: Azure API Management (권장 - 운영 환경)**
```yaml
특징:
- 완전 관리형 서비스
- 내장 인증/인가, Rate Limiting
- Azure Monitor 통합
- 높은 비용 (약 $50/월 이상)

장점:
- 운영 부담 최소화
- 기업급 기능 (개발자 포털, API 버전 관리)
- Azure 생태계 통합

단점:
- 비용 부담
- 커스터마이징 제한
```

**옵션 2: Nginx Ingress Controller (권장 - 개발 환경 / 비용 절감)**
```yaml
특징:
- AKS 내장 Ingress Controller
- 무료 (AKS 비용에 포함)
- 높은 커스터마이징

장점:
- 비용 효율적
- Kubernetes 네이티브
- 유연한 설정

단점:
- 수동 설정 필요
- 운영 부담
```

#### 3.2.3 Nginx Ingress 구현 (권장)

```yaml
# nginx-ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: api-gateway-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
    nginx.ingress.kubernetes.io/rate-limit: "100" # 100 req/min
    nginx.ingress.kubernetes.io/ssl-redirect: "true"
spec:
  ingressClassName: nginx
  tls:
  - hosts:
    - api.kt-event.com
    secretName: tls-secret
  rules:
  - host: api.kt-event.com
    http:
      paths:
      - path: /api/users
        pathType: Prefix
        backend:
          service:
            name: user-service
            port:
              number: 8080
      - path: /api/events
        pathType: Prefix
        backend:
          service:
            name: event-service
            port:
              number: 8080
      - path: /api/ai
        pathType: Prefix
        backend:
          service:
            name: ai-service
            port:
              number: 8080
      - path: /api/content
        pathType: Prefix
        backend:
          service:
            name: content-service
            port:
              number: 8080
      - path: /api/distribution
        pathType: Prefix
        backend:
          service:
            name: distribution-service
            port:
              number: 8080
      - path: /api/participation
        pathType: Prefix
        backend:
          service:
            name: participation-service
            port:
              number: 8080
      - path: /api/analytics
        pathType: Prefix
        backend:
          service:
            name: analytics-service
            port:
              number: 8080
```

**JWT 인증 미들웨어** (각 서비스에서 구현):
```java
// Spring Boot 예시
@Component
public class JwtAuthenticationFilter extends OncePerRequestFilter {

    @Override
    protected void doFilterInternal(HttpServletRequest request,
                                   HttpServletResponse response,
                                   FilterChain filterChain) {
        String token = extractToken(request);
        if (token != null && validateToken(token)) {
            // 인증 성공
            filterChain.doFilter(request, response);
        } else {
            // 401 Unauthorized
            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
        }
    }
}
```

#### 3.2.4 기대 효과

| 항목 | 효과 |
|------|------|
| 개발 생산성 | 각 서비스 인증 로직 제거 → 개발 시간 **30% 단축** |
| 보안 강화 | 중앙집중식 보안 정책 관리 |
| 운영 효율 | 통합 모니터링 및 로깅 |
| 비용 절감 | Nginx Ingress 사용 시 **무료** (vs Azure API Management $50/월) |

---

### 3.3 Asynchronous Request-Reply 패턴

#### 3.3.1 개요

**목적**: 장시간 작업의 사용자 대기 시간 제거

**적용 대상**:
- AI 서비스: 트렌드 분석 및 이벤트 추천 (10초 소요)
- Content 서비스: SNS 이미지 생성 (5초 소요)

#### 3.3.2 Azure 구현 방식

**옵션 1: Azure Service Bus (권장 - 운영 환경)**
```yaml
특징:
- 완전 관리형 메시지 큐
- 높은 안정성 및 가용성
- Azure Monitor 통합

비용:
- Basic tier: $0.05/million operations
- Standard tier: $10/월 기본 + $0.80/million operations

장점:
- 운영 부담 최소화
- 엔터프라이즈급 안정성
- Azure 생태계 통합
```

**옵션 2: RabbitMQ (권장 - 개발 환경 / 비용 절감)**
```yaml
특징:
- 오픈소스 메시지 브로커
- AKS에 직접 배포
- 무료 (인프라 비용만)

장점:
- 비용 효율적
- 높은 커스터마이징
- Kubernetes 네이티브 배포

단점:
- 운영 부담 (HA, 백업)
```

#### 3.3.3 RabbitMQ 구현 (권장)

**Kubernetes 배포**:
```yaml
# rabbitmq-deployment.yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: rabbitmq
spec:
  serviceName: rabbitmq
  replicas: 1 # 개발: 1, 운영: 3 (HA)
  selector:
    matchLabels:
      app: rabbitmq
  template:
    metadata:
      labels:
        app: rabbitmq
    spec:
      containers:
      - name: rabbitmq
        image: rabbitmq:3.12-management
        ports:
        - containerPort: 5672
          name: amqp
        - containerPort: 15672
          name: management
        env:
        - name: RABBITMQ_DEFAULT_USER
          value: "admin"
        - name: RABBITMQ_DEFAULT_PASS
          valueFrom:
            secretKeyRef:
              name: rabbitmq-secret
              key: password
        volumeMounts:
        - name: rabbitmq-data
          mountPath: /var/lib/rabbitmq
  volumeClaimTemplates:
  - metadata:
      name: rabbitmq-data
    spec:
      accessModes: [ "ReadWriteOnce" ]
      resources:
        requests:
          storage: 10Gi

---
apiVersion: v1
kind: Service
metadata:
  name: rabbitmq
spec:
  ports:
  - port: 5672
    name: amqp
  - port: 15672
    name: management
  selector:
    app: rabbitmq
```

**동작 흐름**:
```
1. 클라이언트 요청
   → 즉시 Job ID 반환 (응답 시간 ~100ms)

2. 백그라운드 처리
   → RabbitMQ에 Job 메시지 발행
   → Worker가 Job 처리 (10초)
   → 결과를 Redis에 저장

3. 클라이언트 폴링
   → GET /api/jobs/{id}
   → Redis에서 Job 상태 확인
   → 완료 시 결과 반환
```

**Job 상태 관리** (Redis):
```
job:{job_id}:status = "pending" | "processing" | "completed" | "failed"
job:{job_id}:result = {result_data}
job:{job_id}:progress = 0-100 (%)
TTL: 1시간
```

#### 3.3.4 Spring Boot 구현 예시

```java
// AI 서비스 - Job 생성
@PostMapping("/api/ai/recommendations")
public ResponseEntity<JobResponse> createRecommendationJob(@RequestBody RecommendationRequest request) {
    String jobId = UUID.randomUUID().toString();

    // Redis에 Job 상태 저장
    redisTemplate.opsForValue().set("job:" + jobId + ":status", "pending", 1, TimeUnit.HOURS);

    // RabbitMQ에 Job 발행
    rabbitTemplate.convertAndSend("ai.queue", new JobMessage(jobId, request));

    return ResponseEntity.ok(new JobResponse(jobId, "pending"));
}

// Worker - Job 처리
@RabbitListener(queues = "ai.queue")
public void processRecommendationJob(JobMessage message) {
    String jobId = message.getJobId();

    // Job 상태 업데이트: processing
    redisTemplate.opsForValue().set("job:" + jobId + ":status", "processing");

    try {
        // AI API 호출 (10초 소요)
        String result = callClaudeAPI(message.getRequest());

        // 결과 저장
        redisTemplate.opsForValue().set("job:" + jobId + ":result", result, 1, TimeUnit.HOURS);
        redisTemplate.opsForValue().set("job:" + jobId + ":status", "completed");

        // 캐시에도 저장 (Cache-Aside)
        String cacheKey = "ai:recommendation:" + getCacheKey(message.getRequest());
        redisTemplate.opsForValue().set(cacheKey, result, 24, TimeUnit.HOURS);

    } catch (Exception e) {
        redisTemplate.opsForValue().set("job:" + jobId + ":status", "failed");
        redisTemplate.opsForValue().set("job:" + jobId + ":error", e.getMessage());
    }
}

// Job 상태 조회
@GetMapping("/api/jobs/{jobId}")
public ResponseEntity<JobStatusResponse> getJobStatus(@PathVariable String jobId) {
    String status = redisTemplate.opsForValue().get("job:" + jobId + ":status");

    if ("completed".equals(status)) {
        String result = redisTemplate.opsForValue().get("job:" + jobId + ":result");
        return ResponseEntity.ok(new JobStatusResponse(jobId, status, result));
    } else {
        return ResponseEntity.ok(new JobStatusResponse(jobId, status, null));
    }
}
```

#### 3.3.5 기대 효과

| 지표 | Before | After | 개선 |
|------|--------|-------|------|
| 사용자 대기 시간 | 10초 | 0.1초 (즉시 응답) | **99% 개선** |
| 동시 처리 가능 요청 | 10 req/sec | 50 req/sec | **5배 증가** |
| 서버 리소스 효율 | 동기 대기로 낭비 | 최적화 | **30% 절감** |

---

### 3.4 Circuit Breaker 패턴 (Optional)

#### 3.4.1 개요

**목적**: 외부 API 장애 시 서비스 격리 및 빠른 실패

**적용 대상**:
- 모든 외부 API 연동 지점 (7개 API)

#### 3.4.2 구현 방식 (Resilience4j)

**의존성 추가** (Spring Boot):
```xml
<dependency>
    <groupId>io.github.resilience4j</groupId>
    <artifactId>resilience4j-spring-boot3</artifactId>
    <version>2.1.0</version>
</dependency>
```

**설정** (application.yml):
```yaml
resilience4j:
  circuitbreaker:
    configs:
      default:
        slidingWindowSize: 10
        minimumNumberOfCalls: 5
        failureRateThreshold: 50 # 50% 실패 시 Open
        waitDurationInOpenState: 30s
        permittedNumberOfCallsInHalfOpenState: 3
    instances:
      claudeAPI:
        baseConfig: default
      stableDiffusionAPI:
        baseConfig: default
      taxAPI:
        baseConfig: default
      distributionAPIs:
        baseConfig: default
```

**코드 예시**:
```java
@Service
public class ClaudeAPIClient {

    @CircuitBreaker(name = "claudeAPI", fallbackMethod = "getRecommendationFallback")
    public String getRecommendation(RecommendationRequest request) {
        // Claude API 호출
        return restTemplate.postForObject(CLAUDE_API_URL, request, String.class);
    }

    // Fallback: 캐시된 결과 반환 또는 기본 메시지
    public String getRecommendationFallback(RecommendationRequest request, Exception e) {
        log.warn("Claude API circuit breaker activated, using fallback", e);

        // 캐시에서 유사한 이전 결과 조회
        String cachedResult = getCachedRecommendation(request);

        if (cachedResult != null) {
            return cachedResult;
        }

        // 기본 메시지
        return "AI 서비스가 일시적으로 이용 불가합니다. 잠시 후 다시 시도해주세요.";
    }
}
```

#### 3.4.3 Fallback 전략

| 서비스 | 외부 API | Fallback 전략 |
|--------|---------|--------------|
| AI | Claude API | 캐시된 이전 추천 결과 + 안내 메시지 |
| Content | Stable Diffusion | 기본 템플릿 이미지 + 안내 메시지 |
| User | 국세청 API | 사업자번호 검증 스킵 (수동 확인으로 대체) |
| Distribution | 각 채널 API | 해당 채널 배포 스킵 + 알림 |

#### 3.4.4 모니터링 (Azure Monitor)

**커스텀 메트릭**:
```java
@Component
public class CircuitBreakerMetrics {

    private final MeterRegistry meterRegistry;
    private final CircuitBreakerRegistry circuitBreakerRegistry;

    @PostConstruct
    public void registerMetrics() {
        circuitBreakerRegistry.getAllCircuitBreakers().forEach(cb -> {
            Gauge.builder("circuit.breaker.state", cb,
                this::getStateValue)
                .tag("name", cb.getName())
                .register(meterRegistry);

            cb.getEventPublisher()
                .onStateTransition(event -> {
                    log.info("Circuit Breaker {} state changed: {} -> {}",
                        event.getCircuitBreakerName(),
                        event.getStateTransition().getFromState(),
                        event.getStateTransition().getToState());
                });
        });
    }

    private int getStateValue(CircuitBreaker cb) {
        switch (cb.getState()) {
            case CLOSED: return 0;
            case OPEN: return 1;
            case HALF_OPEN: return 2;
            default: return -1;
        }
    }
}
```

#### 3.4.5 기대 효과

| 지표 | Before | After | 개선 |
|------|--------|-------|------|
| 시스템 가용성 | 95% | 99% | **+4%p** |
| 장애 복구 시간 | 5분 (수동) | 30초 (자동) | **90% 단축** |
| 외부 API 장애 격리 | ❌ 전체 중단 | ✅ 독립 동작 | - |

---

## 4. 전체 아키텍처

### 4.1 Azure Kubernetes 기반 아키텍처

```
┌─────────────────────────────────────────────────────────────────┐
│                        Azure Cloud                               │
│                                                                   │
│  ┌────────────────────────────────────────────────────────────┐ │
│  │              Azure Kubernetes Service (AKS)                 │ │
│  │                                                              │ │
│  │  ┌─────────────────────────────────────────────────────┐   │ │
│  │  │         Nginx Ingress Controller                     │   │ │
│  │  │  - JWT 인증                                          │   │ │
│  │  │  - Rate Limiting                                     │   │ │
│  │  │  - SSL 종료                                          │   │ │
│  │  └─────────────────────────────────────────────────────┘   │ │
│  │                           │                                  │ │
│  │    ┌──────────────────────┼──────────────────────┐          │ │
│  │    │                      │                       │          │ │
│  │  ┌─▼───┐  ┌─────┐  ┌─────▼──┐  ┌────────┐  ┌───▼────┐     │ │
│  │  │User │  │Event│  │   AI   │  │Content │  │  Dist  │     │ │
│  │  │ Svc │  │ Svc │  │  Svc   │  │  Svc   │  │  Svc   │     │ │
│  │  └──┬──┘  └──┬──┘  └───┬────┘  └───┬────┘  └───┬────┘     │ │
│  │     │        │          │            │           │          │ │
│  │     └────────┴──────────┴────────────┴───────────┘          │ │
│  │                         │                                    │ │
│  │                    ┌────▼─────┐                              │ │
│  │                    │RabbitMQ  │  (Async Request-Reply)       │ │
│  │                    │ Worker   │                              │ │
│  │                    └──────────┘                              │ │
│  └──────────────────────────────────────────────────────────── │ │
│                                                                   │
│  ┌────────────────────────────────────────────────────────────┐ │
│  │      Azure Cache for Redis (Cache-Aside)                   │ │
│  │  - AI 결과 캐시                                             │ │
│  │  - 이미지 캐시                                              │ │
│  │  - Job 상태 관리                                            │ │
│  └────────────────────────────────────────────────────────────┘ │
│                                                                   │
│  ┌────────────────────────────────────────────────────────────┐ │
│  │      Azure Database for PostgreSQL                          │ │
│  │  - 사용자 데이터                                            │ │
│  │  - 이벤트 데이터                                            │ │
│  └────────────────────────────────────────────────────────────┘ │
│                                                                   │
│  ┌────────────────────────────────────────────────────────────┐ │
│  │      Azure Monitor + Application Insights                   │ │
│  │  - 로그 수집                                                │ │
│  │  - 메트릭 모니터링                                          │ │
│  │  - 알람                                                     │ │
│  └────────────────────────────────────────────────────────────┘ │
└───────────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────────┐
│                      외부 API (Circuit Breaker 적용)             │
├─────────────────────────────────────────────────────────────────┤
│  국세청 API │ Claude API │ Stable Diffusion │ 우리동네TV │...   │
└─────────────────────────────────────────────────────────────────┘
```

### 4.2 시퀀스 다이어그램 (AI 추천 플로우)

```
클라이언트 → Nginx Ingress: POST /api/ai/recommendations
Nginx Ingress → AI Service: JWT 검증 후 라우팅

AI Service → Redis: GET ai:recommendation:{key}

alt Cache HIT
    Redis → AI Service: 캐시된 결과
    AI Service → 클라이언트: 즉시 반환 (0.1초)
else Cache MISS
    AI Service → Redis: SET job:{id}:status = pending
    AI Service → RabbitMQ: 발행 Job Message
    AI Service → 클라이언트: Job ID 반환 (0.1초)

    RabbitMQ → Worker: Job 수신
    Worker → Redis: SET job:{id}:status = processing

    Worker → Claude API: AI 요청 (Circuit Breaker)

    alt API 성공
        Claude API → Worker: 결과 반환 (10초)
        Worker → Redis: SET ai:recommendation:{key} (TTL 24h)
        Worker → Redis: SET job:{id}:result
        Worker → Redis: SET job:{id}:status = completed
    else API 실패 (Circuit Open)
        Worker → Redis: GET 유사 캐시 결과
        Worker → Redis: SET job:{id}:result (Fallback)
        Worker → Redis: SET job:{id}:status = completed
    end

    loop 5초 간격 폴링
        클라이언트 → Nginx Ingress: GET /api/jobs/{id}
        Nginx Ingress → AI Service: 라우팅
        AI Service → Redis: GET job:{id}:status

        alt completed
            Redis → AI Service: status + result
            AI Service → 클라이언트: 최종 결과
        else processing
            Redis → AI Service: status + progress
            AI Service → 클라이언트: 진행 상황 (70%)
        end
    end
end
```

---

## 5. 개발/운영 환경 구성

### 5.1 개발 환경

**AKS 클러스터**:
```yaml
name: aks-dev-cluster
node_pool:
  vm_size: Standard_B2s (2 vCPU, 4GB RAM)
  node_count: 2
  auto_scaling: false

estimated_cost: ~$100/월
```

**Azure Cache for Redis**:
```yaml
tier: Standard
capacity: C1 (1GB)
availability: Single instance

estimated_cost: ~$20/월
```

**Azure Database for PostgreSQL**:
```yaml
tier: Basic
compute: B_Gen5_1 (1 vCore)
storage: 50GB

estimated_cost: ~$30/월
```

**RabbitMQ**:
```yaml
deployment: StatefulSet (1 replica)
storage: 10GB PVC

estimated_cost: 포함 (AKS 노드)
```

**총 예상 비용**: **~$150/월**

### 5.2 운영 환경

**AKS 클러스터**:
```yaml
name: aks-prod-cluster
node_pool:
  vm_size: Standard_D2s_v3 (2 vCPU, 8GB RAM)
  node_count: 3 (다중 가용 영역)
  auto_scaling: true (min: 3, max: 10)

estimated_cost: ~$300/월 (기본), ~$1,000/월 (최대)
```

**Azure Cache for Redis**:
```yaml
tier: Premium
capacity: P1 (6GB)
availability: Zone redundant (고가용성)

estimated_cost: ~$250/월
```

**Azure Database for PostgreSQL**:
```yaml
tier: General Purpose
compute: GP_Gen5_2 (2 vCore)
storage: 100GB
availability: Zone redundant

estimated_cost: ~$150/월
```

**RabbitMQ**:
```yaml
deployment: StatefulSet (3 replicas, HA)
storage: 30GB PVC per replica

estimated_cost: 포함 (AKS 노드)
```

**Azure Monitor + Application Insights**:
```yaml
estimated_cost: ~$50/월
```

**총 예상 비용**: **~$750/월** (기본), **~$1,450/월** (최대)

---

## 6. 구현 로드맵

### 6.1 MVP 일정 (12주)

| 주차 | 작업 내용 | 패턴 적용 | 담당 |
|------|----------|-----------|------|
| **1주** | Azure 인프라 구축 | - | DevOps |
| | - AKS 클러스터 생성 (개발/운영) | | |
| | - Azure Cache for Redis 생성 | | |
| | - Azure Database for PostgreSQL 생성 | | |
| | - Azure Container Registry 생성 | | |
| **2주** | API Gateway 구축 | API Gateway | DevOps + Backend |
| | - Nginx Ingress Controller 배포 | | |
| | - SSL 인증서 설정 | | |
| | - JWT 인증 미들웨어 구현 | | |
| **3-4주** | User/Event 서비스 | Cache-Aside | Backend |
| | - 회원가입/로그인 구현 | | |
| | - 사업자번호 검증 + 캐싱 | | |
| | - 이벤트 CRUD 구현 | | |
| **5-6주** | AI 서비스 | Async + Cache-Aside | Backend |
| | - Claude API 연동 | | |
| | - RabbitMQ 배포 및 Worker 구현 | | |
| | - Job 기반 비동기 처리 | | |
| | - AI 결과 캐싱 (24h TTL) | | |
| **7-8주** | Content 서비스 | Async + Cache-Aside | Backend |
| | - Stable Diffusion API 연동 | | |
| | - 이미지 생성 Job 처리 | | |
| | - 이미지 캐싱 및 Azure Blob Storage | | |
| **9-10주** | Distribution 서비스 | Circuit Breaker | Backend |
| | - 7개 외부 API 연동 | | |
| | - Resilience4j Circuit Breaker 적용 | | |
| | - Fallback 전략 구현 | | |
| **11주** | Participation/Analytics | Cache-Aside | Backend |
| | - 참여자 관리 및 추첨 | | |
| | - 대시보드 데이터 캐싱 (5분 TTL) | | |
| **12주** | 테스트 및 출시 | 전체 패턴 검증 | 전체 팀 |
| | - 부하 테스트 (k6, 100명) | | |
| | - 장애 시나리오 테스트 | | |
| | - Azure Monitor 알람 설정 | | |
| | - MVP 출시 | | |

### 6.2 기술 스택

**백엔드**:
- Java 17 + Spring Boot 3.2
- Resilience4j 2.1 (Circuit Breaker)
- Spring Data JPA + PostgreSQL
- Spring Data Redis
- Spring AMQP + RabbitMQ

**컨테이너 & 오케스트레이션**:
- Docker 24
- Kubernetes 1.28 (AKS)
- Nginx Ingress Controller 1.9
- Helm 3.13

**Azure 서비스**:
- Azure Kubernetes Service (AKS)
- Azure Cache for Redis
- Azure Database for PostgreSQL
- Azure Container Registry (ACR)
- Azure Monitor + Application Insights
- Azure Blob Storage (이미지 저장)

**모니터링 & 로깅**:
- Azure Monitor (메트릭)
- Application Insights (APM)
- Grafana (대시보드)
- Azure Log Analytics (로그 쿼리)

---

## 7. 예상 성과

### 7.1 성능 개선

| 항목 | Before | After (캐시 히트) | 개선율 |
|------|--------|-----------------|--------|
| AI 응답 시간 | 10초 | 0.1초 | **99%** |
| 이미지 생성 시간 | 5초 | 0.1초 | **98%** |
| 대시보드 로딩 시간 | 3초 | 0.5초 | **83%** |
| 동시 처리 가능 요청 | 10 req/sec | 50 req/sec | **5배** |

### 7.2 비용 절감

**AI API 비용** (캐시 히트율 80% 가정):
- Before: $600/월
- After: $120/월
- **절감액**: $480/월 (**80% 절감**)

**이미지 API 비용** (캐시 히트율 80% 가정):
- Before: $600/월
- After: $120/월
- **절감액**: $480/월 (**80% 절감**)

**총 API 비용 절감**: **$960/월** (**80% 절감**)

**Azure 인프라 비용**:
- 개발 환경: ~$150/월
- 운영 환경: ~$750/월 (기본), ~$1,450/월 (최대)

### 7.3 가용성 개선

| 지표 | Before | After | 개선 |
|------|--------|-------|------|
| 시스템 가용성 | 95% | 99% | **+4%p** |
| 외부 API 장애 시 서비스 지속 | ❌ 불가 | ✅ 가능 | - |
| 장애 자동 복구 시간 | 5분 (수동) | 30초 (자동) | **90% 단축** |

---

## 8. 모니터링 및 운영

### 8.1 Azure Monitor 메트릭

**AKS 클러스터**:
- CPU/메모리 사용률
- 노드 상태
- Pod 상태
- Ingress 요청 수 및 응답 시간

**Azure Cache for Redis**:
- 캐시 히트율 (목표: 80% 이상)
- 메모리 사용률 (목표: 70% 이하)
- 응답 시간 (목표: 100ms 이하)
- 연결 수

**Azure Database for PostgreSQL**:
- CPU/메모리 사용률
- 디스크 I/O
- 활성 연결 수
- 슬로우 쿼리

**Application Insights (APM)**:
- 서비스별 응답 시간
- 의존성 호출 (외부 API)
- 예외 및 에러
- 사용자 트래픽

### 8.2 커스텀 메트릭

**Circuit Breaker**:
- API별 실패율
- Circuit 상태 (Closed/Open/Half-Open)
- Fallback 호출 횟수

**Async Jobs**:
- Job 처리 시간
- 동시 Job 수
- Job 완료율
- Queue 길이 (RabbitMQ)

### 8.3 알람 임계값

| 지표 | Warning | Critical | 액션 |
|------|---------|----------|------|
| 캐시 히트율 | < 70% | < 50% | 캐시 전략 검토 |
| Redis 메모리 | > 80% | > 90% | 스케일업 |
| API 응답 시간 | > 500ms | > 1000ms | 성능 조사 |
| Circuit Breaker Open | 1개 | 3개 이상 | 긴급 대응 |
| Pod CPU | > 70% | > 90% | Pod 스케일아웃 |
| Pod 메모리 | > 80% | > 95% | Pod 재시작 |

### 8.4 로그 수집 및 분석

**Azure Log Analytics**:
```kusto
// 에러 로그 분석
ContainerLog
| where LogEntry contains "ERROR"
| summarize count() by Computer, ContainerID
| order by count_ desc

// API 응답 시간 분석
requests
| where url contains "/api/"
| summarize avg(duration), percentile(duration, 95) by name
| order by avg_duration desc

// Circuit Breaker 상태 변화 추적
traces
| where message contains "Circuit Breaker"
| project timestamp, message, severityLevel
| order by timestamp desc
```

---

## 9. 장애 대응 절차

### 9.1 Circuit Breaker Open 발생

**대응 절차**:
1. 알람 수신 (Azure Monitor → Slack/Email)
2. Application Insights에서 해당 외부 API 호출 현황 확인
3. Fallback 전략 정상 동작 확인 (로그 분석)
4. 30초 후 자동 Half-Open 전환 확인
5. 복구 실패 시:
   - 외부 API 제공사 상태 확인
   - 긴급 연락
   - 장기 장애 시 사용자 공지

### 9.2 캐시 장애

**대응 절차**:
1. Azure Cache for Redis 상태 확인 (Azure Portal)
2. Zone Redundancy 자동 Failover 확인 (운영 환경)
3. 캐시 미스로 전환 (성능 저하 허용)
4. Redis 복구:
   - 개발: 인스턴스 재시작
   - 운영: Azure 자동 복구 대기 또는 수동 Failover

### 9.3 AKS 노드 장애

**대응 절차**:
1. Azure Monitor에서 노드 상태 확인
2. Kubernetes 자동 재스케줄링 확인
3. Pod가 정상 노드로 이동 확인
4. 장애 노드 제거 및 새 노드 추가 (Auto Scaling)

---

## 10. 체크리스트

### 10.1 패턴 적용 완료 확인

- [ ] **Cache-Aside**: AI 결과, 이미지, 사업자번호 검증 캐싱 완료
- [ ] **API Gateway**: Nginx Ingress + JWT 인증 + Rate Limiting 완료
- [ ] **Asynchronous Request-Reply**: RabbitMQ + Worker 기반 Job 처리 완료
- [ ] **Circuit Breaker**: Resilience4j 적용 및 Fallback 전략 구현 완료

### 10.2 성능 목표 달성 확인

- [ ] AI 응답 시간: 10초 이내 (캐시 미스), 0.1초 (캐시 히트)
- [ ] 캐시 히트율: 80% 이상
- [ ] 시스템 가용성: 99% 이상
- [ ] 동시 처리 가능 요청: 50 req/sec 이상

### 10.3 Azure 인프라 구축 완료 확인

- [ ] AKS 클러스터 생성 (개발/운영)
- [ ] Azure Cache for Redis 구성 및 연결
- [ ] Azure Database for PostgreSQL 구성 및 연결
- [ ] Azure Container Registry 구성 및 CI/CD 연동
- [ ] Nginx Ingress Controller 배포 및 설정
- [ ] SSL 인증서 적용
- [ ] Azure Monitor + Application Insights 통합

### 10.4 운영 준비 완료 확인

- [ ] 모니터링 대시보드 구축 (Azure Monitor + Grafana)
- [ ] 알람 설정 완료 (Slack/Email)
- [ ] 장애 대응 매뉴얼 작성
- [ ] 부하 테스트 완료 (k6, 100명)
- [ ] 장애 시나리오 테스트 완료 (Circuit Breaker, 캐시 장애)

---

## 11. 다음 단계 (Phase 2 이후)

**MVP 이후 확장 계획** (선택 사항):

- **Retry 패턴**: 일시적 오류 자동 재시도 (현재는 Circuit Breaker로 커버)
- **Queue-Based Load Leveling**: 트래픽 폭증 시 부하 분산
- **Saga 패턴**: 복잡한 분산 트랜잭션 관리 (이벤트 생성 플로우)
- **CQRS**: 읽기/쓰기 분리로 대시보드 성능 최적화
- **Event Sourcing**: 이벤트 변경 이력 추적 및 감사
- **Service Mesh (Istio)**: 고급 트래픽 관리 및 보안
- **Azure Front Door**: 글로벌 CDN 및 WAF
- **Azure Key Vault**: 시크릿 관리 강화

---

## 참고 문서

- [유저스토리](../userstory.md)
- [UI/UX 설계서](../uiux/uiux.md)
- [클라우드 디자인 패턴 개요](../../claude/cloud-design-patterns.md)
- [Azure Kubernetes Service 공식 문서](https://learn.microsoft.com/ko-kr/azure/aks/)
- [Azure Cache for Redis 공식 문서](https://learn.microsoft.com/ko-kr/azure/azure-cache-for-redis/)
- [Resilience4j 공식 문서](https://resilience4j.readme.io/)
- [백업 파일](./backup/) - 이전 버전
