2026-10-29 정정 — 특정 기업의 40% 절감 및 항상 이중 인코딩한다는 주장을 철회했습니다. 남은 성능·가격·퍼널 그래프는 원자료 미확인 예시로 표시하며 운영 실적의 근거로 사용하지 않습니다.

HLS와 DASH는 서로 다른 매니페스트를 사용한다. 그렇다고 항상 영상을 두 번 인코딩해야 하는 것은 아니다. 같은 압축 비트스트림을 다른 컨테이너로 포장할 수 있기 때문이다.

CMAF는 조건이 맞으면 HLS와 DASH가 fragmented MP4 미디어를 공유하도록 돕는다. 코덱, 암호화 방식, 트랙 구성과 플레이어 지원이 맞아야 한다. 패키징 중복 감소와 인코딩 횟수 감소는 같은 주장이 아니다. Disney+의 40% 비용 절감이라는 기존 주장은 근거를 확인하지 못해 철회했다.

LL-HLS는 부분 세그먼트와 갱신·요청 규칙을 이용한다. 200ms는 가능한 구성 예시이지 필수 청크 길이가 아니다. Apple HLS 작성 지침을 함께 확인한다.


1. CMAF가 끝낸 HLS/DASH 분열

CMAF 도입 Before/After — 두 파이프라인이 하나로

Before (2015):

진영 컨테이너 매니페스트 디바이스
Apple HLS MPEG-TS (.ts) .m3u8 iOS, Safari, Apple TV
Google/MS DASH fMP4 (.m4s) .mpd Android Chrome, Smart TV, Xbox

같은 영상을 두 번 인코딩 → 두 번 저장 → CDN 캐시도 따로.

After (2016+):

encoding/
├── master.m3u8       ← HLS 매니페스트
├── manifest.mpd      ← DASH 매니페스트
└── segments/
    ├── init.mp4      ← 초기화 (공유)
    ├── seg_1.m4s     ← 미디어 (공유)
    ├── seg_2.m4s
    └── ...

가능했던 이유: HLS v7 (2016)이 fMP4 지원. iOS 10 이상이면 OK. 8년 전 디바이스 이하만 호환성 신경.


2. CMAF 도입 효과 — 실제 절감 수치

설명용 가정 · 실측 근거 미확인: 대형 OTT CMAF 도입 추정 효과 (Disney+ 기준)

음수 = 절감, 양수 = 증가. 인코딩 1번이면 처리량 2배, 스토리지 절반.


3. fMP4가 가능했던 이유 — 일반 MP4와의 차이

구분 일반 MP4 fMP4
메타데이터 moov 전체 미디어 정보 moov (init) + moof (조각별)
재생 시작 moov 다 받아야 첫 조각만 받으면
시킹 moov 인덱스로 sidx + 조각 독립
스트리밍 어려움 최적
세그먼트화 불가 자연스러움

fMP4 = moov 분리 + 조각마다 moof 메타데이터. 각 조각이 독립 디코딩.


4. init.mp4 박스 트리

flowchart TB
  ROOT[init.mp4] --> FTYP[ftyp<br/>major_brand: cmfc]
  ROOT --> MOOV[moov]
  MOOV --> MVHD[mvhd<br/>movie header]
  MOOV --> TRAK[trak<br/>video track]
  MOOV --> MVEX[mvex<br/>fragmented 신호]
  TRAK --> TKHD[tkhd]
  TRAK --> MDIA[mdia]
  MDIA --> MDHD[mdhd<br/>timescale]
  MDIA --> HDLR[hdlr<br/>= vide]
  MDIA --> MINF[minf → stbl → stsd]
  MINF --> AVC1[avc1<br/>sample entry]
  AVC1 --> AVCC[avcC<br/>H.264 SPS/PPS]
구조와 흐름

avcC가 H.264 SPS/PPS 들고 있음 → 디코더 초기화의 핵심. mvex 박스가 없으면 일반 MP4로 인식됨.


5. .m4s 미디어 세그먼트 박스 트리

