# 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: ``` #### 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 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 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 io.github.resilience4j resilience4j-spring-boot3 2.1.0 ``` **설정** (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/) - 이전 버전