[AI] 08_ADR_ 041‐045 - 100-hours-a-week/9-team-Devths-WIKI GitHub Wiki
ADR 041-045: 인프라 확장 및 하이브리드 스케일링
Architecture Decision Records (ADR) 041-045
인프라 확장성 및 하이브리드 스케일링 전략
📚 목차
ADR-041: 하이브리드 스케일링 전략 (RunPod + Lambda)
📋 메타데이터
| 항목 | 내용 |
|---|---|
| 상태 | ✅ 승인됨 (Accepted) |
| 작성일 | 2026-01-14 |
| 결정자 | AI/인프라팀 |
| 관련 기능 | GPU 서버, 서버리스, 로드 밸런싱, 오토스케일링 |
🎯 컨텍스트 (Context)
AI 서비스의 트래픽 패턴을 분석한 결과, 평시와 피크 타임의 부하 차이가 명확합니다.
트래픽 패턴:
- 평시 부하: 70% (예측 가능, 안정적)
- 피크 부하: +30% (점심시간, 저녁시간, 주말)
문제점:
- RunPod 단독 사용 시 피크 타임 대비 과도한 리소스 할당 필요
- 평시에는 30% 리소스 유휴 상태 → 비용 낭비
- 오토스케일링만으로는 GPU 서버의 빠른 확장 어려움
요구사항:
- 평시 부하는 안정적으로 처리 (RunPod)
- 피크 부하는 유연하게 대응 (서버리스)
- 비용 최적화 (유휴 리소스 최소화)
- 안정성 확보 (이중화)
🔍 선택지 분석 (Options)
Option 1: RunPod 단독 (피크 대비 스펙)
┌─────────────────────────────────────────────────────────┐
│ RunPod 단독 (100% 처리) │
├─────────────────────────────────────────────────────────┤
│ │
│ [RunPod 서버] │
│ ├─ GPU: RTX 4090 │
│ ├─ 스펙: 피크 타임 대비 (100%) │
│ ├─ 비용: $500/월 │
│ └─ 평시 유휴: 30% (낭비) │
│ │
└─────────────────────────────────────────────────────────┘
| 장점 | 단점 |
|---|---|
| 단순한 구조 | 평시 30% 유휴 리소스 |
| 안정적 성능 | 높은 비용 ($500/월) |
| 관리 용이 | 확장성 제한 |
Option 2: Lambda 단독 (서버리스)
┌─────────────────────────────────────────────────────────┐
│ Lambda 단독 (100% 처리) │
├─────────────────────────────────────────────────────────┤
│ │
│ [Lambda 함수] │
│ ├─ 자동 스케일링 │
│ ├─ 사용량 기반 과금 │
│ ├─ 비용: $100/월 (예상) │
│ └─ Cold Start 이슈 │
│ │
└─────────────────────────────────────────────────────────┘
| 장점 | 단점 |
|---|---|
| 사용량 기반 과금 | Cold Start 지연 (1~3초) |
| 무제한 확장 | GPU 미지원 |
| 관리 부담 없음 | 실행 시간 제한 (15분) |
Option 3: 하이브리드 (RunPod + Lambda) ⭐
┌─────────────────────────────────────────────────────────┐
│ 하이브리드 스케일링 │
├─────────────────────────────────────────────────────────┤
│ │
│ [사용자 요청] │
│ ↓ │
│ [API Gateway / ALB] ← 로드 밸런서 │
│ ├─ 라우팅 규칙 │
│ ├─ 헬스 체크 │
│ └─ 트래픽 분산 │
│ ↓ │
│ ┌──────────────────┬──────────────────┐ │
│ │ │ │ │
│ │ [RunPod 서버] │ [Lambda 함수] │ │
│ │ (베이스 라인) │ (버스트) │ │
│ │ │ │ │
│ │ 평시 부하 70% │ 피크 부하 30% │ │
│ │ ├─ GPU 서버 │ ├─ 서버리스 │ │
│ │ ├─ 항상 ON │ ├─ 피크만 ON │ │
│ │ └─ $350/월 │ └─ $30/월 │ │
│ │ │ │ │
│ └──────────────────┴──────────────────┘ │
│ ↓ ↓ │
│ [AI 모델 추론] │
│ │
│ 총 비용: $380/월 (RunPod 단독 대비 24% 절감) │
│ │
└─────────────────────────────────────────────────────────┘
| 장점 | 단점 |
|---|---|
| 비용 최적화 (24% 절감) | 구현 복잡도 증가 |
| 안정성 확보 (이중화) | 두 시스템 관리 필요 |
| 유연한 확장 (무제한) | 라우팅 로직 필요 |
| 유휴 리소스 최소화 | 모니터링 복잡 |
✅ 결정 (Decision)
Option 3: 하이브리드 스케일링 전략 채택
| 버전 | 구성 | 이유 |
|---|---|---|
| V1~V2 | RunPod 단독 | MVP, 트래픽 패턴 파악 |
| V3 | RunPod + Lambda | 비용 최적화, 안정성 |
| V4 | RunPod + Lambda + K8s | 대규모 확장 |
📝 근거 (Rationale)
1. 트래픽 패턴 분석
실제 트래픽 데이터 (예상):
시간대별 요청 수:
00:00-06:00: 10 req/min (10%)
06:00-09:00: 50 req/min (50%)
09:00-12:00: 70 req/min (70%) ← 평시
12:00-14:00: 100 req/min (100%) ← 피크!
14:00-18:00: 70 req/min (70%)
18:00-21:00: 90 req/min (90%) ← 피크!
21:00-24:00: 40 req/min (40%)
평균: 70 req/min (평시)
피크: 100 req/min (점심, 저녁)
부하 분석:
- 평시 (70%): RunPod로 안정적 처리
- 피크 (+30%): Lambda로 버스트 처리
2. 비용 분석
RunPod 단독 (피크 대비):
RunPod 서버:
- GPU: RTX 4090
- 스펙: 100% 처리 가능
- 비용: $500/월
- 평시 유휴: 30% ($150/월 낭비)
총 비용: $500/월
하이브리드 (RunPod 70% + Lambda 30%):
RunPod 서버:
- GPU: RTX 4090
- 스펙: 70% 처리 (다운사이징)
- 비용: $350/월
Lambda 함수:
- 피크 타임만 활성화
- 30,000 requests/월
- 비용: $30/월
총 비용: $380/월
절감: $120/월 (24%)
3. 라우팅 전략
스마트 라우팅 로직:
# routing-logic.py
import boto3
from datetime import datetime
cloudwatch = boto3.client('cloudwatch')
def route_request(request):
"""스마트 라우팅 - RunPod vs Lambda"""
# 1. RunPod 서버 상태 확인
runpod_cpu = get_runpod_cpu_usage()
runpod_healthy = check_runpod_health()
# 2. 라우팅 결정
if runpod_healthy and runpod_cpu < 70:
# RunPod 여유 있음 → RunPod 사용
return route_to_runpod(request)
else:
# RunPod 부하 높음 → Lambda 사용
return route_to_lambda(request)
def get_runpod_cpu_usage():
"""RunPod CPU 사용률 조회"""
response = cloudwatch.get_metric_statistics(
Namespace='RunPod',
MetricName='CPUUtilization',
Dimensions=[{'Name': 'ServerID', 'Value': 'runpod-1'}],
StartTime=datetime.now() - timedelta(minutes=5),
EndTime=datetime.now(),
Period=300,
Statistics=['Average']
)
if response['Datapoints']:
return response['Datapoints'][0]['Average']
return 0
def check_runpod_health():
"""RunPod 헬스 체크"""
try:
response = requests.get('https://runpod-server.com/health', timeout=2)
return response.status_code == 200
except:
return False
def route_to_runpod(request):
"""RunPod으로 라우팅"""
return requests.post('https://runpod-server.com/api/inference', json=request)
def route_to_lambda(request):
"""Lambda로 라우팅"""
lambda_client = boto3.client('lambda')
response = lambda_client.invoke(
FunctionName='ai-burst-handler',
InvocationType='RequestResponse',
Payload=json.dumps(request)
)
return json.loads(response['Payload'].read())
4. Lambda 함수 구현
# lambda_function.py
import json
from langchain_google_genai import ChatGoogleGenerativeAI
def lambda_handler(event, context):
"""Lambda 함수 - 피크 타임 버스트 처리"""
try:
# 요청 파싱
body = json.loads(event['body']) if isinstance(event['body'], str) else event['body']
prompt = body.get('prompt')
model = body.get('model', 'gemini-3-flash')
# LLM 호출
llm = ChatGoogleGenerativeAI(model=model)
response = llm.invoke(prompt)
return {
'statusCode': 200,
'headers': {
'Content-Type': 'application/json',
'X-Source': 'lambda' # 디버깅용
},
'body': json.dumps({
'result': response.content,
'source': 'lambda',
'model': model
})
}
except Exception as e:
return {
'statusCode': 500,
'body': json.dumps({
'error': str(e),
'source': 'lambda'
})
}
5. API Gateway 설정
# api-gateway.yaml
Resources:
ApiGateway:
Type: AWS::ApiGatewayV2::Api
Properties:
Name: AI-Hybrid-Gateway
ProtocolType: HTTP
# RunPod 통합
RunPodIntegration:
Type: AWS::ApiGatewayV2::Integration
Properties:
ApiId: !Ref ApiGateway
IntegrationType: HTTP_PROXY
IntegrationUri: https://runpod-server.com/api
IntegrationMethod: POST
PayloadFormatVersion: '1.0'
# Lambda 통합
LambdaIntegration:
Type: AWS::ApiGatewayV2::Integration
Properties:
ApiId: !Ref ApiGateway
IntegrationType: AWS_PROXY
IntegrationUri: !GetAtt LambdaFunction.Arn
PayloadFormatVersion: '2.0'
# 라우트 (스마트 라우팅)
InferenceRoute:
Type: AWS::ApiGatewayV2::Route
Properties:
ApiId: !Ref ApiGateway
RouteKey: 'POST /inference'
Target: !Join
- /
- - integrations
- !Ref SmartRoutingIntegration
🔧 구현 예시
1. CloudWatch Alarm 설정
# cloudwatch-alarm.yaml
Resources:
RunPodHighCPUAlarm:
Type: AWS::CloudWatch::Alarm
Properties:
AlarmName: RunPod-High-CPU-Alarm
AlarmDescription: RunPod CPU 70% 초과 시 Lambda 활성화
MetricName: CPUUtilization
Namespace: RunPod
Statistic: Average
Period: 300 # 5분
EvaluationPeriods: 2
Threshold: 70
ComparisonOperator: GreaterThanThreshold
AlarmActions:
- !Ref LambdaScaleUpTopic
LambdaScaleUpTopic:
Type: AWS::SNS::Topic
Properties:
DisplayName: Lambda Scale Up Notification
Subscription:
- Endpoint: !GetAtt LambdaFunction.Arn
Protocol: lambda
2. 모니터링 대시보드
# monitoring-dashboard.py
import boto3
from datetime import datetime, timedelta
cloudwatch = boto3.client('cloudwatch')
def create_dashboard():
"""CloudWatch 대시보드 생성"""
dashboard_body = {
"widgets": [
{
"type": "metric",
"properties": {
"title": "RunPod CPU 사용률",
"metrics": [
["RunPod", "CPUUtilization", {"stat": "Average"}]
],
"period": 300,
"region": "us-east-1",
"yAxis": {"left": {"min": 0, "max": 100}}
}
},
{
"type": "metric",
"properties": {
"title": "Lambda 실행 횟수",
"metrics": [
["AWS/Lambda", "Invocations", {"stat": "Sum"}]
],
"period": 300,
"region": "us-east-1"
}
},
{
"type": "metric",
"properties": {
"title": "트래픽 분산 비율",
"metrics": [
["Custom", "RunPodRequests", {"stat": "Sum", "label": "RunPod"}],
["Custom", "LambdaRequests", {"stat": "Sum", "label": "Lambda"}]
],
"period": 300,
"region": "us-east-1"
}
}
]
}
cloudwatch.put_dashboard(
DashboardName='AI-Hybrid-Scaling',
DashboardBody=json.dumps(dashboard_body)
)
📊 비교표
| 항목 | RunPod 단독 | Lambda 단독 | 하이브리드 |
|---|---|---|---|
| 월 비용 | $500 | $100 | $380 ✅ |
| 평시 성능 | ⭐⭐⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐⭐⭐⭐ |
| 피크 성능 | ⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ |
| 안정성 | ⭐⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐⭐⭐⭐ |
| 확장성 | ⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ |
| 관리 복잡도 | 🔴 낮음 | 🔴🔴 중간 | 🔴🔴🔴 높음 |
| V3 적합성 | ⚠️ | ❌ | ✅ 추천 |
🎯 최종 추천
V1~V2 (MVP)
RunPod 단독
- 트래픽 패턴 파악
- 단순한 구조
- 비용: $500/월
V3 (하이브리드)
RunPod (70%) + Lambda (30%)
- 비용 최적화: $380/월
- 안정성 확보 (이중화)
- 유연한 확장
V4 (대규모)
RunPod + Lambda + K8s
- 무제한 확장
- 엔터프라이즈급 안정성
- 비용: $1,000+/월
💡 핵심 정리
하이브리드 스케일링 전략:
-
RunPod (베이스 라인): 평시 70% 부하 처리
- GPU 서버 (항상 ON)
- 안정적 성능
- $350/월
-
Lambda (버스트): 피크 30% 부하 처리
- 서버리스 (피크만 ON)
- 자동 스케일링
- $30/월
-
로드 밸런서: 스마트 라우팅
- RunPod CPU < 70% → RunPod
- RunPod CPU ≥ 70% → Lambda
이점:
- ✅ 비용 절감: 24% ($120/월)
- ✅ 안정성 향상: 이중화
- ✅ 유연한 확장: 무제한
- ✅ 유휴 리소스 최소화
📅 이력
| 날짜 | 변경 내용 |
|---|---|
| 2026-01-14 | 초기 결정 (하이브리드 스케일링 전략) |
ADR-042: (예정)
ADR-043: (예정)
ADR-044: (예정)
ADR-045: (예정)
🎊 결론
V3 하이브리드 스케일링 전략 완성!
| 구성 요소 | 역할 | 비용 |
|---|---|---|
| RunPod | 베이스 라인 (70%) | $350/월 |
| Lambda | 버스트 (30%) | $30/월 |
| API Gateway | 로드 밸런싱 | $10/월 |
| CloudWatch | 모니터링 | $5/월 |
| 총 비용 | - | $395/월 |
절감 효과: RunPod 단독 대비 21% 절감 ($500 → $395) ✅
이제 비용 효율적이고 안정적인 인프라가 완성되었습니다! 🎉