Netflix Live Origin
Netflix Live Origin 분석
원문: Netflix Live Origin — Netflix Technology Blog (2025.12.16)
며칠 전, Netflix가 자체 라이브 스트리밍을 위해 만든 커스텀 오리진 서버에 대한 기술 블로그 글을 공개했습니다. 이 오리진은 2024년 타이슨-폴 복싱 경기에서 동시 6,500만 스트림을 처리한 인프라의 핵심 컴포넌트입니다. 일반적인 CDN 오리진과는 결이 다른, 라이브 전용 설계가 곳곳에 녹아 있어서 이번 글에서 하나씩 뜯어보겠습니다.
생각
보통 라이브 스트리밍 오리진이라고 하면, 패키저가 세그먼트를 밀어 넣고 CDN이 그걸 당겨가는 단순한 파일 서버를 떠올리기 쉽습니다. AWS라면 MediaPackage가 오리진 역할을 맡고, Tencent Cloud라면 StreamPackage가 같은 포지션입니다. 그런데 Netflix는 이 오리진을 직접 만들었습니다. Open Connect(자체 CDN)와 클라우드 인코딩 파이프라인 사이에 자리 잡고, 단순히 세그먼트를 저장하고 서빙하는 데 그치지 않고 어떤 세그먼트를 내보낼지 판단하는 브로커 역할까지 맡습니다. "오리진이 똑똑하면 CDN이 편해진다"는 철학이 전체 설계를 관통하고 있습니다.
전체 아키텍처
Netflix 라이브 파이프라인에서 Live Origin이 차지하는 위치는 다음과 같습니다.

