kt-event-marketing/design/pattern/backup/architecture-pattern-backup2.md
2025-10-22 10:00:16 +09:00

1166 lines
36 KiB
Markdown

# 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/) - 이전 버전