flowchart TB
  ROOT[seg_N.m4s] --> STYP[styp<br/>brands: msdh, msix]
  ROOT --> SIDX[sidx<br/>segment index<br/>선택]
  ROOT --> MOOF[moof<br/>movie fragment]
  ROOT --> MDAT[mdat<br/>실제 NAL units]
  MOOF --> MFHD[mfhd<br/>sequence number]
  MOOF --> TRAF[traf<br/>track fragment]
  TRAF --> TFHD[tfhd<br/>track header]
  TRAF --> TFDT[tfdt<br/>baseMediaDecodeTime<br/>★ 시간 정보 핵심]
  TRAF --> TRUN[trun<br/>샘플별 size/duration/flags]
구조와 흐름

핵심 박스:

  • tfdt: 이 세그먼트의 시작 시간 — ABR 전환, 시킹에 필수
  • trun: mdat 안의 NAL unit 자르는 정보
  • mdat: H.264 NAL units (IDR + P-frame들)

6. fMP4 박스 빠른 참조

박스 위치 역할
ftyp init.mp4 파일 타입, CMAF면 cmfc
moov init.mp4 초기화 메타데이터
mvex moov 안 fragmented임을 신호
avcC stsd 안 H.264 SPS/PPS
styp .m4s 세그먼트 타입, msdh/msix
sidx .m4s 세그먼트 인덱스 (선택)
moof .m4s 조각 메타데이터
tfdt traf 안 디코드 시작 시간
trun traf 안 샘플별 정보
mdat .m4s 실제 미디어 데이터
# 박스 분석
MP4Box -info input.mp4              # GPAC
mp4dump --verbose input.m4s | head  # Bento4
ffprobe -show_format -of json *.m4s

라이브 디버깅에서 일상 도구.


7. timescale — 시간 단위의 함정

timescale: 90000  →  1초 = 90000

예시:
sample_duration 3000      → 3000/90000 = 1/30초 (30fps)
sample_duration 1500      → 1/60초 (60fps)
baseMediaDecodeTime 7200000 → 80초

비디오 90000 (MPEG 표준), 오디오 48000 (샘플레이트). 서로 다른 timescale 정확히 동기화가 트랜스코더의 일.


8. CMAF Constraint — 표준 준수 7항목

# 규칙 위반 시
1 모든 세그먼트가 IDR(키프레임)로 시작 ABR 전환 불가
2 moof + mdat 박스 순서 준수 일부 플레이어 거부
3 mfhd sequence_number 순차 증가 순서 혼란
4 tfdt baseMediaDecodeTime 정확 시간 점프
5 timescale 일관성 동기화 깨짐
6 init.mp4에 mvex 박스 필수 fragmented 인식 안 됨
7 .m4s styp에 msdh/msix 브랜드 CMAF 호환 안 됨

Shaka Packager가 자동 보장. 직접 fMP4 만들면 실수하기 쉬움.


9. MPEG-TS vs fMP4 — 어디서 뭘 쓰나

항목 MPEG-TS fMP4
오버헤드 TS 패킷·적응 필드·다중화 조건에 따라 변동 박스·샘플·fragment 구성에 따라 변동
시킹 패킷 단위 파싱 sidx 즉시
메타데이터 단순 (PID) 풍부
오류 복구 패킷 단위 가능 박스 손상 시 fragment 전체
호환성 모든 디바이스 iOS 10+, Android 5+
인제스트(스트리머 → 플랫폼): MPEG-TS (RTMP/SRT 위)
배포(플랫폼 → 시청자): fMP4/CMAF

각 단계에 맞는 컨테이너.


10. Chunked CMAF — LL-HLS의 기반

Chunked CMAF — 6초 세그먼트를 200ms 청크로 점진 전송

일반 CMAF는 6초 인코딩 다 끝나야 .m4s 생성. 지연 18~25초.

Chunked CMAF: 한 .m4s 안에 (moof + mdat) 청크 30개. 200ms 청크가 만들어지자마자 HTTP/1.1 chunked encoding으로 즉시 전송.

[일반 .m4s]
moof + mdat (전체 6초)

[Chunked .m4s]
moof + mdat (청크 1, 0~200ms)
moof + mdat (청크 2, 200~400ms)
moof + mdat (청크 3, 400~600ms)
...

플레이어가 청크 받자마자 디코더에 넘김. 세그먼트 완성 대기 0초.


11. LL-HLS 지연 분해 — 1.9초의 정체

설명용 가정 · 실측 근거 미확인: LL-HLS 잘 튜닝된 라이브 — 단계별 지연 (ms)

