FastAPI와 함께 탄력적인 AI 아키텍처 구축
Source: Dev.to

AI 기반 애플리케이션이 실험적인 프로토타입 단계에서 미션 크리티컬한 프로덕션 서비스로 전환함에 따라 탄력성, 확장성 및 내결함성이 가장 중요해집니다. 특히 Azure OpenAI와 같은 대형 언어 모델(LLM)을 활용하는 최신 AI 시스템은 네트워크 불안정, 할당량 제한, 지역 장애, 그리고 동적인 사용 패턴을 처리해야 합니다.
이 블로그에서는 다음과 같은 기술을 활용하여 탄력적인 AI 서비스를 설계하는 실용적인 가이드를 제공합니다:
- Python FastAPI 마이크로서비스
- Redis 캐싱 (AWS ElastiCache 사용)
- Azure OpenAI Provisioned Throughput Units (PTUs)
- 고급 재시도 로직 및 재해 복구 전략
- AWS Secrets Manager를 통한 보안 구성 관리
왜 회복탄력성은 AI에서 협상 불가인가
AI 서비스, 특히 LLM API에 의존하는 서비스는 고유한 운영 과제에 직면합니다:
| 도전 과제 | 영향 |
|---|---|
| 속도 및 할당량 제한 | API 제공자는 토큰/요청 상한을 부과합니다; 지능적인 처리가 필요합니다. |
| 일시적 실패 | 네트워크 중단 또는 서버 오류가 간헐적인 요청 실패를 초래합니다. |
| 지연 민감도 | 사용자는 거의 실시간 응답을 기대하며; 성능이 중요합니다. |
| 지역 장애 | 클라우드 장애가 전체 지리적 지역에 영향을 줄 수 있습니다. |
아키텍처 개요
비동기 FastAPI 마이크로서비스가 시스템의 핵심에 위치합니다. 이 서비스는 Azure OpenAI PTU와 통신하여 LLM 추론을 수행하고, Redis를 사용해 저지연 응답 캐싱을 제공합니다. 민감한 자격 증명 및 재시도 구성은 AWS Secrets Manager에 저장되며, 다중 지역 장애 조치는 Route 53 DNS 지오‑라우팅 및 상태 검사를 통해 조정됩니다.
이 계층형 설계는 성능과 내결함성을 모두 해결합니다:
- Redis는 불필요한 API 호출을 줄여줍니다.
- 재시도 로직은 간헐적인 네트워크 오류를 완화합니다.
- 다중 지역 배포는 대규모 장애 시 연속성을 보장합니다.

_Architecture of an Enterprise-Grade AI_
우리 아키텍처는 핵심 구성 요소를 활용하여 견고함을 보장합니다:

