AI 모델 서빙 아키텍처: 온라인 추론 vs 배치 추론 선택 기준
AI 모델을 학습하고 나면 “어떻게 서빙할 것인가”라는 질문이 반드시 따라옵니다. 실시간으로 응답해야 하는 챗봇과, 밤새 수백만 건의 상품 추천을 계산해야 하는 배치 잡은 근본적으로 다른 인프라를 요구합니다. 잘못된 선택은 GPU 비용을 수 배로 불리거나, 사용자 경험을 망가뜨리는 지연을 만들어냅니다. 이 글에서는 온라인 추론과 배치 추론의 구조적 차이, 결정 기준, 그리고 실무에서 자주 쓰는 하이브리드 패턴까지 체계적으로 다룹니다.
온라인 추론 vs 배치 추론: 핵심 차이
두 방식의 가장 근본적인 차이는 요청이 언제 도착하고, 결과를 언제 소비하느냐입니다. 온라인 추론은 요청이 들어오는 즉시 모델을 실행하고 수십~수백 ms 내에 응답을 반환합니다. 배치 추론은 요청을 일정 기간 모아두었다가 한꺼번에 처리하며, 결과를 데이터베이스나 파일 시스템에 저장해 놓습니다.
| 구분 | 온라인 추론 (Online Inference) | 배치 추론 (Batch Inference) |
|---|---|---|
| 지연 시간(Latency) | p99 < 200ms 목표 | 분~시간 단위 허용 |
| 처리량(Throughput) | 수백 RPS (스케일아웃으로 확장) | GPU 포화 상태로 수십~수백만 건/시간 |
| 인프라 형태 | REST/gRPC API 서버, 오토스케일링 | Spark, Ray, Airflow DAG, Kubernetes Job |
| GPU 활용률 | 유휴 시간 多 (트래픽 변동) | 90%+ 포화 가능 |
| 비용 패턴 | 트래픽 비례 (idle 비용 발생) | 실행 시간 비례 (spot 인스턴스 적합) |
| 대표 사례 | 챗봇, 실시간 사기 감지, 이미지 검색 | 야간 추천 계산, 전체 고객 리스크 스코어링 |
| 모델 업데이트 | 블루/그린 배포, 카나리 필요 | 잡 실행 전 새 모델 버전 지정으로 충분 |
지연 시간과 처리량의 트레이드오프
온라인 추론에서 지연 시간(latency)은 SLO(Service Level Objective)의 핵심 지표입니다. 일반적으로 p50/p95/p99 기준으로 측정하며, 사용자가 체감하는 것은 p99입니다. 모델이 아무리 빠르더라도 네트워크 왕복(RTT), 직렬화/역직렬화, 큐 대기 시간이 누적됩니다. NVIDIA Triton Inference Server를 예로 들면, TensorRT로 최적화한 ResNet-50은 배치 사이즈 1 기준 A100에서 약 1~2ms 내외이지만, 실제 서비스 레이턴시는 네트워크·로드밸런서 오버헤드를 더해 10~30ms 수준이 됩니다.
배치 추론에서는 처리량(throughput)이 핵심입니다. 배치 사이즈를 키울수록 GPU 메모리 대역폭 활용률이 높아져 건당 처리 비용이 낮아집니다. LLM 추론의 경우 배치 사이즈 1 대비 배치 사이즈 32에서 토큰당 처리 비용이 10배 이상 개선되는 사례도 있습니다. 단, 배치 사이즈를 무한히 늘리면 OOM(Out of Memory)이 발생하므로 GPU 메모리 용량과 시퀀스 길이를 고려한 동적 배치 크기 결정이 필요합니다.
# Triton Dynamic Batching 설정 예시 (config.pbtxt)
dynamic_batching {
preferred_batch_size: [8, 16, 32]
max_queue_delay_microseconds: 5000 # 5ms 이내 대기 후 배치 실행
default_queue_policy {
timeout_action: DELAY
default_timeout_microseconds: 10000
allow_timeout_override: true
max_queue_size: 256
}
}
instance_group [
{
count: 2
kind: KIND_GPU
gpus: [0, 1]
}
]
큐 기반 비동기 추론: 두 세계의 중간 지점
모든 요청이 즉각적인 응답을 필요로 하지는 않습니다. 문서 요약, 대용량 이미지 분석, 리포트 생성처럼 “요청은 지금 하지만 결과는 나중에 받아도 되는” 유스케이스가 많습니다. 이 경우 큐 기반 비동기 추론(Queue-based Async Inference) 패턴이 효과적입니다.
클라이언트가 요청을 제출하면 즉시 작업 ID를 반환받습니다. 워커 풀이 큐에서 작업을 꺼내 추론을 실행하고, 완료 시 결과를 저장소(Redis, S3, DB)에 기록합니다. 클라이언트는 폴링(polling)이나 웹훅(webhook)으로 결과를 수신합니다. 이 패턴은 트래픽 스파이크를 큐로 흡수하므로 온라인 추론처럼 공격적인 오토스케일링 없이도 안정적입니다.
# Celery + Redis 기반 비동기 추론 워커 예시
from celery import Celery
import torch
app = Celery("inference", broker="redis://localhost:6379/0",
backend="redis://localhost:6379/1")
# 워커 시작 시 모델 1회 로드 (요청마다 로드하지 않음)
model = None
@app.on_after_configure.connect
def load_model(sender, **kwargs):
global model
model = torch.jit.load("model.pt").cuda().eval()
@app.task(bind=True, max_retries=3)
def run_inference(self, input_data: list) -> dict:
try:
tensor = torch.tensor(input_data).cuda()
with torch.no_grad():
output = model(tensor)
return {"result": output.cpu().tolist(), "status": "success"}
except Exception as exc:
raise self.retry(exc=exc, countdown=2 ** self.request.retries)
언제 무엇을 선택할 것인가: 결정 트리
서빙 방식을 결정할 때 다음 순서로 질문하세요.
- 사용자가 결과를 실시간으로 기다리는가? — Yes이면 온라인 추론. 챗봇, 실시간 번역, API 응답이 여기 해당합니다.
- 결과를 수 분 내에 받아도 무방한가? — Yes이면 큐 기반 비동기 추론을 검토하세요. 문서 분석, 긴 영상 처리 등이 해당합니다.
- 대상 데이터가 사전에 정해져 있고 주기적으로 갱신되는가? — Yes이면 배치 추론이 최적입니다. 전체 사용자 추천 갱신, 주간 리스크 스코어링 등이 해당합니다.
- 트래픽이 예측 불가능하게 스파이크하는가? — 온라인 추론이라면 HPA(Horizontal Pod Autoscaler) + GPU 노드 프로비저닝 전략이 필요합니다. 배치라면 큐 깊이 기반 워커 오토스케일링으로 대응합니다.
- 비용이 최우선 제약인가? — 배치 추론을 Spot/Preemptible 인스턴스로 운영하면 온라인 추론 대비 60~80% 비용 절감이 가능합니다.
대부분의 성숙한 ML 플랫폼은 두 방식을 혼합합니다. 예를 들어, 추천 시스템은 배치로 후보군 수백 개를 미리 계산해 캐시에 저장하고, 실시간 요청 시에는 캐시된 후보를 가져와 경량 랭킹 모델로 온라인 추론합니다. 이를 Two-stage Retrieval + Ranking 패턴이라 합니다.
실전 팁: 서빙 인프라 선택과 운영
- 모델 최적화 우선: 인프라 투자 전에 TensorRT, ONNX Runtime, 양자화(INT8/FP16)로 모델 자체 레이턴시를 줄이세요. 같은 GPU에서 2~4배 처리량 향상이 가능합니다.
- 웜업(Warm-up): 온라인 추론 서버는 콜드 스타트 시 첫 요청 레이턴시가 급등합니다. 배포 후 더미 요청으로 JIT 컴파일과 CUDA 커널을 워밍업하세요.
- 배치 추론 재시작 전략: Spark나 Ray 잡이 중간에 실패하면 처음부터 재실행하는 대신, 체크포인트(처리 완료된 파티션 추적)를 활용해 이어서 실행하세요.
- 레이턴시 SLO 설정: p50이 아닌 p99, p999 기준으로 SLO를 정의하세요. 꼬리 레이턴시(tail latency)가 사용자 경험에 직결됩니다.
- 비용 모니터링: GPU 시간당 처리 건수(throughput/GPU-hour)를 핵심 비용 효율 지표로 추적하세요. 모델 업데이트나 배치 사이즈 변경 후 이 지표를 반드시 확인합니다.
마무리
온라인 추론과 배치 추론은 우열의 문제가 아니라 사용 맥락의 문제입니다. 실시간 사용자 응답이 필요하면 온라인, 대량 데이터를 경제적으로 처리해야 하면 배치, 그 중간 어딘가라면 큐 기반 비동기가 답입니다. 대부분의 프로덕션 ML 시스템은 세 방식을 모두 사용하며, 각 방식의 트레이드오프를 명확히 이해해야 비용과 성능 두 마리 토끼를 잡을 수 있습니다. 초기에 온라인으로 시작했더라도, 데이터 규모와 비용이 증가하면 배치나 하이브리드로 전환하는 것을 두려워하지 마세요.
자주 묻는 질문
Q. 온라인 추론 서버가 트래픽 스파이크를 버티지 못할 때 어떻게 해야 하나요?
A. 단기적으로는 요청 큐잉과 타임아웃 정책을 강화하고, 중기적으로는 HPA + Karpenter(AWS) 또는 GKE Node Auto Provisioner로 GPU 노드를 동적 확장하세요. 근본적으로는 요청 중 일부를 큐 기반 비동기로 전환하거나, 캐시 가능한 추론 결과를 Redis에 저장해 모델 호출 자체를 줄이는 것이 가장 효과적입니다.
Q. 배치 추론에서 Spot 인스턴스를 쓸 때 인터럽트가 발생하면 어떻게 되나요?
A. Spot 인터럽트는 약 2분 전에 통보됩니다. Ray나 Spark는 체크포인트 기반 재실행을 지원하므로, 처리 단위(파티션, 미니배치)를 작게 유지하고 중간 결과를 주기적으로 영구 스토리지(S3, GCS)에 기록하면 인터럽트 후 재개 시 손실을 최소화할 수 있습니다. AWS SageMaker Managed Spot Training은 이 패턴을 자동화해 줍니다.
Q. LLM(대형 언어 모델) 서빙은 온라인과 배치 중 어느 쪽이 적합한가요?
A. 용도에 따라 다릅니다. 챗봇·코파일럿은 스트리밍 온라인 추론(vLLM, TGI)이 필수입니다. 대량 문서 요약, 데이터 라벨링, 오프라인 평가는 배치가 훨씬 경제적입니다. vLLM의 continuous batching 기능은 온라인 환경에서도 배치 효율을 가져올 수 있어, 두 방식의 장점을 절충하는 현실적인 선택지입니다.