총 약 1.9초. 플레이어 버퍼가 최대 비중. 더 줄이려면 WebRTC.


12. 프로토콜별 지연 비교

설명용 가정 · 실측 근거 미확인: 라이브 프로토콜 지연 비교 (초)

LL-HLS는 일반 HLS의 10배 개선. WebRTC는 또 그 10배.


13. LL-HLS 매니페스트 — EXT-X-PART

청크를 매니페스트에 노출.

#EXTM3U
#EXT-X-VERSION:9
#EXT-X-TARGETDURATION:6
#EXT-X-SERVER-CONTROL:CAN-BLOCK-RELOAD=YES,PART-HOLD-BACK=1.0
#EXT-X-PART-INF:PART-TARGET=0.2

#EXT-X-MAP:URI="init.mp4"

#EXTINF:6.0,
seg_1.m4s
#EXTINF:6.0,
seg_2.m4s

# 진행 중인 세그먼트의 청크들
#EXT-X-PART:DURATION=0.2,URI="seg_3.m4s",BYTERANGE="50000@0"
#EXT-X-PART:DURATION=0.2,URI="seg_3.m4s",BYTERANGE="42000@50000"
#EXT-X-PART:DURATION=0.2,URI="seg_3.m4s",BYTERANGE="47000@92000"

#EXT-X-PRELOAD-HINT:TYPE=PART,URI="seg_3.m4s",BYTERANGE-START=139000
#EXT-X-RENDITION-REPORT:URI="720p/playlist.m3u8",LAST-MSN=42,LAST-PART=14
태그 역할
EXT-X-PART 청크 위치 (URI + byterange)
EXT-X-PART-INF 청크 길이 정보
EXT-X-PRELOAD-HINT 다음 청크 미리 알림
EXT-X-SERVER-CONTROL Blocking reload 허용
EXT-X-RENDITION-REPORT 다른 화질 진행 상황

14. Blocking Playlist Reload — 폴링 없이 push

GET /playlist.m3u8?_HLS_msn=42&_HLS_part=15

"시퀀스 42의 파트 15보다 새 게 나올 때까지 대기."

서버가 응답을 보류했다가 새 청크 생기면 즉시 회신. 클라이언트 폴링 없이 push 효과. 대신 서버는 long polling 처리 필요.

# Shaka Packager로 chunked CMAF 인코딩
packager \
  'in=video.mp4,stream=video,init_segment=init.mp4,segment_template=seg_$Number$.m4s' \
  --hls_master_playlist_output master.m3u8 \
  --hls_playlist_type LIVE \
  --segment_duration 6 \
  --fragment_duration 0.2 \
  --low_latency_dash_mode

15. CDN 캐시 TTL — 매니페스트 vs 세그먼트 분리

설명용 가정 · 실측 근거 미확인: TTL 설정에 따른 CDN 캐시 히트율 (라이브)

매니페스트는 매 6초 변함 → TTL 1~2초가 최적 sweet spot. 세그먼트는 한 번 만들어지면 안 변함 → TTL 24시간.

# 매니페스트
Cache-Control: max-age=2

# 세그먼트
Cache-Control: max-age=86400

이 분리만 잘해도 CDN 비용 큰 차이.


16. fMP4 vs MPEG-TS 오버헤드

설명용 가정 · 실측 근거 미확인: 동일 H.264 콘텐츠 — 컨테이너 오버헤드 비교 (1080p60 6Mbps 기준)

오버헤드 차이를 비용으로 환산하려면 실제 파일 크기와 동일한 미디어 데이터량을 비교해야 한다. 고정된 1.5%p 절감으로 가정하지 않는다.


17. CENC — Common Encryption

CMAF의 또 다른 큰 가치: 하나의 .m4s에 다중 DRM.

sequenceDiagram
  participant V as 시청자 플레이어
  participant CDN
  participant L as 라이센스 서버
  
  V->>CDN: master.m3u8 / manifest.mpd 요청
  CDN-->>V: 매니페스트 (KID 포함)
  V->>CDN: seg_N.m4s 요청
  CDN-->>V: 암호화된 .m4s (디코딩 불가)
  V->>L: 라이센스 요청<br/>{KID, 디바이스, 사용자 토큰}
  L-->>V: 키 + 권한<br/>(디바이스에 맞게 암호화)
  V->>V: 키로 .m4s 복호화 → 재생
