본문 바로가기

IT & AI

넷플릭스는 vLLM을 어떻게 프로덕션에 올렸을까요

728x90

넷플릭스는 vLLM을 어떻게 프로덕션에 올렸을까요

AI 뉴스 썸네일
AI 뉴스 썸네일

넷플릭스가 사내 LLM 서빙 플랫폼의 구조와 운영 경험을 공개했어요. vLLM을 고르는 데서 끝나지 않고, 기존 ML 인프라와 연결한 방식부터 무중단 배포, 메트릭 통합, 제약 디코딩 병목까지 구체적으로 다뤘어요. 1

핵심 요약

구분핵심왜 볼 만한가요
서빙 구조기존 JVM 서빙 계층과 Triton 위에 vLLM을 연결했어요LLM만을 위한 별도 운영 체계를 만들지 않고 기존 배포·상태 확인·자동 확장 기능을 재사용했어요
엔진 선택TensorRT-LLM에서 vLLM을 기본 경로로 바꿨어요최고 처리량 하나보다 사용자 정의 모델, 디버깅, 확장 훅, 연구 환경과의 연결 비용을 함께 봤어요
APIgRPC와 OpenAI 호환 HTTP API를 함께 열었어요기존 ML 호출자와 새 LLM 애플리케이션이 같은 인프라를 나눠 쓸 수 있어요
운영버전 고정, 무중단 배포, 통합 메트릭을 직접 보강했어요라이브러리를 붙이는 단계와 안정적인 서비스로 운영하는 단계 사이의 간극을 보여줘요
성능로짓 처리를 vLLM V1의 배치 구조와 C++ 멀티스레딩으로 옮겼어요단일 요청 벤치마크에서 안 보이던 CPU 병목을 실제 동시 요청 환경에서 줄였어요

1. vLLM 선택보다 어려웠던 프로덕션 통합

넷플릭스의 출발점은 LLM 전용 플랫폼을 새로 세우는 방식이 아니었어요. 기존 JVM 기반 서빙 시스템이 라우팅, A/B 테스트, 특징 조회, 추론 전후 처리, 로깅을 맡고 있었어요. 큰 모델의 GPU 추론만 Model Scoring Service로 넘겼고, 그 아래에서 NVIDIA Triton이 모델 로딩과 배치 처리, GPU 스케줄링을 담당했어요. LLM도 이 경로에 넣어 기존 배포와 상태 확인, 자동 확장, 다중 리전 롤아웃 기능을 그대로 활용했어요. 2

초기 엔진은 TensorRT-LLM이었지만 2025년 여름 재평가 뒤 vLLM을 기본 엔진으로 골랐어요. 넷플릭스가 본 기준은 사용자 정의 모델을 별도 컴파일 과정 없이 불러오는지, 디코딩 로직을 확장할 수 있는지, 장애 중간 상태를 살펴보기 쉬운지였어요. 연구자가 이미 익숙한 도구라는 점도 연구 결과를 운영 환경으로 넘기는 비용을 낮췄어요.

728x90

모델 패키징에는 Triton의 vLLM backend를 기본으로 썼어요. 모델 아티팩트는 가중치와 토크나이저를 가리키는 설정 중심으로 남고, 입출력 명세는 배포 시점에 만들어져요. 덕분에 모델 패키지와 프런트엔드 업데이트의 결합이 줄어요. 다만 Triton이 기대하는 vLLM API와 실제 설치 버전이 어긋나면 backend 전체가 로드되지 않았어요. 넷플릭스는 서비스 이미지에서 호환 버전을 고정하고, 모델 작성자가 패키징 단계에서 vLLM 버전을 덮어쓰지 못하게 막았어요.

표준 Hugging Face 구조를 벗어난 모델도 별도 경로가 필요했어요. 사용자 정의 전처리와 후처리, 앙상블 실행, 특수 토큰화를 쓰는 모델은 Python backend로 돌렸어요. 하나의 방식으로 모든 모델을 감싸기보다 기본 경로와 예외 경로를 명확히 나눈 셈이에요.

