본문 바로가기
Artificial Intelligence/60. Python

[PYTHON] 추론 비용 70% 절감 방법 : Spot Instance 활용 및 체크포인트 복구 전략 5가지 해결책

by Papa Martino V 2026. 4. 20.
728x90

Spot Instance
Spot Instance

 

딥러닝 모델의 크기가 커짐에 따라 서빙에 필요한 GPU 인프라 비용은 기업의 가장 큰 부담 중 하나가 되었습니다. 특히 거대 언어 모델(LLM)이나 고해상도 이미지 생성 모델을 상시 운영할 때, 온디맨드(On-demand) 인스턴스 비용은 기하급수적으로 상승합니다. 이를 해결하기 위한 최선의 대안이 바로 Spot Instance(스팟 인스턴스) 활용입니다. 하지만 스팟 인스턴스는 공급업체의 리소스 회수 시 '중단 알림(Preemption Notice)' 후 강제 종료된다는 치명적인 단점이 있습니다. 본 포스팅에서는 파이썬을 기반으로 스팟 인스턴스의 중단을 선제적으로 감지하고, 상태를 보존하며, 복구하는 전문적인 체크포인트 전략을 상세히 다룹니다.


1. 온디맨드 vs 스팟 인스턴스: 경제성 및 리스크 차이 분석

스팟 인스턴스를 실무에 도입하기 전, 인프라의 특성을 정확히 이해하는 것이 중요합니다. 아래 표는 AWS, GCP, Azure와 같은 주요 클라우드 환경에서의 특성을 비교한 것입니다.

비교 항목 온디맨드 (On-Demand) 스팟 인스턴스 (Spot Instance)
비용 절감율 0% (표준 가격) 최대 60% ~ 90% 저렴
가용성 보장 SLA에 따른 99.9% 보장 보장 없음 (언제든 중단 가능)
사전 알림 없음 (유지) 30초 ~ 2분 전 중단 알림 발생
주요 용도 중단 불가능한 핵심 서비스 배치 추론, 유연한 확장 노드, 학습
복구 전략 자동 복구(Auto Healing) 체크포인트 및 상태 관리 필수

2. 스팟 중단 해결을 위한 아키텍처적 접근

스팟 인스턴스를 활용한 추론 서버 구축 시 가장 큰 해결 과제는 '진행 중인 요청(In-flight Request)의 유실 방지'입니다. 이를 위해 다음과 같은 전략을 수립해야 합니다.

  • 시그널 감지: 클라우드 메타데이터 엔드포인트를 주기적으로 폴링하여 중단 신호를 획득합니다.
  • Graceful Shutdown: 신호 감지 시 더 이상 새로운 요청을 받지 않고, 현재 처리 중인 요청을 안전하게 마무리합니다.
  • 상태 외부 저장: 인스턴스 내부 디스크가 아닌 Redis, S3, NFS 등에 체크포인트와 로그를 실시간 동기화합니다.

3. [Practical Examples] 실무 적용을 위한 Python 코드 가이드

엔지니어가 자신의 인프라에 즉시 이식할 수 있는 핵심 파이썬 스크립트 모음입니다.

Example 1: AWS Spot Instance 중단 알림 모니터링 스레드

import requests
import time
import threading

def monitor_spot_interruption():
    """AWS 메타데이터 서비스를 통한 중단 신호 감지"""
    url = "http://169.254.169.254/latest/meta-data/spot/instance-action"
    while True:
        try:
            response = requests.get(url, timeout=1)
            if response.status_code == 200:
                print("!!! Spot Interruption Warning Detected !!!")
                initiate_graceful_shutdown()
                break
        except Exception:
            pass
        time.sleep(5)

def initiate_graceful_shutdown():
    # 추론 서비스 중지 로직 구현
    pass

# 모니터링 시작
threading.Thread(target=monitor_spot_interruption, daemon=True).start()

Example 2: Redis를 활용한 추론 요청 큐 체크포인트 관리

import redis
import json

r = redis.StrictRedis(host='localhost', port=6379, db=0)

def save_request_checkpoint(request_id, payload):
    """중단 시 재처리를 위해 Redis에 임시 저장"""
    data = {"payload": payload, "status": "processing"}
    r.setex(f"checkpoint:{request_id}", 300, json.dumps(data))