Live Origin은 AWS EC2 위에서 동작하는 멀티테넌트 마이크로서비스입니다. 패키저가 HTTP PUT으로 세그먼트를 밀어 넣으면, Open Connect가 HTTP GET으로 이를 가져갑니다. 프로토콜은 표준 HTTP를 그대로 씁니다. 별도의 커스텀 프로토콜 없이 PUT과 GET만으로 동작한다는 점이 인상적입니다.
Tencent Cloud로 매핑하면 StreamPackage가 가장 가까운 포지션입니다. StreamLive(인코더) → StreamPackage(패키징+오리진) → CSS(CDN 배포)로 이어지는 구조에서, StreamPackage가 오리진 역할을 맡습니다.
다만 Netflix처럼 "세그먼트 선별 로직"이 오리진에 내장된 구조는 아니며, StreamPackage는 패키징과 DRM에 집중합니다.
핵심 설계 1: 멀티 파이프라인 인식 오리진
라이브는 태생적으로 결함이 발생할 수밖에 없습니다. 프레임 드랍, 세그먼트 누락, 타이밍 불연속 — 실시간 인코딩에서는 이런 일이 언제든 일어날 수 있습니다.
여기서 Netflix가 택한 대응은 이중 인코딩 파이프라인을 독립된 리전에서 돌리고, 오리진이 그중 더 나은 쪽을 선택하는 방식입니다.
동작 방식은 다음과 같습니다.
- 두 파이프라인(A, B)이 동일한 세그먼트를 독립적으로 생성합니다.
- 패키저가 세그먼트를 오리진에 PUT할 때, 미디어 헬스체크 결과를 메타데이터로 함께 첨부합니다.
- Open Connect가 GET 요청을 보내면, 오리진은 결정론적 순서로 후보를 확인해 정상인 쪽을 반환합니다.
- 극히 드물게 양쪽 모두 결함이 있으면, 결함 정보를 다운스트림에 전달해 클라이언트가 에러 은폐(concealment) 처리를 하도록 합니다.
이게 가능한 이유는 클라우드 인코더에 epoch locking(인코더들은 공통된 기준 시각(Epoch Time)을 기준으로 세그먼트 경계를 계산하므로, 서로 다른 인코딩 파이프라인에서도 동일한 세그먼트 번호와 타이밍의 미디어 세그먼트를 만들어낼 수 있습니다. 이 덕분에 장애가 발생해도 플레이어는 세그먼트 끊김 없이 다른 파이프라인으로 전환할 수 있습니다.)을 구현했기 때문입니다. 양쪽 파이프라인이 동일한 세그먼트 번호를 동일한 시점에 생성하므로, 오리진 입장에서는 둘 중 하나를 골라주기만 하면 됩니다.
이 구조의 핵심은 "파이프라인 페일오버를 클라이언트가 아니라 서버에서 처리한다"는 데 있습니다. 클라이언트의 복잡도를 줄이는 대신 오리진이 똑똑해지는 트레이드오프를 택한 셈입니다.
일반적인 CDN 오리진은 이런 판단을 하지 않습니다. 받은 걸 그대로 서빙할 뿐입니다.
핵심 설계 2: Open Connect 스트리밍 최적화
Netflix의 Open Connect는 원래 VOD에 최적화된 CDN이었습니다. 콘텐츠를 미리 OCA에 배치해두는 구조라서, 라이브처럼 "아직 존재하지 않는 파일을 달라"는 요청 패턴과는 잘 맞지 않았습니다.
그래서 넷플릭스가 풀어야 했던 문제는 다음과 같습니다.
불필요한 요청 차단
OCA는 세그먼트 템플릿을 미리 알고 있으므로, 아직 존재할 수 없는 시간대의 세그먼트 요청은 오리진까지 올라가기 전에 엣지 단에서 거부됩니다.
요청 홀딩 (Hold-Open)
오리진이 "다음 세그먼트"에 대한 요청을 받았을 때, 아직 퍼블리시되지 않았다면 곧바로 404를 돌려주는 대신 커넥션을 열어둔 채 대기하다가 세그먼트가 도착하면 바로 응답합니다. 이 방식으로 네트워크 안의 불필요한 재요청 트래픽을 크게 줄일 수 있습니다.
밀리초 단위 캐싱
세그먼트는 2초마다 생성되는데, 표준 HTTP Cache-Control은 초 단위로만 동작합니다. Netflix는 nginx에 밀리초 단위 캐시 제어를 추가해서 라이브 엣지 근처의 캐시 정합성을 확보했습니다.
"2초짜리 세그먼트에 초 단위 캐시는 너무 거칠다"는 인식에서 나온 선택입니다. 이건 라이브를 직접 운영해본 사람만 체감하는 문제입니다. HLS에서 세그먼트 duration을 줄이면 매니페스트 업데이트 빈도가 올라가고, 캐시 무효화 타이밍도 그만큼 까다로워집니다.
핵심 설계 3: 스토리지 아키텍처
넷플릭스도 처음에는 VOD에서 쓰던 것과 동일하게 그냥 S3를 사용했습니다. 소규모 이벤트에서는 별문제가 없었지만, 서비스 규모가 커지면서 라이브의 요구사항이 S3와 잘 맞지 않는다는 걸 깨닫게 됐습니다.
Netflix가 정의한 Live Origin 스토리지 요구사항은 다음과 같습니다.
| 요구사항 | 설명 |
|---|---|
| HA Writes | 단일 리전 내 극한의 쓰기 가용성. 500ms 내 쓰기 실패는 버그로 간주 |
| Throughput | 수백 MiB/s의 크로스 리전 복제 |
| Large Partitions | MiB 단위 쓰기, 이벤트당 GiB급 누적 |
| Strong Consistency | 같은 리전 내 Read-your-write. 퍼블리시 후 1초 이내 읽기 가능 |
| Origin Storm | GiB급 읽기 처리량에서도 쓰기에 영향 없음 |
S3는 훌륭한 오브젝트 스토리지지만, 이 요구사항은 오브젝트 스토리지보다는 "글로벌 저지연 고가용 데이터베이스"에 훨씬 가까웠습니다. 그래서 넷플릭스는 이 스토리지 계층을 처음부터 직접 만들기로 합니다.
최종 스토리지 스택
Live Origin
└→ KeyValue Storage Abstraction
├→ Write: Apache Cassandra (LSM 기반, AZ 장애에도 쓰기 가능)
└→ Read: EVCache (Memcached 기반 분산 캐시)쓰기 경로: KeyValue 추상화 계층이 MiB급 페이로드를 청크로 쪼개서 Cassandra에 분산 저장합니다. 각 청크는 멱등하게 재시도하거나 헤징할 수 있고, local-quorum 일관성 덕분에 AZ 하나가 죽어도 쓰기가 계속됩니다.
읽기 경로: Write-through 캐시로 EVCache(Memcached)를 앞단에 둡니다. 거의 모든 읽기가 캐시에서 처리되기 때문에, 200Gbps가 넘는 읽기 트래픽이 몰려도 쓰기 성능에는 영향을 주지 않습니다.