API는 기존 gRPC와 OpenAI 호환 HTTP를 함께 제공해요. 호환 API가 있어 호스팅 모델에서 자체 미세조정 모델로 옮길 때 클라이언트 변경을 줄일 수 있어요. 하지만 NVIDIA Triton의 호환 프런트엔드가 `response_format`을 받아 놓고 vLLM에 전달하지 않는 문제도 발견했어요. JSON 출력을 요청해도 제약 디코딩이 적용되지 않아 잘못된 JSON이 나올 수 있었어요. 넷플릭스는 프런트엔드에 직접 패치를 적용해 해당 값을 vLLM의 guided decoding 인자로 바꿨어요.

배포 전략은 인터페이스 변경 여부에 따라 갈렸어요. 입출력 규격이 같으면 새 버전을 함께 띄운 뒤 상태 확인을 거쳐 트래픽을 옮기는 Red-Black 방식을 썼어요. 규격이 깨지는 변경에는 여러 모델 버전을 동시에 유지하는 Versioned 방식을 적용했어요. 후자는 전환 기간에 GPU 비용이 늘지만, 호출자가 새 버전으로 옮길 때까지 기존 요청을 계속 처리할 수 있어요.

운영 지표도 한곳에 모아야 했어요. Triton의 기본 연결은 vLLM 메트릭 40여 개 가운데 9개만 노출했어요. 토큰 처리량, KV 캐시 사용률, prefix cache 적중률처럼 운영에 필요한 값이 빠졌어요. 넷플릭스는 Triton의 HTTP 메트릭과 vLLM의 Prometheus 파일을 합쳐 단일 `/metrics` 경로로 제공했어요.

제약 디코딩에서는 Python 실행 구조가 병목이 됐어요. vLLM V0는 배치의 로짓을 GPU에서 가져온 뒤 요청별 제약 로직을 CPU에서 순차 처리했어요. 요청이 늘수록 GIL의 영향으로 꼬리 지연도 커졌어요. vLLM V1으로 옮긴 뒤 배치 단위 자료구조를 쓰고, 뜨거운 실행 경로를 C++ 멀티스레딩으로 다시 만들었어요. 부분 prefill과 메모리 압박에 따른 preemption이 상태 머신을 깨뜨리는 경우까지 추적해 재설정 로직을 넣었어요.

왜 중요한가요

이 사례는 추론 엔진의 벤치마크 점수만으로 프로덕션 적합성을 판단하기 어렵다는 점을 구체적으로 보여줘요. 실제 서비스에서는 모델 패키징, API 의미 보존, 버전 호환, 기동 시간, 메트릭, 무중단 전환이 함께 맞아야 해요. 넷플릭스가 공개한 실패 지점은 vLLM과 Triton을 조합하려는 팀이 배포 전에 확인할 항목으로 바로 쓸 수 있어요. 2

특히 OpenAI 호환이라는 이름만 보고 동작까지 같다고 가정하면 위험해요. 요청 스키마가 값을 받아도 하위 엔진까지 전달하지 않을 수 있어요. JSON 형식 강제처럼 결과 유효성에 영향을 주는 옵션은 실제 응답과 오류 처리까지 끝단에서 시험해야 해요.

엔진 선택 기준도 현실적이에요. 처리량 차이가 줄어든 뒤에는 사용자 정의 모델 지원, 장애 추적, 연구 코드와의 거리, 운영팀의 제어 범위가 더 큰 비용을 만들 수 있어요. 자체 LLM 서빙을 검토하는 팀이라면 최고 성능 표 하나보다 현재 ML 플랫폼에 얼마나 자연스럽게 들어오는지부터 따져볼 만해요.

참고 자료

  1. Netflix의 사내 LLM 서빙 플랫폼 — GeekNews
  2. In-House LLM Serving at Netflix — Netflix Technology Blog
728x90