구조와 흐름

이전엔 HLS용 암호화 + DASH용 암호화 따로. CENC로 같은 .m4s 파일을 Widevine/FairPlay/PlayReady가 공유.


18. CTR vs CBCS 암호화 모드

모드 풀네임 표준 특징
AES-CTR Counter mode DASH (Widevine, PlayReady) 빠름
AES-CBCS CBC with subsample HLS (FairPlay) iOS/Safari 필수, 약간 무거움
[현실적 선택]
- DASH 전용: CTR
- HLS 전용: CBCS
- 통합 Multi-DRM: 두 번 암호화 또는 CBCS 단일
  (Widevine도 CBCS 지원, 최근 트렌드)

19. DRM 3진영

DRM 벤더 플랫폼 보안 레벨
Widevine Google Android, Chrome, ChromeOS, Smart TV L1/L2/L3
FairPlay Apple iOS, macOS Safari, Apple TV 모바일 필수
PlayReady Microsoft Xbox, Windows, Edge 비중 감소

OTT는 보통 셋 다 지원 (Multi-DRM). Shaka Packager 한 명령으로 셋 다 처리.

packager \
  'in=video.mp4,stream=video,init_segment=init.mp4,segment_template=seg_$Number$.m4s,drm_label=video' \
  --enable_widevine_encryption --key_server_url https://widevine/v1/key ... \
  --enable_playready_encryption --playready_server_url https://playready/v1/key \
  --enable_fairplay_encryption --fairplay_key_uri skd://fairplay/key \
  --hls_master_playlist_output master.m3u8 \
  --mpd_output manifest.mpd

20. SCTE-35 — 광고 마커

#EXTINF:6.0,
seg_42.m4s
#EXT-X-CUE-OUT:DURATION=30      ← 광고 시작
#EXTINF:6.0,
seg_43.m4s
...
#EXT-X-CUE-IN                   ← 광고 끝, 본 콘텐츠 복귀
#EXTINF:6.0,
seg_48.m4s

방송 표준 SCTE-35 마커가 HLS의 CUE-OUT/CUE-IN으로. 플레이어가 광고 매니페스트로 전환.


21. SSAI vs CSAI — 광고 삽입 두 방식

flowchart TB
  subgraph CSAI [CSAI Client-Side Ad Insertion]
    C1[플레이어] -->|광고 시점| C2[광고 영상 별도 요청]
    C2 --> C3[Ad Server]
    C3 -.->|광고 차단기 차단 가능| C1
  end
  subgraph SSAI [SSAI Server-Side Ad Insertion]
    S1[SSAI 서버] -->|광고 끼운<br/>매니페스트| S2[플레이어]
    S3[Origin 본 영상] --> S1
    S4[광고 세그먼트] --> S1
    S2 -->|구분 안 됨<br/>차단 불가| S2
  end
구조와 흐름
CSAI SSAI
광고 위치 클라이언트 요청 서버가 끼움
광고 차단 가능 불가
지연 있음 원활
CDN 캐시 본 영상 공유 매니페스트마다 다름
채택 레거시 YouTube, Hulu, Disney+

SSAI가 표준. 시청자별 매니페스트가 다르지만 광고 세그먼트는 공유 → CDN 캐시 효율 유지.


22. 광고 비콘 — 시청 funnel

설명용 가정 · 실측 근거 미확인: 광고 시청 완료율 funnel (일반 라이브 광고 기준)

VAST/VPAID 표준 비콘 이벤트. 25%/50%/75%/complete 단계별로 광고 서버에 전송. 광고 매출 정산의 핵심 데이터.


23. 라이브 → VOD 자동 변환

flowchart LR
  L1[라이브 방송 중<br/>type=EVENT<br/>ENDLIST 없음] --> L2{스트리머<br/>방송 종료?}
  L2 -->|YES| L3[시스템이<br/>EXT-X-ENDLIST 추가]
  L3 --> L4[매니페스트 = VOD]
  L4 --> L5[다시보기 재생 가능<br/>처음부터]
  L4 --> L6[추가 트랜스코딩<br/>썸네일/모바일 별도 ladder]
구조와 흐름