def mark_as_completed(request_id):
    """성공 시 체크포인트 삭제"""
    r.delete(f"checkpoint:{request_id}")

Example 3: Graceful Shutdown 처리를 위한 FastAPI Signal Handler

from fastapi import FastAPI
import signal
import sys

app = FastAPI()

@app.on_event("shutdown")
def shutdown_event():
    print("Saving model state and cleaning up resources...")
    # S3로 로그 업로드 등 마무리 작업 수행

def handle_sigterm(sig, frame):
    print("SIGTERM received, exiting...")
    sys.exit(0)

signal.signal(signal.SIGTERM, handle_sigterm)

Example 4: 배치 추론 진행도(Offset) 외부 저장 및 복구

import os

CHECKPOINT_FILE = "/mnt/efs/inference_offset.txt"

def get_last_offset():
    if os.path.exists(CHECKPOINT_FILE):
        with open(CHECKPOINT_FILE, "r") as f:
            return int(f.read().strip())
    return 0

def update_offset(new_offset):
    with open(CHECKPOINT_FILE, "w") as f:
        f.write(str(new_offset))

# 추론 루프 시작 시
current_idx = get_last_offset()

Example 5: 중단 시 모델 추론 상태 S3 업로드 (boto3)

import boto3

def upload_state_to_s3(local_path, s3_bucket, s3_key):
    s3 = boto3.client('s3')
    try:
        s3.upload_file(local_path, s3_bucket, s3_key)
        print("Final state uploaded to S3 successfully.")
    except Exception as e:
        print(f"Failed to upload: {e}")

Example 6: 비대칭 추론 워커 구조 (RabbitMQ 이용)

import pika

def consume_requests():
    connection = pika.BlockingConnection(pika.ConnectionParameters('msg-broker'))
    channel = connection.channel()
    
    # 중단 시 메시지가 큐로 복구되도록 auto_ack=False 설정
    def callback(ch, method, properties, body):
        process_inference(body)
        ch.basic_ack(delivery_tag=method.delivery_tag)

    channel.basic_consume(queue='inference_tasks', on_message_callback=callback)
    channel.start_consuming()

Example 7: Docker Compose를 활용한 자동 재시작 정책

# docker-compose.yml 예시
services:
  inference-server:
    image: my-model-server:latest
    deploy:
      restart_policy:
        condition: on-failure
        delay: 5s
        max_attempts: 3
    volumes:
      - /shared/checkpoints:/app/checkpoints

4. 전문적인 운영 팁: 가용성을 유지하는 3단계 전략

단순히 기술적으로 복구하는 것 외에도 운영 전략이 동반되어야 비용과 안정성의 균형을 잡을 수 있습니다.

  1. Spot Fleet 및 Mixed Instance Group 사용: 단일 인스턴스 타입만 쓰지 말고 여러 가용 영역(AZ)과 여러 타입을 섞어 회수 리스크를 분산합니다.
  2. Fallback to On-Demand: 모든 스팟 리소스가 회수되었을 때를 대비해 소량의 온디맨드 인스턴스를 최소한(Baseline)으로 유지하십시오.
  3. Warm-up 최적화: 인스턴스 복구 속도를 높이기 위해 모델 가중치를 미리 베이크인(Bake-in)한 커스텀 AMI나 컨테이너 이미지를 사용하십시오.

5. 결론 및 향후 전망

클라우드 비용 효율화(FinOps) 관점에서 스팟 인스턴스는 강력한 무기입니다. 파이썬의 강력한 라이브러리 생태계와 클라우드 네이티브 API를 결합하면, 중단 가능성이라는 위험 요소를 통제 가능한 변수로 바꿀 수 있습니다. 이제 단순한 추론을 넘어 '지속 가능한 추론 인프라'를 구축해 보시기 바랍니다.


참고 문헌 및 출처

  • AWS Documentation: "Best Practices for Handling Spot Instance Interruptions" (2025-2026 Updated)
  • Google Cloud Architecture Center: "Running Batch Workloads on Spot VMs"
  • FinOps Foundation: "Cost Optimization for Machine Learning Inference"
  • Python Software Foundation: "Signal Handling in Distributed Systems"
728x90