Skip to content

HLS는 왜 스트리밍의 기본값이 됐나 ​

HLS는 Apple이 2009년에 제안한 HTTP 기반 적응형 스트리밍 프로토콜입니다. m3u8 매니페스트 파일이 미디어 세그먼트 목록을 담고 있고, 클라이언트가 이 목록을 주기적으로 갱신하며 세그먼트를 순차 다운로드해서 재생합니다. 현재 사실상 라이브/VOD를 불문하고 가장 널리 쓰이는 스트리밍 프로토콜입니다.


들어가기 전에 ​

2009년 iPhone 3GS 시절, Flash가 모바일에서 안 돌아가는 게 문제였습니다. Apple은 "HTTP 위에서 동작하는 스트리밍"이라는 발상으로 HLS를 만들었습니다. 기존 HTTP 인프라(웹서버, CDN, 캐시)를 그대로 활용할 수 있어서 별도 스트리밍 서버가 필요 없습니다. 이 단순함이 HLS가 지배적 프로토콜이 된 핵심 이유입니다.

DASH(MPEG-DASH)가 국제 표준으로 제안됐지만, Apple 생태계가 HLS만 지원하는 바람에 실질적으로 HLS가 업계 표준이 됐습니다. iOS/Safari에서 DASH를 네이티브로 재생할 수 없어서, 모바일 사용자를 포기할 수 없는 이상 HLS는 필수입니다.


핵심 구조: 매니페스트 + 세그먼트 ​

HLS는 크게 Master Playlist, Media Playlist, Segment 세 가지로 움직입니다. 구조도는 실제 글 발행 전에 이미지로 넣는 편이 낫습니다. 코드블럭으로 그려놓으면 모바일에서 금방 무너집니다.

Master Playlist, Media Playlist, Segment 구조

파일역할
Master Playlist사용 가능한 Variant Stream 목록. 해상도, 비트레이트, 코덱 정보
Media Playlist실제 미디어 세그먼트 URL 목록. 재생 순서대로 나열
Segment미디어 데이터 파일. 보통 .ts (MPEG-2 TS) 또는 .m4s (fMP4)

m3u8 주요 태그 ​

기본 태그 ​

태그설명
#EXTM3U파일 시작 식별자. 반드시 첫 줄
#EXT-X-VERSION:<n>프로토콜 버전. 현재 최신 7

Media Playlist 태그 ​

태그설명필수
#EXT-X-TARGETDURATION:<s>세그먼트 최대 길이 (초). 모든 세그먼트는 이 값을 초과할 수 없음✓
#EXTINF:<duration>,[title]다음 세그먼트의 길이. 소수점 포함 가능 (v3+)✓
#EXT-X-MEDIA-SEQUENCE:<n>첫 세그먼트의 시퀀스 번호. 라이브에서 증가
#EXT-X-DISCONTINUITY-SEQUENCE:<n>Discontinuity 카운터. 동기화에 사용
#EXT-X-ENDLIST더 이상 세그먼트가 추가되지 않음 (VOD 표시)
#EXT-X-PLAYLIST-TYPE:EVENT세그먼트 삭제 없이 뒤에만 추가. DVR에 활용
#EXT-X-PLAYLIST-TYPE:VOD완결된 재생목록. 변경 없음

Master Playlist 태그 ​

태그설명
#EXT-X-STREAM-INFVariant Stream 정의. BANDWIDTH, RESOLUTION, CODECS 등 포함
#EXT-X-MEDIA대체 렌디션 (오디오 언어, 자막 등) 정의
#EXT-X-I-FRAME-STREAM-INFI-Frame 전용 스트림. 트릭 플레이(빨리감기) 용도
#EXT-X-SESSION-DATA세션 레벨 메타데이터 전달
#EXT-X-SESSION-KEYMaster Playlist에서 암호화 키 선언

세그먼트 관련 태그 ​

태그설명
#EXT-X-KEY암호화 방식 (AES-128, SAMPLE-AES) 및 키 URL
#EXT-X-MAP초기화 세그먼트 (fMP4의 init segment)
#EXT-X-BYTERANGE하나의 파일에서 바이트 범위로 세그먼트 분리
#EXT-X-DISCONTINUITY인코딩 불연속점 (코덱, 해상도, 타임스탬프 변경)
#EXT-X-PROGRAM-DATE-TIME세그먼트와 절대 시각 매핑 (ISO 8601)
#EXT-X-DATERANGE시간 범위 기반 메타데이터. SCTE-35 광고 신호 전달에 사용

실제 예시 ​

Master Playlist ​

m3u8
#EXTM3U
#EXT-X-VERSION:7
#EXT-X-INDEPENDENT-SEGMENTS

#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="audio",NAME="Korean",LANGUAGE="ko",DEFAULT=YES,URI="audio_ko.m3u8"
#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="audio",NAME="English",LANGUAGE="en",DEFAULT=NO,URI="audio_en.m3u8"

#EXT-X-STREAM-INF:BANDWIDTH=5000000,RESOLUTION=1920x1080,CODECS="avc1.640028,mp4a.40.2",AUDIO="audio"
1080p.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=2500000,RESOLUTION=1280x720,CODECS="avc1.64001f,mp4a.40.2",AUDIO="audio"
720p.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=1000000,RESOLUTION=854x480,CODECS="avc1.4d401e,mp4a.40.2",AUDIO="audio"
480p.m3u8

Media Playlist (라이브) ​

m3u8
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:6
#EXT-X-MEDIA-SEQUENCE:1024

#EXTINF:6.006,
https://cdn.example.com/live/seg_1024.ts
#EXTINF:6.006,
https://cdn.example.com/live/seg_1025.ts
#EXTINF:6.006,
https://cdn.example.com/live/seg_1026.ts