결과적으로 P99 쓰기 지연이 기존 S3 기반 구조의 P50 수준까지 내려왔습니다. SSD 기반 DB이다 보니 비용은 함께 올라갔지만,
"라이브에서 쓰기 실패는 곧 세그먼트 유실이고, 이는 시청자 화면이 끊기는 결과로 이어진다"는 판단 아래 비용보다 가용성을 우선했습니다.
핵심 설계 4: 스케일링 아키텍처

2024년 타이슨 vs 폴 경기에서는 동시 6,500만 스트림이 몰렸습니다. 이 정도 규모를 버티려면 오리진 자체가 수평 확장 가능한 구조여야 합니다.
Netflix는 전통적인 Origin Shield 방식 대신 직접 확장 가능한 오리진을 선택했습니다. 엔드투엔드 캐시 일관성을 제어하기가 더 쉽기 때문입니다.
퍼블리시/검색 경로 분리
| 계층 | 퍼블리시(쓰기) | CDN 검색(읽기) |
|---|---|---|
| EC2 | 전용 퍼블리시 스택 | 전용 CDN 스택 |
| 스토리지 추상화 | KV Write 클러스터 | KV Read 클러스터 |
| 스토리지 엔진 | Cassandra (쓰기) | EVCache (읽기) |
CDN 쪽에서 트래픽이 폭증해도 퍼블리시 경로에는 영향이 가지 않습니다. 라이브에서 쓰기가 밀리면 곧 세그먼트가 늦게 나오는 문제로 이어지기 때문에, 이 격리는 사실상 생명줄과 같습니다.
우선순위 기반 Rate Limiting
시스템에 부하가 걸리면, 넷플릭스는 요청을 동등하게 처리하지 않습니다.
| 우선순위 | 트래픽 유형 | 보호 방법 |
|---|---|---|
| 높음 | 퍼블리시 (세그먼트 쓰기) | 경로 분리 |
| 높음 | 라이브 엣지 검색 | 우선 처리 |
| 낮음 | DVR 검색 (과거 구간) | 부하 시 503 + 5초 캐시로 억제 |
| 낮음 | 존재하지 않는 세그먼트 요청 | 404 + TTL로 조기 차단 |
라이브 엣지인지 DVR인지는 세그먼트 템플릿을 기준으로 판단합니다. 템플릿을 오리진 노드의 메모리에 캐시해두기 때문에, 별도의 데이터스토어 접근 없이도 우선순위를 곧바로 결정할 수 있습니다.