세그먼트는 그대로 보존. 매니페스트만 ENDLIST 태그 추가. 가벼운 작업.


24. QC 파이프라인 — 매분 자동 검증

flowchart LR
  A[매분 무작위<br/>스트림 샘플링] --> B[매니페스트 파싱<br/>EXT-X-MAP / 순서 / tfdt]
  B --> C[세그먼트 박스 검증<br/>moof+mdat / CMAF Constraint]
  C --> D[디코딩 테스트<br/>처음부터 5초]
  D --> E[VMAF 측정<br/>회귀 -2점 이상 알람]
  E --> F[광고 마커<br/>일관성 검증]
  F --> G{이상?}
  G -->|YES| H[즉시 알람<br/>PagerDuty]
  G -->|NO| I[정상]
구조와 흐름

매분 수십~수백 스트림 자동 검증. 라이브 인프라의 안전망.


25. CMAF 라이브 흔한 장애 3종

# 증상 원인 해결
1 디코딩 실패 init.mp4 변경 누락 (매니페스트는 옛 init) init.mp4 버전 관리 (init_v1.mp4, init_v2.mp4), 매니페스트 URI 함께 갱신
2 시퀀스 끊김 세그먼트 누락 (seg_42 → seg_44, 트랜스코딩 노드 hang) #EXT-X-DISCONTINUITY 추가, 플레이어 catch-up
3 PTS 점프 인코딩 재시작으로 tfdt 0부터 다시 baseMediaDecodeTime을 이전 끝 + 1로 강제, 또는 새 매니페스트 시퀀스

운영 경험: 거의 모든 라이브 장애가 이 셋 중 하나. 모니터링/대응 룰북 필수.


26. CMAF 도입 시 트레이드오프

도입 OK 시나리오:

  • 시청자 디바이스 iOS 10+, Android 5+ 비중 95% 이상
  • HLS와 DASH 둘 다 운영하는 OTT
  • LL-HLS 준비

도입 보류 시나리오:

  • 구형 스마트TV/피처폰 비중 큰 곳
  • HLS만 사용하고 LL-HLS도 필요 없음 (단일 인코딩이라 효과 미미)
  • 인제스트 단계 (RTMP/SRT는 MPEG-TS 그대로)

치지직처럼 게임 방송은 시청자 거의 다 최신 디바이스. 안전한 도입.


정리하면

CMAF는 컨테이너 통합 + 저지연 + DRM 통합의 종합 표준이다.

  1. HLS/DASH 분열 종식 — 같은 .m4s 공유, 매니페스트만 다름
  2. fMP4 = init.mp4(moov) + .m4s(moof+mdat) — 각 조각 독립 디코딩
  3. avcC에 H.264 SPS/PPS, mvex가 fragmented 신호
  4. tfdt + trun이 시간/샘플 정보의 핵심
  5. CMAF Constraint 7항목 — Shaka Packager가 자동 보장
  6. 인제스트 MPEG-TS, 배포 fMP4 — 단계에 맞는 컨테이너
  7. Chunked CMAF — 6초 세그먼트를 200ms 청크로 분할 전송
  8. LL-HLS 지연 ~1.9초 — 플레이어 버퍼가 최대 비중
  9. EXT-X-PART + Blocking Reload + Preload Hint — 폴링 없이 push
  10. CDN TTL 분리 — 매니페스트 1~2초, 세그먼트 24시간
  11. CENC로 하나의 .m4s에 Widevine/FairPlay/PlayReady 동시
  12. CTR (DASH) vs CBCS (Apple) — Widevine CBCS 지원으로 단일 암호화 트렌드
  13. SSAI가 표준 — 매니페스트 동적, 세그먼트 공유로 CDN 효율 유지
  14. SCTE-35 CUE-OUT/IN으로 라이브 광고 트리거
  15. 라이브→VOD = ENDLIST 추가만으로 자동 변환
  16. QC 파이프라인 매분 자동 검증 — 매니페스트/박스/디코딩/VMAF/광고 마커
  17. 흔한 장애 3종 — init.mp4 누락 / 세그먼트 누락 / PTS 점프

다음 글에선 CDN 멀티 벤더 전략 — Origin Shield, 멀티 CDN 라우팅, 비용 최적화 — 를 다룬다.


참고