#EXT-X-ENDLIST가 없으면 라이브입니다. 클라이언트는 이 매니페스트를 주기적으로 다시 가져와서 새 세그먼트를 확인합니다.


라이브 동작 메커니즘 ​

매니페스트 갱신 주기 ​

클라이언트는 Media Playlist를 주기적으로 폴링해서 새 세그먼트를 확인합니다.

  • 갱신 간격: Target Duration의 0.5~1배 (RFC 권장)
  • 서버는 이전 버전 게시 후 1.5 × Target Duration 이내에 새 버전을 반드시 올려야 함
  • #EXT-X-ENDLIST가 없는 한 클라이언트는 계속 폴링

슬라이딩 윈도우 ​

라이브에서 Media Playlist는 무한히 길어지지 않습니다. 오래된 세그먼트는 앞에서부터 제거되고 EXT-X-MEDIA-SEQUENCE가 증가합니다.

시점 T:   seq 1024, 1025, 1026
시점 T+6s: seq 1025, 1026, 1027  ← 1024 제거, 1027 추가
시점 T+12s: seq 1026, 1027, 1028

RFC 규정: #EXT-X-ENDLIST 없는 라이브 플레이리스트의 총 duration은 3 × Target Duration 이상을 유지해야 합니다.


지연 시간 분석 ​

HLS의 지연 시간은 구조적으로 발생합니다:

지연 = 인코딩 지연 + 세그먼트 길이 + 매니페스트 갱신 간격 + CDN 전파 + 클라이언트 버퍼

일반적인 지연 구성 (6초 세그먼트 기준) ​

구간지연
인코딩 + 세그먼트 생성~6초 (1 세그먼트 길이)
매니페스트 갱신 대기~3초 (0.5 × Target Duration)
CDN 전파~1초
클라이언트 버퍼 (3 세그먼트)~18초
총 지연약 20~30초

실무에서 HLS 기본 지연은 10~30초 범위입니다. 세그먼트 길이를 줄이면 지연이 줄지만, 그만큼 매니페스트 갱신 빈도와 HTTP 요청 수가 늘어납니다.

지연을 줄이는 방법 ​

방법효과트레이드오프
세그먼트 길이 축소 (6s → 2s)지연 ~50% 감소HTTP 오버헤드 증가, CDN 부하 증가
EXT-X-PLAYLIST-TYPE:EVENT + 작은 윈도우DVR 유지하면서 작은 윈도우매니페스트 크기 증가
LL-HLS (Low-Latency HLS)지연 2~4초별도 규격 필요 (다른 글에서 상세 설명)

일반 HLS로는 10초 벽을 깨기 어렵습니다. 구조적 한계입니다 — 세그먼트가 "완성"되어야 클라이언트가 받을 수 있으니까요. 이 한계를 깬 게 LL-HLS이고, 다른 글에서 더 자세히 작성했습니다.


세그먼트 포맷 ​

HLS는 두 가지 컨테이너를 지원합니다:

포맷파일 확장자특징
MPEG-2 TS.ts전통 방식. 세그먼트마다 PAT/PMT 포함. 단독 디코딩 가능
Fragmented MP4.m4s + init.mp4CMAF 호환. 초기화 세그먼트 + 미디어 세그먼트 분리. 저장 효율 좋음

fMP4(CMAF)를 쓰면 HLS와 DASH가 같은 세그먼트 파일을 공유할 수 있습니다. 하나의 인코딩으로 두 프로토콜을 동시에 서빙하는 구조가 가능해집니다.


암호화와 DRM ​

HLS는 세그먼트 레벨 암호화를 지원합니다:

방식설명
AES-128전체 세그먼트를 AES-128-CBC로 암호화. 키 URL에서 키 다운로드
SAMPLE-AES미디어 샘플 단위 암호화. FairPlay DRM에 사용

Apple FairPlay DRM은 HLS + SAMPLE-AES 조합으로 동작합니다. #EXT-X-KEY 태그에 KEYFORMAT="com.apple.streamingkeydelivery" 형태로 선언합니다.


프로토콜 버전 히스토리 ​

버전추가된 기능
1기본 HLS
2IV 속성 지원
3부동소수점 EXTINF duration
4EXT-X-BYTERANGE, I-Frames-Only
5KEYFORMAT, EXT-X-MAP (I-Frame 전용)
6EXT-X-MAP (일반 사용)
7EXT-X-SESSION-DATA, EXT-X-SESSION-KEY

현재 대부분의 서비스는 v3~v7을 사용합니다.


마치며 ​

HLS의 핵심을 한 문장으로: "미디어를 HTTP 위의 파일 목록으로 추상화한 것."

이 단순함이 HLS를 지배적 프로토콜로 만들었습니다. 웹서버가 파일을 서빙할 수 있으면 스트리밍이 되고, CDN이 파일을 캐시할 수 있으면 확장이 됩니다. 별도의 스트리밍 프로토콜 서버가 필요 없습니다.

대신 구조적으로 지연이 발생하는 건 감수해야 합니다. 세그먼트가 완성되어야 서빙할 수 있고, 클라이언트가 매니페스트를 폴링해야 새 세그먼트를 알 수 있으니까요. 이 문제를 해결하기 위해 LL-HLS가 나왔고, 지연 시간을 2초대까지 끌어내리는 데 성공했습니다.

Apple이 사실상 "HLS 아니면 iOS에서 재생 안 됨"을 관철시킨 것이 HLS 지배의 진짜 이유입니다. 기술적 우월성보다 생태계 락인이 표준을 만든 케이스입니다.

참고 자료 ​

基于 VitePress 构建 · 部署于腾讯云 EdgeOne Pages