저우선순위 트래픽이 몰릴 때는 503과 함께
max-age=5s를 돌려보내서, Open Connect가 5초 동안 같은 요청을 반복하지 않도록 합니다. 간단하지만 효과가 확실한 구현입니다.
핵심 설계 5: 404 Storm 대응
대규모 라이브 서비스에서는 존재하지 않는 세그먼트에 대한 요청이 순간적으로 폭증하는 경우가 있습니다. 일반적인 구조라면 이런 요청이 모두 스토리지까지 전달되어(404는 보통 네거티브 캐싱을 하지 않으므로) 불필요한 부하를 유발할 수 있습니다. 하지만 넷플릭스는 채널과 렌디션 관련 메타데이터를 별도의 컨트롤 플레인 저장소와 인메모리 캐시에 보관합니다. 대부분의 조회가 캐시에서 처리되기 때문에, 잘못된 요청이 대량으로 발생하더라도 스토리지 계층까지 부하가 전파되지 않습니다. 장애 상황에서도 서비스를 안정적으로 유지할 수 있는 핵심 설계 요소 중 하나입니다.
아직 생성되지 않은 세그먼트에 요청이 몰리는 상황을 "404 Storm"이라고 부릅니다. 오리진은 메타데이터 계층 구조를 활용해 이 상황에 대응합니다.
Event → Stream Rendition → Segment처리 로직은 다음과 같습니다.
- 이벤트 자체가 없으면 → 메모리 캐시만으로 즉시 404를 반환합니다.
- 이벤트는 있지만 타이밍이 안 맞으면 → 예상 퍼블리시 시간에 맞춰 TTL을 설정한 404를 반환합니다.
- 세그먼트가 끝내 생성되지 않거나 데드라인을 넘기면 → 410 Gone을 반환해 클라이언트가 재요청을 멈추게 합니다.
메타데이터는 미디어 데이터와는 별도의 컨트롤 플레인 스토어에 저장됩니다. 이벤트와 렌디션 레벨의 메타데이터는 인메모리 캐시 적중률이 90%를 넘기 때문에, 404 폭풍이 몰려와도 스토리지 계층으로 부하가 전이되지 않습니다.
핵심 설계 6: 캐시 무효화와 오리진 마스킹
캐시 무효화
캐시 키에 버전 번호를 포함시켜서, 버전을 올리면 해당 이벤트의 모든 캐시가 한 번에 무효화됩니다. 이벤트 전 테스트를 마친 뒤 네트워크를 깨끗한 상태로 되돌릴 때 이렇게 사용합니다.
더 세밀한 무효화도 가능합니다. 예를 들어 "세그먼트 100~150번, 단 인코더 A에서 나온 것만, 리전 X에서 요청된 것만" 같은 조건부 무효화도 지원합니다.
오리진 마스킹
특정 파이프라인의 특정 구간 세그먼트를 서빙 대상에서 제외하는 기능입니다. 문제가 있는 세그먼트가 발견되면 마스킹을 걸어서, DVR 구간에서도 시청자에게 나가지 않도록 보호합니다. 수백만 스트리밍 클라이언트를 문제 세그먼트로부터 격리하는 안전장치인 셈입니다.
스트리밍 메타데이터 향상
넷플릭스는 HTTP 응답 헤더에 스트림 내 이벤트 알림을 담아 전달합니다. 광고 시작이나 챕터 전환 같은 이벤트를 세그먼트 헤더에 실어 보내는 방식입니다.
특징은 다음과 같습니다.
- 알림은 누적형으로 동작해, 이후 세그먼트에도 계속 포함됩니다.
- OCA는 세그먼트를 받을 때 헤더에서 알림 정보를 추출해 인메모리에 저장합니다.
- 클라이언트가 라이브 엣지보다 뒤처져 있어도 최신 알림을 받을 수 있습니다.
- 세그먼트뿐 아니라 모든 응답에 알림 정보를 실을 수 있습니다.
Tencent Cloud CSS는 SCTE-35 마커로 비슷한 역할을 수행하지만, Netflix는 HTTP 헤더 기반으로 더 범용적인 알림 채널을 만든 셈입니다. DASH의 InbandEventStream과 비슷한 역할을 하면서도, 매니페스트가 아니라 세그먼트 응답 헤더에 태우는 방식이 독특합니다.
Tencent Cloud 제품 매핑
Netflix의 각 컴포넌트를 Tencent Cloud 제품으로 대응시켜보면 다음과 같습니다.
| Netflix 컴포넌트 | 역할 | Tencent Cloud 대응 |
|---|---|---|
| Cloud Encoder | 라이브 인코딩, 이중화 | StreamLive (채널 기반 인코딩, 듀얼 파이프라인) |
| Packager | 세그먼트 패키징 | StreamLive Output 또는 StreamPackage 입력 |
| Live Origin | 오리진 서버 + 세그먼트 선별 | StreamPackage (오리진 역할, 단 선별 로직은 없음) |
| Open Connect | 자체 CDN | CSS CDN 배포 |
| EVCache + Cassandra | 오리진 스토리지 | 해당 없음 (StreamPackage 내부 구현) |
Netflix와 Tencent Cloud의 근본적인 차이는 다음과 같습니다.
- Netflix는 자체 CDN과 자체 오리진을 모두 갖고 있어서 엔드투엔드 제어가 가능합니다.
- Tencent Cloud는 매니지드 서비스 조합이라 서비스 간 경계는 명확하지만, Netflix처럼 오리진이 "세그먼트를 고르는" 수준의 인텔리전스를 서비스 단위로 제공하기는 어렵습니다.
- StreamPackage의 Endpoint 이중화와 Input Failover가 Netflix의 멀티 파이프라인 선택과 비슷한 포지션이지만, 구현 깊이는 다릅니다.
마치며
대부분의 라이브 플랫폼은 패키저 뒤에 S3나 일반 오브젝트 스토리지를 두고, CDN이 이를 오리진으로 바라보는 구조에서 출발합니다. 사실 이 정도만으로도 상당수 서비스는 충분히 운영할 수 있습니다. Netflix 역시 처음부터 지금과 같은 구조를 갖고 있었던 건 아닙니다.
흥미로운 점은, Netflix가 6,500만 동시 스트림 규모를 처리하는 과정에서 단순히 서버 대수를 늘리는 선택을 하지 않았다는 사실입니다. 세그먼트 생성 지연, 404 폭풍, 오리진 부하 전파, 장애 복구, 페일오버 일관성 같은 문제를 하나씩 분해하고, 각각에 별도의 시스템적 해법을 만들어냈습니다. Epoch Locking, Origin Shield, 컨트롤 플레인 분리, 메타데이터 캐싱 같은 설계는 모두 특정 문제를 풀기 위해 나온 결과물입니다.
이 글을 읽으며 가장 인상 깊었던 부분은 개별 기술 자체보다 문제를 바라보는 방식이었습니다. 대규모 시스템에서는 단순히 "동작한다"가 목표가 아닙니다. 장애가 발생해도 버틸 수 있는지, 비정상 트래픽이 들어와도 다른 계층으로 전파되지 않는지, 특정 컴포넌트가 실패해도 전체 서비스는 계속 동작하는지를 끊임없이 따져야 합니다. Netflix의 아키텍처는 그런 사고방식이 수년간 쌓인 결과처럼 보입니다.
블로그 글 속 구조도만 보면 모든 게 단순해 보입니다. 하지만 실제 운영 환경에서는 세그먼트 하나가 예상보다 500ms 늦게 생성되는 순간부터 수많은 문제가 연쇄적으로 터질 수 있습니다. 결국 대규모 스트리밍 시스템의 본질은 화려한 기술 스택이 아니라, 그런 작은 실패가 전체 서비스 장애로 번지지 않게 만드는 엔지니어링에 있는 듯합니다.
그래서 이 글의 진짜 가치는 특정 제품이나 기능 소개가 아니라, Netflix가 문제를 어떻게 정의하고 시스템을 진화시켜 왔는지 엿볼 수 있다는 데 있습니다. 라이브 스트리밍을 다루는 엔지니어라면 규모와 관계없이 한 번쯤 배워볼 만한 설계 철학이라고 생각합니다. 물론 이걸 그대로 구현할 수 있느냐는 또 다른 문제입니다.