Source: …
핵심 복원력 활성화 요소 심층 탐구
FastAPI로 API 가속화
FastAPI는 비동기 Python 웹 프레임워크로, 높은 동시성 및 빠른 응답 시간을 제공하여 AI 백엔드 마이크로서비스에 이상적입니다.
from fastapi import FastAPI
app = FastAPI()
@app.get("/health")
async def health_check():
return {"status": "healthy"}
이 간단한 헬스 엔드포인트는 AWS Route 53이 제공하는 고가용성 라우팅 전략에 필수적입니다.
구성 레이어: 안전하고 동적인 설정
코드에 자격 증명이나 재시도 파라미터를 포함하면 보안 위험과 운영 경직성이 발생합니다. 대신 이 아키텍처는 시작 시 AWS Secrets Manager에서 비밀(예: API 키, 재시도 정책)을 가져와 Python의 @lru_cache 데코레이터를 사용해 메모리에 캐시합니다.
import boto3
import json
from functools import lru_cache
@lru_cache()
def get_secrets(secret_name: str = "prod/llm-config") -> dict:
client = boto3.client("secretsmanager")
response = client.get_secret_value(SecretId=secret_name)
return json.loads(response["SecretString"])
동적인 비밀 조회를 통해 재시도 정책이나 API 키와 같은 설정을 서비스 재배포 없이 업데이트할 수 있습니다.
복원력 레이어: 지능형 재시도와 장애 전환
분산 시스템에서 실패는 불가피합니다; 목표는 이를 우아하게 처리하는 것입니다. 우리의 복원력 전략은 세 가지 핵심 개념에 기반합니다:
1. 다중 PTU 엔드포인트를 이용한 중복성
Azure OpenAI의 Provisioned Throughput Unit (PTU) 은 처리 용량을 보장하지만, 단일 PTU는 병목이 되거나 지역 문제 시 장애가 발생할 수 있습니다. 이를 완화하기 위해 여러 Azure 지역(예: East US, West Europe) 에 걸쳐 다중 PTU 를 프로비저닝합니다. 애플리케이션은 이러한 PTU 엔드포인트를 풀로 취급하며, 하나의 엔드포인트에 요청이 실패하면 자동으로 다음 엔드포인트로 재시도하여 로드 밸런싱과 지역 중복성을 제공합니다.
2. 지터가 포함된 지수 백오프
일시적인 오류가 발생했을 때 즉시 재시도하면 문제를 악화시킬 수 있습니다(‘재시도 폭풍’). 우리는 지터가 포함된 지수 백오프 를 구현합니다:
import random
import asyncio
async def retry_with_backoff(
coro,
max_attempts: int = 5,
base_delay: float = 0.5,
jitter: float = 0.1,
):
for attempt in range(1, max_attempts + 1):
try:
return await coro()
except Exception:
if attempt == max_attempts:
raise
delay = base_delay * (2 ** (attempt - 1))
delay += random.uniform(-jitter, jitter) * delay
await asyncio.sleep(delay)
- 지수 성장 (
base_delay * 2^(attempt‑1)) 은 재시도 간격을 넓혀 줍니다. - 지터 (
± jitter * delay) 는 다수의 클라이언트가 동시에 재시도하는 것을 방지합니다.
3. 서킷 브레이커 패턴
장기간 장애 시 하위 서비스에 과부하가 걸리지 않도록 서킷 브레이커 를 사용합니다. 설정된 오류 임계값을 초과하면 회로가 열려 일정 시간 동안 추가 호출을 차단합니다.
from pybreaker import CircuitBreaker
llm_breaker = CircuitBreaker(
fail_max=5, # 최대 연속 실패 횟수
reset_timeout=30, # 회로를 닫으려 시도하기 전 대기 시간(초)
)
@llm_breaker
async def call_llm(payload):
# Azure OpenAI PTU 엔드포인트 호출
...
회로가 열려 있는 동안 서비스는 캐시된 응답을 반환하거나 우아한 서비스 저하 메시지를 제공하여 사용자 경험을 유지합니다.
Source: …
재해 복구 및 가시성
- 다중 지역 배포: 최소 두 개의 Azure 지역에 FastAPI 인스턴스와 Redis 클러스터를 배포합니다. Route 53 헬스 체크를 사용해 DNS를 정상적인 지역으로 장애 조치합니다.
- 백업 및 복원: Redis(ElastiCache)의 자동 스냅샷을 활성화하고 Secrets Manager 버전을 내보냅니다.
- 모니터링: Prometheus + Grafana를 활용해 지연 시간, 오류 비율, 재시도 메트릭을 모니터링합니다. 커스텀 메트릭(예: 서킷 브레이커 상태)을 내보내어 근본 원인 분석에 도움을 줍니다.
- 로깅: AWS CloudWatch 또는 ELK 스택으로 로그를 중앙집중화하고, 서비스 간 요청을 추적할 수 있도록 상관 관계 ID를 포함합니다.
모두 합치기 – 샘플 요청 흐름
- Client → FastAPI: 요청이 가장 가까운 FastAPI 인스턴스에 도달합니다 (DNS에 의해 결정).
- FastAPI → Redis: 최근 응답이 캐시되어 있는지 확인합니다.
- Cache hit → 캐시된 결과를 반환합니다.
- Cache miss → 단계 3으로 진행합니다.
- FastAPI → Azure PTU Pool:
retry_with_backoff+ 회로 차단기(circuit breaker)를 사용하여 사용 가능한 PTU 엔드포인트를 호출합니다. - Response → Redis: TTL(예: 5 분)과 함께 새로운 결과를 저장합니다.
- FastAPI → Client: 응답을 반환합니다.
관측 가능성
볼 수 없는 것은 고칠 수 없습니다. structured logging을 모든 시도에 사용하면 다음을 캡처합니다:
- 사용된 엔드포인트
- 실패 원인
- 적용된 지연
- 최종 결과
이러한 로그는 모니터링 대시보드(예: Grafana)로 전달되며, 실패율이나 토큰 사용량이 사전 정의된 임계값을 초과하면 자동 알림을 트리거합니다.
확장성 레이어: 쿠버네티스를 이용한 탄력적 스케일링
변동하는 수요에 대응하기 위해 FastAPI 서비스를 쿠버네티스에 배포하고 Horizontal Pod Autoscaler (HPA) 를 사용합니다. HPA는 CPU 사용률과 같은 메트릭을 기반으로 서비스 파드 수를 자동으로 늘리거나 줄입니다.
샘플 HPA 정책
| Setting | Value |
|---|---|
| Target CPU Utilization | 60 % |
| Minimum Replicas | 2 |
| Maximum Replicas | 20 |
이를 통해 트래픽 급증이나 지역 장애 조치 상황에서도 서비스가 즉시 확장되어 증가된 부하를 처리할 수 있어, 수동 개입 없이도 성능을 유지할 수 있습니다.
주요 요점
엔터프라이즈 수준의 AI 서비스를 구축한다는 것은 처음부터 복원력을 최우선으로 한다는 의미입니다. 이는 사후 고려사항이 아니라 핵심 아키텍처 요구사항입니다.
- 실패를 대비한 설계 – 네트워크, API, 심지어 전체 클라우드 지역이 실패할 수 있다고 가정합니다. 이러한 상황을 우아하게 처리할 수 있는 메커니즘을 구축하세요.
- 구성 분리 및 중앙화 – AWS Secrets Manager와 같은 서비스를 사용해 설정을 외부에서 관리합니다. 이는 보안과 운영 민첩성을 향상시킵니다.
- 스마트 재시도 구현 – 지수 백오프와 지터를 결합한 다중 중복 엔드포인트를 사용해 일시적인 문제를 극복하고 의존성을 과부하시키지 않도록 합니다.
- 자동 스케일링 및 장애 조치 – Kubernetes HPA와 AWS Route 53과 같은 도구를 활용해 인간 개입 없이도 복구하고 적응할 수 있는 시스템을 구축합니다.
이러한 실천 방안을 결합하면 강력할 뿐만 아니라 사용자가 기대하는 안정성과 신뢰성을 제공하는 AI 서비스를 구축할 수 있습니다.
결론
대규모로 운영되는 AI 시스템은 설계 단계부터 복원력을 갖추어야 합니다. 비동기 API, 보안 구성, 지능형 재시도, 지역 간 장애 조치, 자동 스케일링을 결합함으로써, 악조건에서도 안정적이고 성능이 뛰어나며 투명성을 유지하는 AI 서비스를 제공할 수 있습니다.
핵심 인사이트: 복원력은 최적화가 아니라, 프로덕션 AI 시스템에 대한 기본 요구사항입니다.
