
LLM을 실제 서비스에 적용하려면 모델을 실행하는 것만으로는 충분하지 않습니다. 모델을 안정적으로 배포하고, GPU 자원을 효율적으로 사용하며, 요청량 증가에 대응하고, 모델 버전을 안전하게 전환해야 합니다. 여기에 기존 ML 시스템과의 호환성, API 제공 방식, 모니터링, 사용자 정의 디코딩 로직까지 고려해야 합니다.
Netflix는 LLM을 기존 ML 인프라와 분리된 별도의 시스템으로 만들기보다 기존 서빙 플랫폼에 통합하는 방식을 선택했습니다. 기존 Model Scoring Service(MSS)를 기반으로 NVIDIA Triton Inference Server와 vLLM을 연결하고, 기존 gRPC 인터페이스와 OpenAI 호환 HTTP API를 함께 제공합니다.
특히 실제 프로덕션 환경에서는 단순히 오픈소스 추론 엔진을 연결하는 것만으로 끝나지 않았습니다. Triton과 vLLM의 버전 호환성, API 필드 누락, 모델 I/O 변경에 따른 배포 문제, GPU 모델의 긴 시작 시간, CPU 기반 디코딩 병목 등 여러 문제가 발생했고 이를 플랫폼 수준에서 보완했습니다.
이번 글에서는 Netflix의 LLM 서빙 구조부터 vLLM을 기본 엔진으로 선택한 이유, Triton과의 통합 방식, 무중단 배포 전략, 메트릭 통합, 디코딩 성능 개선까지 살펴봅니다.
기존 ML 인프라에 LLM을 통합한 Netflix의 서빙 구조
Netflix의 핵심 방향은 LLM을 기존 ML 인프라와 별도의 사일로로 분리하지 않는 것입니다.
기존 JVM 기반 통합 서빙 시스템은 모델 호출만 담당하는 단순한 계층이 아닙니다. 라우팅과 A/B 테스트부터 후보 생성, 특징 조회, 추론, 후처리, 단계별 로깅까지 처리하며 실시간 경로와 캐시된 배치 경로를 모두 지원합니다.
여기에 LLM을 통합하면서 호출 방식은 두 가지로 나뉩니다.
- 기존 ML 서비스는 기존 gRPC 경로를 사용
- LLM 애플리케이션은 직접 HTTP 경로를 사용
실제 모델 실행 위치는 모델 크기에 따라 달라집니다.
작은 CPU 모델은 원격 호출에 따른 비용을 줄이기 위해 호출 프로세스 내부에서 직접 실행합니다. 반면 큰 GPU 모델은 전처리와 후처리를 로컬에서 처리하고, 실제 추론만 원격 Model Scoring Service(MSS)에 위임합니다.
MSS는 XGBoost, TensorFlow, PyTorch뿐만 아니라 LLM까지 동일한 인터페이스로 제공합니다. 하부에서는 NVIDIA Triton Inference Server가 모델 로딩, 배치 처리, GPU 스케줄링을 담당합니다.
구조를 단순화하면 다음과 같은 흐름입니다.
클라이언트 → 기존 서빙 시스템 → MSS → Triton → vLLM → GPU 모델
Triton 위의 Java 제어 영역에서는 실제 운영에 필요한 기능을 담당합니다.
- 모델 배포
- 버전 관리
- 상태 확인
- 자동 확장
- 다중 리전 롤아웃
- 무중단 업그레이드
모델 개발자가 모델 아티팩트와 배포 설정을 패키징하면 플랫폼은 필요한 GPU 인스턴스를 프로비저닝하고 Triton을 구성합니다. 이후 업그레이드 역시 서비스 중단 없이 진행하도록 조정합니다.
즉, LLM을 별도의 독립 플랫폼으로 만드는 대신 기존 ML 서빙 구조 안에 포함시키면서 기존 운영 체계와 LLM 추론을 하나의 경로로 연결한 것입니다.
Netflix가 기본 추론 엔진으로 vLLM을 선택한 이유
Netflix의 LLM 플랫폼이 처음부터 vLLM을 사용했던 것은 아닙니다.
초기에는 성능이 높고 기존 MSS의 Triton과 이미 통합돼 있던 TensorRT-LLM을 사용했습니다. 하지만 시간이 지나면서 오픈소스 추론 엔진의 성능이 특화 스택과의 차이를 대부분 좁혔고, Netflix의 LLM 워크로드 역시 다양해졌습니다.
당시 워크로드는 단순한 자기회귀 디코딩에 그치지 않았습니다.
- 임베딩 생성
- 검색과 순위화를 위한 prefill-only 추론
- 자기회귀 디코딩
- 단계별 제약 로직이 복잡한 사용자 정의 모델
이러한 범위를 다시 벤치마크한 뒤 Netflix는 성능뿐 아니라 운영 적합성을 기준으로 vLLM을 기본 경로 엔진으로 선택했습니다.
사용자 정의 모델을 빠르게 적용할 수 있다
vLLM은 다단계 컴파일 과정을 거치지 않고 사용자 정의 모델 아키텍처를 로드할 수 있습니다.
이는 비표준 모델을 반복적으로 개발하고 테스트해야 하는 환경에서 중요합니다. 모델을 변경할 때마다 복잡한 컴파일 과정에 의존하지 않아도 되기 때문에 연구 단계에서 프로덕션까지 이동하는 과정이 단순해집니다.
사용자 정의 디코딩 로직을 확장할 수 있다
Netflix의 일부 워크로드는 단순히 모델에 프롬프트를 전달하고 결과를 받는 구조가 아닙니다.
생성되는 토큰에 따라 허용되는 출력이 달라지는 복잡한 제약 로직이 필요합니다. vLLM은 이러한 사용자 정의 디코딩 로직을 위한 확장 지점을 제공합니다.
장애와 중간 상태를 조사하기 쉽다
초기 TensorRT-LLM과 비교했을 때 vLLM은 장애나 중간 상태를 조사하기에 상대적으로 편리한 구조를 제공했습니다.
프로덕션 환경에서는 단순한 최고 성능보다 문제가 발생했을 때 원인을 추적하고 수정할 수 있는 운영 편의성도 중요합니다.
연구 환경과 프로덕션의 간극을 줄인다
ML 실무자들이 연구 단계에서 이미 vLLM에 익숙하다는 점도 선택 이유였습니다.
연구 환경에서 사용하던 엔진과 프로덕션 환경에서 사용하는 엔진이 달라지면 모델을 배포하는 과정에서 추가적인 학습과 개발 비용이 발생할 수 있습니다. vLLM을 기본 경로로 선택하면서 이 간극을 줄일 수 있었습니다.
결국 Netflix의 선택 기준은 단순히 "어떤 엔진이 가장 빠른가"가 아니었습니다.
사용자 정의 모델 지원, 디버깅, 확장성, 개발자 경험, 기존 인프라 통합까지 포함한 운영 적합성을 기준으로 vLLM을 선택한 것입니다.
Triton과 vLLM을 연결하는 두 가지 패키징 방식
Triton과 vLLM을 연결할 때 중요한 부분 중 하나는 모델을 어떻게 패키징하느냐입니다.
Netflix가 고려한 방식은 Triton의 Python backend와 vLLM backend입니다.
두 방식의 가장 큰 차이는 모델 아티팩트와 프런트엔드의 결합 정도에 있습니다.
Python backend의 특징
Python backend에서는 개발자가 패키징 단계에서 입출력 텐서 명세를 직접 정의합니다.
이 명세는 모델 아티팩트에 고정됩니다. 따라서 외부 프런트엔드에서 보내는 요청의 구조와 패키징된 모델의 I/O 명세가 일치해야 합니다.
문제는 프런트엔드가 변경될 때 발생합니다.
예를 들어 프런트엔드 업그레이드로 요청 I/O가 변경되면 모델 패키징 코드도 함께 수정해야 합니다. 그렇지 않으면 런타임에서 요청 처리가 실패할 수 있습니다.
vLLM backend의 특징
vLLM backend에서는 모델 가중치와 토크나이저를 가리키는 JSON 설정을 기반으로 아티팩트를 구성합니다.
배포 시 Triton backend가 I/O 텐서 명세를 동적으로 생성합니다.
따라서 모델 개발자가 직접 텐서 명세를 정의할 필요가 줄어들고, 모델과 프런트엔드를 서로 독립적으로 변경하기 쉬워집니다.
이 때문에 Netflix는 기본적으로 vLLM backend를 선택했습니다.
하지만 프로덕션 환경에서는 두 가지 중요한 문제가 나타났습니다.
첫 번째 문제, Triton과 vLLM의 버전 호환성
Triton의 vLLM backend는 특정 vLLM API를 기준으로 컴파일됩니다.
따라서 Triton과 vLLM의 버전이 맞지 않으면 backend 자체를 로드하지 못할 수 있습니다.
입력 정보에서는 Triton 25.09가 vllm.engine.metrics를 가져오지만 해당 모듈이 vLLM 0.11.2에서 제거된 사례를 제시합니다.
이처럼 각각의 버전을 따로 관리하면 단순한 모델 코드 문제가 아니라 서비스 전체가 시작되지 않는 문제로 이어질 수 있습니다.
Netflix는 이를 방지하기 위해 서비스 이미지 생성 과정에서 호환되는 버전을 고정하고, 모델 개발자가 패키징 과정에서 vLLM 버전을 임의로 덮어쓰지 못하도록 관리합니다.
즉, 오픈소스 구성요소를 사용하는 것과 버전을 자유롭게 조합하는 것은 다른 문제입니다.
프로덕션에서는 호환성이 검증된 버전 조합을 하나의 실행 환경으로 관리하는 것이 중요합니다.
두 번째 문제, 사용자 정의 실행 로직
vLLM backend는 표준 Hugging Face 호환 모델과 일반적인 추론 수명주기를 전제로 합니다.
하지만 모든 모델이 이 구조에 맞는 것은 아닙니다.
사용자 정의 전처리와 후처리, 앙상블 파이프라인, 별도의 토큰화 과정처럼 표준적인 추론 흐름을 벗어난 모델도 존재합니다.
이 경우 Python backend가 필요합니다.
Python backend에서는 execute()를 직접 제어할 수 있기 때문에 비표준 실행 흐름을 구현할 수 있습니다.
따라서 Netflix의 기본 선택은 vLLM backend이지만, 모든 모델을 하나의 방식으로 처리하려 하지 않습니다.
표준 모델은 vLLM backend를 활용하고, 비표준 실행 로직이 필요한 모델은 Python backend를 사용하는 방식으로 역할을 나눕니다.
gRPC와 OpenAI 호환 HTTP API를 함께 제공하는 이유
Netflix의 기존 ML 시스템에서는 XGBoost 앙상블부터 대규모 LLM까지 동일한 gRPC 호출 방식으로 모델을 평가할 수 있습니다.
이 구조를 유지하면 기존 클라이언트 라이브러리와 상태 확인, 배포 파이프라인 등을 그대로 활용할 수 있습니다.
하지만 LLM 생태계에서는 OpenAI 호환 인터페이스가 널리 사용됩니다.
추론 엔진과 오케스트레이션 프레임워크, 평가 도구, 클라이언트 라이브러리 등이 OpenAI 호환 API를 기준으로 만들어져 있기 때문입니다.
그래서 Netflix는 기존 gRPC API를 유지하면서 OpenAI 호환 HTTP API도 함께 제공합니다.
이 구조는 모델 교체에도 유리합니다.
예를 들어 호스팅 모델을 사용하다가 직접 미세 조정한 자체 호스팅 모델로 변경하더라도 동일한 API를 유지할 수 있다면 애플리케이션 코드의 변경을 최소화할 수 있습니다.
Triton OpenAI 호환 프런트엔드를 활용한 구조
Netflix는 NVIDIA의 Triton OpenAI 호환 프런트엔드를 재사용했습니다.
구조는 다음과 같습니다.
- 내장 Triton 서버를 시작합니다.
- TritonLLMEngine이 요청 스키마를 Triton 추론 요청으로 변환합니다.
- FastAPI를 통해 HTTP 응답을 제공합니다.
- KServe HTTP/gRPC 프런트엔드도 함께 활성화합니다.
- Java 제어 영역은 동일한 Triton 인스턴스에 gRPC로 접근합니다.
이렇게 하면 LLM 애플리케이션은 OpenAI 호환 HTTP API를 사용할 수 있고, 기존 플랫폼은 gRPC를 계속 사용할 수 있습니다.
OpenAI 호환 API에서도 프로덕션 문제가 발생했다
OpenAI 호환 API를 제공한다고 해서 모든 기능이 자동으로 완벽하게 연결되는 것은 아니었습니다.
Netflix는 프런트엔드가 스키마에서 허용한 response_format을 vLLM으로 전달하기 전에 조용히 버리는 문제를 발견했습니다.
예를 들어 JSON 출력을 요청하더라도 해당 요청이 실제 유도 디코딩 제약으로 전달되지 않으면 모델은 JSON 형식을 제대로 지키지 않을 수 있습니다.
더 중요한 문제는 플랫폼 오류가 발생하지 않았다는 점입니다.
API 요청 자체는 정상적으로 처리되는 것처럼 보이지만 실제로는 요청자가 요구한 출력 제약이 적용되지 않는 상황이 발생할 수 있습니다.
Netflix는 프런트엔드를 Git subtree로 가져와 response_format 요청을 vLLM의 유도 디코딩 매개변수로 변환하도록 직접 패치했습니다.
이 사례는 API 호환성에서 중요한 부분을 보여줍니다.
API의 이름과 요청 형식이 같다는 것만으로 기능까지 완전히 동일하게 동작한다고 볼 수 없습니다.
프로덕션에서는 실제 파라미터가 하위 추론 엔진까지 제대로 전달되는지 검증해야 합니다.
GPU 모델의 무중단 배포가 어려운 이유
CPU 기반 서비스와 비교하면 대규모 GPU 모델의 배포는 더 복잡합니다.
모델을 로딩하는 데 시간이 오래 걸리고, 모델 버전이 바뀌면서 I/O 스키마까지 변경될 수 있기 때문입니다.
Netflix는 이를 해결하기 위해 Red-Black과 Versioned라는 두 가지 배포 전략을 사용합니다.
Red-Black 배포
Red-Black 방식은 기존 버전 옆에 새로운 버전을 먼저 배포한 뒤 상태 확인을 통과하면 트래픽을 단계적으로 전환하는 방식입니다.
새 버전과 기존 버전의 확장과 축소를 같은 비율로 진행하고, 문제가 발생하면 원자적으로 롤백할 수 있습니다.
모델 인터페이스가 안정적이라면 비용 측면에서도 효율적입니다.
I/O 스키마가 바뀌면 문제가 달라진다
문제는 새 모델에서 텐서 차원처럼 I/O 스키마가 변경되는 경우입니다.
새 모델이 완전히 활성화되기 전에는 상위 소비자가 새로운 설정으로 변경될 수 없습니다.
이 상태에서 기존 형식의 요청이 새로운 배포로 전달되면 요청 자체가 실패할 수 있습니다.
이때 사용하는 방식이 Versioned 배포입니다.
Versioned 배포
Versioned 방식에서는 (modelId, modelVersion) 조합마다 독립적인 배포를 유지합니다.
여러 버전을 동시에 서비스하기 때문에 모델 배포와 소비자 업데이트를 분리할 수 있습니다.
예를 들어 새로운 모델 버전이 배포되더라도 소비자는 새 버전이 완전히 준비된 뒤 설정을 변경할 수 있습니다. 그동안 기존 버전은 기존 트래픽을 계속 처리합니다.
전환이 끝나면 더 이상 사용하지 않는 이전 배포를 정리합니다. 다만 최신 버전은 항상 보존합니다.
단점도 있습니다.
전환 과정에서 여러 버전이 동시에 실행되므로 GPU 비용이 일시적으로 증가할 수 있습니다.
따라서 Netflix가 제시하는 방향은 명확합니다.
모델 인터페이스가 안정적이라면 비용이 낮은 Red-Black 방식을 우선 사용하고, 호환되지 않는 I/O 변경이 불가피한 경우에만 Versioned 방식을 사용하는 것입니다.
가능하다면 텐서 형태처럼 변경될 수 있는 설정을 추론 모델 안에 직접 넣어 버전 독립적으로 만드는 것도 중요합니다.
대형 LLM의 콜드 스타트를 줄이는 모델 캐시
LLM 서빙에서 또 하나의 현실적인 문제는 시작 시간입니다.
vLLM-on-Triton 인스턴스는 여러 초기화 단계를 거쳐야 gRPC 포트를 열 수 있습니다.
특히 대형 LLM을 S3나 Hugging Face에서 직접 내려받아 시작하면 모델 로딩에 필요한 시간이 길어져 스케줄러가 허용하는 범위를 넘어설 수 있습니다.
Netflix는 이를 줄이기 위해 모델 발표 시점에 모델을 Amazon FSx에 미리 구체화합니다.
이후 인스턴스가 시작될 때 객체 저장소에서 직접 모델을 다운로드하는 대신 고성능 파일 시스템을 사용합니다.
즉, 모델을 필요할 때마다 멀리 있는 저장소에서 가져오는 방식이 아니라 서비스 시작 전에 사용할 모델을 준비해 두는 방식입니다.
OpenAI 호환 API가 필요한 배포에서는 Triton을 해당 프런트엔드 프로세스 내부의 내장 서버로 실행합니다.
반대로 해당 API가 필요하지 않은 배포에서는 Triton을 독립적으로 실행합니다.
이 실행 방식은 패키징 시 배포별로 설정합니다.
그 밖에도 시작 과정에서는 다음 작업이 진행됩니다.
- 모델 패키지 압축 해제
- Python entry_points를 통한 사용자 정의 vLLM 플러그인 설치
- Prometheus 멀티프로세스 디렉터리 정리
- 엔진 준비 완료 확인
- 엔진이 준비될 때까지 gRPC 포트 차단
특히 마지막 단계는 중요합니다.
모델이 아직 준비되지 않았는데 외부 요청을 받게 만드는 것이 아니라, 실제로 추론 가능한 상태가 된 뒤 서비스 접근을 허용하는 구조입니다.
Triton과 vLLM의 메트릭을 하나로 통합하다
프로덕션 LLM 플랫폼에서 성능을 확인하려면 모델 응답만 봐서는 부족합니다.
GPU 사용량과 토큰 처리량, KV 캐시 상태 등 추론 엔진 내부의 상태를 함께 확인해야 합니다.
그런데 Triton과 vLLM은 서로 다른 방식으로 메트릭을 관리합니다.
vLLM은 PROMETHEUS_MULTIPROC_DIR에 .db 파일 형태로 메트릭을 기록하고, Triton은 별도의 Prometheus 엔드포인트를 제공합니다.
두 시스템은 서로의 메트릭을 자동으로 인식하지 못합니다.
Triton의 내장 브리지를 사용하더라도 vLLM의 40개가 넘는 메트릭 중 9개만 노출되는 문제가 있었습니다.
특히 다음과 같은 중요한 지표가 빠질 수 있습니다.
- 토큰 처리량
- KV 캐시 사용률
- 접두사 캐시 적중률
Netflix는 이를 해결하기 위해 경량 HTTP 프록시를 사용했습니다.
프록시는 Triton의 메트릭을 HTTP로 가져오고, Prometheus MultiProcessCollector를 사용해 디스크에 저장된 vLLM 메트릭을 읽습니다.
그 결과 두 시스템의 메트릭을 하나의 /metrics 응답으로 통합할 수 있습니다.
이 방식의 장점은 기존 모니터링 체계를 그대로 사용할 수 있다는 것입니다.
새로운 LLM 플랫폼을 도입했다고 해서 기존 대시보드와 경보 시스템을 전부 다시 만들 필요가 없습니다.
디코딩 과정에서 출력 제약을 직접 적용하는 이유
일부 프로덕션 LLM 워크로드에서는 모델이 생성한 결과를 그대로 사용하는 것이 어렵습니다.
생성되는 토큰의 순서에 따라 다음 단계에서 허용되는 토큰이 달라지는 경우가 있기 때문입니다.
Netflix는 이런 제약을 추론이 끝난 다음 결과를 검사하는 방식으로 처리하지 않고, 토큰을 생성하는 디코딩 루프 안에서 직접 적용합니다.
각 제약은 상태 머신으로 모델링합니다.
생성된 토큰 이력에 따라 상태가 바뀌고, 각 단계에서는 현재 상태에서 허용되는 토큰 마스크를 출력합니다.
vLLM에서는 사용자 정의 로짓 프로세서 인터페이스를 사용합니다.
요청마다 필요한 규칙이 다르기 때문에 요청별로 별도의 프로세서를 할당합니다.
초기에는 이러한 기능의 차이 때문에 vLLM V0을 사용했습니다. 이후 V1이 성숙한 2025년 4분기에 V1으로 이전했습니다.
문제는 V0의 구현 방식에서 나타났습니다.
vLLM V0에서 발생한 CPU 병목
처음 구현은 순수 Python으로 작성됐습니다.
기능적으로는 정상 동작했지만 동시 요청이 늘어나면서 확장성 문제가 나타났습니다.
처리 과정은 다음과 같았습니다.
- GPU가 전체 요청 배치의 로짓을 생성합니다.
- 로짓을 CPU로 복사합니다.
- 데이터 전송이 완료될 때까지 기다립니다.
- 각 요청의 제약 로직을 순차적으로 실행합니다.
여기에서 문제가 된 것은 Python의 GIL입니다.
요청별 로짓 프로세서가 실행되는 구조에서는 여러 요청의 CPU 작업을 효과적으로 병렬화하기 어려웠습니다.
결과적으로 배치 크기가 커질수록 CPU 처리 시간이 증가하고 꼬리 지연시간도 길어졌습니다.
GPU에서는 이미 모델 순전파가 효율적으로 배치 처리되고 있어도 전체 요청의 지연시간은 CPU 로직에 묶일 수 있었습니다.
특히 이 문제는 단일 요청으로 테스트할 때는 잘 나타나지 않았습니다.
실제 서비스 수준의 동시 요청이 발생했을 때 비로소 CPU 기반 로짓 처리의 병목이 드러났습니다.
이것은 LLM 성능 테스트에서 중요한 부분입니다.
단일 요청에서 빠른 것과 높은 동시성에서 안정적으로 빠른 것은 다른 문제입니다.
vLLM V1에서는 배치 단위로 다시 설계
Netflix는 vLLM V1으로 이전하면서 사용자 정의 로짓 프로세서를 다시 작성했습니다.
V1에서는 로짓 처리가 요청 단위에서 배치 단위로 이동했습니다.
여러 요청의 마스크를 함께 계산하도록 배치 자료구조를 기반으로 프로세서를 다시 구현했습니다.
또한 성능에 중요한 경로는 Python에서 벗어나 멀티스레드 C++로 재구현했습니다.
그 결과 배치 크기가 증가하더라도 로짓 처리 시간이 일정하게 유지되도록 개선했습니다.
다만 V1의 API는 더 복잡했습니다.
update_state(batch_update)를 통해 배치 구성원의 변화를 명시적으로 추적해야 하기 때문입니다.
V0의 요청별 인터페이스보다 구현은 복잡해졌지만, 동적으로 변경되는 배치에서 요청별 상태를 정확하게 유지하려면 필요한 구조였습니다.
성능 개선 이후에도 상태 관리 문제가 남았다
CPU 병목을 해결했다고 해서 모든 문제가 끝난 것은 아닙니다.
상태를 유지하는 디코딩 로직에서는 부분 prefill과 선점이라는 두 가지 상황이 추가로 문제가 됐습니다.
부분 prefill
vLLM V1은 청크 단위 prefilling을 수행합니다.
따라서 하나의 요청에 대한 prefill이 여러 엔진 단계에 걸쳐 진행될 수 있습니다.
그런데 BatchUpdate만으로는 완전한 prefill과 부분 prefill을 명확하게 구분할 수 없었습니다.
Netflix는 이를 위해 내부 추적 로직을 추가했습니다.
선점
GPU 메모리가 부족하면 vLLM은 일부 진행 중인 요청의 KV 캐시를 제거하고, 이후 해당 요청을 다른 프롬프트 및 출력 토큰 목록과 함께 다시 예약할 수 있습니다.
문제는 상태 머신이 출력 토큰 목록이 계속 증가한다고 가정한다는 점입니다.
선점으로 KV 캐시가 제거되고 요청이 다시 실행되면 이 전제가 깨질 수 있습니다.
Netflix는 디코딩 단계 사이에서 토큰 이력이 이전보다 짧아졌는지를 확인합니다.
만약 이 상황이 감지되면 상태 머신을 초기화하고 새로운 프롬프트를 기준으로 다시 구성합니다.
이처럼 실제 LLM 서빙에서는 모델의 추론 속도뿐 아니라 추론 과정에서 유지되는 상태의 생명주기까지 관리해야 합니다.
Netflix가 바라보는 다음 LLM 서빙 과제
현재 Netflix의 LLM 서빙 플랫폼은 크게 세 가지 방향을 함께 추구합니다.
- 낮은 지연시간
- 깊은 사용자 정의
- 기존 인프라와의 통합
vLLM과 Triton을 기반으로 일관된 API를 제공하면서 연구 단계에서 프로덕션까지 이어지는 경로를 구축했습니다.
동시에 실제 운영 과정에서 발견된 문제도 플랫폼 차원에서 보완했습니다.
- 호환 가능한 버전 고정
- 누락되는 API 필드 보완
- Triton backend와 Python backend의 역할 구분
- 모델 배포 전략 개선
- vLLM과 Triton 메트릭 통합
- 사용자 정의 디코딩 로직 최적화
앞으로는 다음 네 가지 영역에 대한 투자를 계획하고 있습니다.
시스템 프롬프트 압축
품질을 희생하지 않으면서 프롬프트 길이를 줄이는 방향입니다.
프롬프트 길이를 줄이면 LLM이 처리해야 하는 입력량 자체를 줄일 수 있기 때문에 효율적인 추론을 위한 하나의 개선 영역이 될 수 있습니다.
vLLM V1 비동기 스케줄링
현재 vLLM V1의 비동기 스케줄링을 활용하는 방향도 다음 투자 영역에 포함됩니다.
GPU 융합 커널 기반 로짓 프로세서
현재 CPU 코드에서 처리하는 부분을 GPU 융합 커널로 옮겨 더 효율적으로 실행하는 방향입니다.
배치 처리와 GPU 실행을 더욱 밀접하게 연결해 CPU에서 발생하는 병목을 줄이는 것이 목표입니다.
저정밀 모델 변형
메모리 사용량을 줄이고 처리량을 높이기 위한 저정밀 모델 변형도 계획하고 있습니다.
이는 대규모 모델을 GPU 환경에서 운영할 때 필요한 자원 효율성을 높이는 방향입니다.
Netflix는 앞으로도 Triton, vLLM, PyTorch 등 오픈소스 ML 라이브러리를 계속 활용하면서 관련 커뮤니티와 협력할 계획입니다.
Netflix의 LLM 서빙 플랫폼에서 가장 눈에 띄는 부분은 LLM을 기존 ML 시스템과 완전히 분리하지 않았다는 점입니다.
기존 서빙 시스템의 라우팅과 A/B 테스트, 로깅, 배포, 상태 확인 등의 운영 체계를 그대로 활용하면서 LLM을 Model Scoring Service와 Triton에 통합했습니다.
그 위에서 vLLM을 기본 추론 엔진으로 선택해 사용자 정의 모델과 디코딩 로직을 지원하고, OpenAI 호환 API를 추가해 LLM 생태계와의 연결성도 확보했습니다.
하지만 실제 프로덕션 환경에서는 단순한 엔진 선택만으로 충분하지 않았습니다.
Triton과 vLLM의 버전이 맞지 않으면 backend가 로드되지 않을 수 있고, API가 특정 필드를 조용히 누락할 수도 있습니다. GPU 모델은 시작 시간이 길며, 모델 버전 변경으로 I/O 스키마가 달라지면 단순한 Red-Black 배포만으로 해결하기 어려운 상황도 발생합니다.
Netflix는 이런 문제를 버전 고정, API 패치, 모델 캐시, Versioned 배포 등의 방식으로 보완했습니다.
특히 디코딩 과정의 최적화 사례는 LLM 서빙에서 성능을 바라보는 관점을 보여줍니다.
GPU에서 모델을 빠르게 실행하는 것만으로 전체 시스템이 빨라지는 것은 아닙니다. 실제 동시 요청이 증가하면 CPU의 로짓 처리나 Python GIL과 같은 주변 로직이 병목이 될 수 있습니다.
Netflix는 이를 vLLM V1의 배치 단위 처리와 멀티스레드 C++ 구현으로 개선했고, 부분 prefill과 선점처럼 실제 운영에서 발생하는 상태 변화까지 처리했습니다.
결국 Netflix 사례가 보여주는 핵심은 LLM 서빙은 단순히 모델을 GPU에서 실행하는 기술이 아니라는 것입니다.
모델 실행 엔진부터 API, 패키징, 버전 관리, 배포, 캐시, 메트릭, 상태 관리, 사용자 정의 디코딩까지 하나의 프로덕션 시스템으로 설계해야 합니다.
특히 LLM 활용이 복잡해질수록 단순한 추론 성능보다 기존 인프라와 얼마나 자연스럽게 연결되는지, 장애가 발생했을 때 얼마나 쉽게 원인을 찾을 수 있는지, 모델 변경을 얼마나 안전하게 배포할 수 있는지가 중요해집니다.
Netflix가 vLLM과 Triton을 선택하고 계속해서 플랫폼을 개선하는 과정은 LLM 서빙이 앞으로 고성능 추론 엔진의 선택을 넘어 안정적인 ML 인프라 운영 문제로 확장되고 있다는 점을 보여주는 사례라고 할 수 있습니다.
https://netflixtechblog.com/in-house-llm-serving-at-netflix-a5a8e799ea2c
In-House LLM Serving at Netflix
By AI Platform’s Model Runtime team and Inference team
netflixtechblog.com

'인공지능' 카테고리의 다른 글
| Skill Recorder로 작업 과정을 AI 자동화로 만드는 방법 (0) | 2026.08.04 |
|---|---|
| AI 에이전트 보안의 새로운 기준, NanoClaw와 Echo가 브라우저부터 라이브러리까지 보호하는 방법 (0) | 2026.08.04 |
| MCP 2026-07-28 사양 업데이트, Stateless Protocol Core와 주요 변화 정리 (0) | 2026.08.04 |
| Diátaxis로 정리하는 기술 문서 작성 체계와 네 가지 문서 유형 (0) | 2026.08.03 |
| Seedance 2.5, 최대 30초 영상 생성부터 정밀 편집까지 지원하는 차세대 AI 영상 모델 (0) | 2026.08.03 |