영상 스트리밍 프로토콜 완벽 가이드 | RTMP·RTSP·HLS·DASH·CMAF 비교

영상 스트리밍 프로토콜 완벽 가이드 | RTMP·RTSP·HLS·DASH·CMAF 비교

이 글의 핵심

영상 스트리밍 프로토콜 완벽 가이드. RTMP, RTSP, HLS, DASH, CMAF, WebRTC 등 주요 프로토콜의 원리와 실전 활용법을 비교합니다.

들어가며

영상 스트리밍 프로토콜영상을 인터넷으로 전송하는 방법을 정의합니다. YouTube, Netflix, Twitch 등 모든 스트리밍 서비스는 이런 프로토콜을 사용합니다.

비유로 말씀드리면, 프로토콜택배 배송 방식입니다. RTMP빠른 퀵서비스, HLS안정적인 일반 택배, WebRTC즉시 배달입니다.

이 글을 읽으면

  • 주요 스트리밍 프로토콜의 원리를 이해합니다
  • 각 프로토콜의 장단점을 파악합니다
  • 상황별 최적의 프로토콜을 선택할 수 있습니다
  • 실전 구현 방법을 익힙니다

목차

  1. 스트리밍 프로토콜 기초
  2. RTMP
  3. RTSP
  4. HLS
  5. DASH
  6. CMAF
  7. WebRTC
  8. 프로토콜 비교
  9. 실전 구현
  10. 트러블슈팅
  11. 마무리

스트리밍 프로토콜 기초

스트리밍이란?

스트리밍은 영상을 다운로드하면서 동시에 재생하는 기술입니다.

다운로드:
[========================================] 100%
다운로드 완료 후 재생

스트리밍:
[=====>                                  ] 10%
다운로드 중인데 이미 재생 시작!

스트리밍의 2가지 방식

1. 라이브 스트리밍 (Live Streaming)

  • 실시간 방송 (Twitch, YouTube Live)
  • 낮은 지연시간 중요
  • 예: 스포츠 중계, 게임 방송

2. VOD (Video on Demand)

  • 녹화된 영상 (Netflix, YouTube)
  • 안정성과 품질 중요
  • 예: 영화, 드라마

프로토콜 선택 기준

기준설명
지연시간실시간성 (1초 vs 30초)
확장성동시 시청자 수 (100명 vs 100만명)
호환성브라우저/기기 지원
비용서버/CDN 비용
품질화질, 적응형 스트리밍

RTMP (Real-Time Messaging Protocol)

RTMP란?

RTMP는 Adobe가 개발한 실시간 영상 전송 프로토콜입니다. 라이브 스트리밍 인제스트(업로드)의 사실상 표준입니다.

특징:

  • TCP 기반 (안정적)
  • 낮은 지연시간 (1-5초)
  • Flash 기반 (브라우저 지원 종료)

RTMP 워크플로우

[스트리머] → RTMP → [서버] → HLS/DASH → [시청자]
   (OBS)              (Nginx)             (브라우저)

1. 스트리머: OBS로 RTMP 송출
2. 서버: RTMP 수신 → HLS/DASH 변환
3. 시청자: HLS/DASH로 시청

RTMP 구현 (Nginx)

nginx.conf:

rtmp {
    server {
        listen 1935;  # RTMP 포트
        
        application live {
            live on;  # 라이브 스트리밍 활성화
            
            # HLS 변환
            hls on;
            hls_path /tmp/hls;
            hls_fragment 3s;  # 세그먼트 길이
            hls_playlist_length 60s;
            
            # DASH 변환
            dash on;
            dash_path /tmp/dash;
            dash_fragment 3s;
        }
    }
}

http {
    server {
        listen 8080;
        
        # HLS 제공
        location /hls {
            types {
                application/vnd.apple.mpegurl m3u8;
                video/mp2t ts;
            }
            root /tmp;
            add_header Cache-Control no-cache;
            add_header Access-Control-Allow-Origin *;
        }
        
        # DASH 제공
        location /dash {
            types {
                application/dash+xml mpd;
            }
            root /tmp;
            add_header Cache-Control no-cache;
            add_header Access-Control-Allow-Origin *;
        }
    }
}

OBS 설정:

서버: rtmp://your-server.com/live
스트림 키: stream-key-123

RTMP 장단점

장점:

  • ✅ 낮은 지연시간 (1-5초)
  • ✅ 안정적인 전송 (TCP)
  • ✅ 업계 표준 (모든 인코더 지원)

단점:

  • ❌ 브라우저 직접 재생 불가 (Flash 종료)
  • ❌ 방화벽 문제 (1935 포트)
  • ❌ 확장성 제한

RTSP (Real Time Streaming Protocol)

RTSP란?

RTSPIP 카메라와 CCTV에서 주로 사용하는 프로토콜입니다.

특징:

  • UDP/TCP 지원
  • 양방향 제어 (재생, 일시정지, 탐색)
  • RTP/RTCP로 실제 데이터 전송

RTSP 구조

RTSP (제어 채널)

RTP (미디어 전송)

RTCP (품질 피드백)

RTSP URL 형식

rtsp://username:[email protected]:554/stream1

rtsp://     - 프로토콜
username    - 인증 사용자명
password    - 인증 비밀번호
192.168.1.100 - IP 주소
554         - 포트 (기본값)
/stream1    - 스트림 경로

RTSP 재생 (FFmpeg)

# RTSP 스트림 재생
ffplay rtsp://192.168.1.100:554/stream1

# RTSP → RTMP 변환
ffmpeg -i rtsp://192.168.1.100:554/stream1 \
       -c copy \
       -f flv rtmp://your-server.com/live/stream

# RTSP → HLS 변환
ffmpeg -i rtsp://192.168.1.100:554/stream1 \
       -c:v libx264 -c:a aac \
       -f hls -hls_time 3 -hls_list_size 10 \
       output.m3u8

RTSP 장단점

장점:

  • ✅ 낮은 지연시간
  • ✅ 양방향 제어
  • ✅ IP 카메라 표준

단점:

  • ❌ 브라우저 지원 없음
  • ❌ 방화벽 문제 (UDP)
  • ❌ 확장성 제한

HLS (HTTP Live Streaming)

HLS란?

HLS는 Apple이 개발한 HTTP 기반 스트리밍 프로토콜입니다. 가장 널리 사용되는 프로토콜입니다.

특징:

  • HTTP 기반 (CDN 활용 가능)
  • 적응형 비트레이트 (ABR)
  • 모든 Apple 기기 지원

HLS 구조

영상 → 세그먼트로 분할 → Playlist 생성

video.mp4

segment0.ts (6초)
segment1.ts (6초)
segment2.ts (6초)

playlist.m3u8 (세그먼트 목록)

HLS Playlist (M3U8)

Master Playlist (다중 화질):

#EXTM3U
#EXT-X-VERSION:3

# 1080p
#EXT-X-STREAM-INF:BANDWIDTH=5000000,RESOLUTION=1920x1080
1080p.m3u8

# 720p
#EXT-X-STREAM-INF:BANDWIDTH=2500000,RESOLUTION=1280x720
720p.m3u8

# 480p
#EXT-X-STREAM-INF:BANDWIDTH=1000000,RESOLUTION=854x480
480p.m3u8

Media Playlist (세그먼트 목록):

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

#EXTINF:6.0,
segment0.ts
#EXTINF:6.0,
segment1.ts
#EXTINF:6.0,
segment2.ts
#EXT-X-ENDLIST

HLS 생성 (FFmpeg)

# 단일 화질 HLS
ffmpeg -i input.mp4 \
       -c:v libx264 -c:a aac \
       -f hls \
       -hls_time 6 \
       -hls_list_size 0 \
       -hls_segment_filename 'segment%03d.ts' \
       playlist.m3u8

# 다중 화질 HLS (ABR)
ffmpeg -i input.mp4 \
  -filter_complex \
  "[0:v]split=3[v1][v2][v3]; \
   [v1]scale=w=1920:h=1080[v1out]; \
   [v2]scale=w=1280:h=720[v2out]; \
   [v3]scale=w=854:h=480[v3out]" \
  -map "[v1out]" -c:v:0 libx264 -b:v:0 5M \
  -map "[v2out]" -c:v:1 libx264 -b:v:1 2.5M \
  -map "[v3out]" -c:v:2 libx264 -b:v:2 1M \
  -map a:0 -c:a aac -b:a 128k \
  -f hls -hls_time 6 \
  -hls_playlist_type vod \
  -master_pl_name master.m3u8 \
  -var_stream_map "v:0,a:0 v:1,a:0 v:2,a:0" \
  stream_%v/playlist.m3u8

HLS 재생 (JavaScript)

<!DOCTYPE html>
<html>
<head>
    <script src="https://cdn.jsdelivr.net/npm/hls.js@latest"></script>
</head>
<body>
    <video id="video" controls width="640"></video>
    
    <script>
        const video = document.getElementById('video');
        const videoSrc = 'https://example.com/master.m3u8';
        
        if (video.canPlayType('application/vnd.apple.mpegurl')) {
            // Safari (네이티브 HLS 지원)
            video.src = videoSrc;
        } else if (Hls.isSupported()) {
            // 다른 브라우저 (hls.js 사용)
            const hls = new Hls();
            hls.loadSource(videoSrc);
            hls.attachMedia(video);
            
            hls.on(Hls.Events.MANIFEST_PARSED, () => {
                video.play();
            });
        }
    </script>
</body>
</html>

HLS 장단점

장점:

  • ✅ HTTP 기반 (CDN 활용)
  • ✅ 방화벽 문제 없음
  • ✅ 적응형 비트레이트 (ABR)
  • ✅ Apple 기기 네이티브 지원
  • ✅ 무한 확장성

단점:

  • ❌ 높은 지연시간 (6-30초)
  • ❌ 세그먼트 파일 많음

DASH (Dynamic Adaptive Streaming over HTTP)

DASH란?

DASHMPEG 표준 스트리밍 프로토콜입니다. HLS의 오픈 표준 대안입니다.

특징:

  • HTTP 기반
  • 코덱 독립적 (H.264, H.265, VP9, AV1)
  • DRM 지원 우수

DASH 구조

영상 → 세그먼트 분할 → MPD 생성

video.mp4

init.mp4 (초기화 세그먼트)
segment1.m4s
segment2.m4s
segment3.m4s

manifest.mpd (세그먼트 목록)

DASH Manifest (MPD)

<?xml version="1.0"?>
<MPD xmlns="urn:mpeg:dash:schema:mpd:2011">
  <Period>
    <!-- 비디오 -->
    <AdaptationSet mimeType="video/mp4" codecs="avc1.4d401f">
      <!-- 1080p -->
      <Representation id="1" bandwidth="5000000" width="1920" height="1080">
        <SegmentTemplate timescale="1000" 
                         initialization="init-$RepresentationID$.mp4"
                         media="segment-$RepresentationID$-$Number$.m4s"
                         startNumber="1">
          <SegmentTimeline>
            <S t="0" d="6000" r="9"/>
          </SegmentTimeline>
        </SegmentTemplate>
      </Representation>
      
      <!-- 720p -->
      <Representation id="2" bandwidth="2500000" width="1280" height="720">
        <!-- ... -->
      </Representation>
    </AdaptationSet>
    
    <!-- 오디오 -->
    <AdaptationSet mimeType="audio/mp4" codecs="mp4a.40.2">
      <Representation id="audio" bandwidth="128000">
        <!-- ... -->
      </Representation>
    </AdaptationSet>
  </Period>
</MPD>

DASH 생성 (FFmpeg + MP4Box)

# 1. 다중 화질 인코딩
ffmpeg -i input.mp4 \
  -c:v libx264 -b:v 5M -s 1920x1080 -profile:v high -level 4.1 1080p.mp4 \
  -c:v libx264 -b:v 2.5M -s 1280x720 -profile:v high -level 4.0 720p.mp4 \
  -c:v libx264 -b:v 1M -s 854x480 -profile:v main -level 3.1 480p.mp4

# 2. DASH 패키징 (MP4Box)
MP4Box -dash 6000 -frag 6000 -rap \
       -segment-name 'segment_$RepresentationID$_' \
       -out manifest.mpd \
       1080p.mp4 720p.mp4 480p.mp4

DASH 재생 (dash.js)

<!DOCTYPE html>
<html>
<head>
    <script src="https://cdn.dashjs.org/latest/dash.all.min.js"></script>
</head>
<body>
    <video id="video" controls width="640"></video>
    
    <script>
        const url = 'https://example.com/manifest.mpd';
        const player = dashjs.MediaPlayer().create();
        player.initialize(document.getElementById('video'), url, true);
    </script>
</body>
</html>

DASH 장단점

장점:

  • ✅ 오픈 표준 (로열티 없음)
  • ✅ 코덱 독립적
  • ✅ DRM 지원 우수
  • ✅ HTTP 기반

단점:

  • ❌ Apple 기기 지원 약함
  • ❌ 복잡한 구현

CMAF (Common Media Application Format)

CMAF란?

CMAFHLS와 DASH를 통합하는 차세대 포맷입니다. 하나의 파일로 두 프로토콜 지원이 가능합니다.

특징:

  • fMP4 기반
  • HLS + DASH 동시 지원
  • 낮은 지연시간 (LL-HLS, LL-DASH)

CMAF 구조

기존:
HLS용 파일 (TS)  +  DASH용 파일 (MP4)
→ 2배 저장 공간, 2배 인코딩 시간

CMAF:
공통 파일 (fMP4)
→ HLS와 DASH 모두 사용
→ 1배 저장 공간, 1배 인코딩 시간

CMAF 생성 (FFmpeg)

# CMAF 인코딩
ffmpeg -i input.mp4 \
  -c:v libx264 -b:v 5M -s 1920x1080 -profile:v high \
  -c:a aac -b:a 128k \
  -f hls \
  -hls_segment_type fmp4 \
  -hls_fmp4_init_filename init.mp4 \
  -hls_segment_filename 'segment%03d.m4s' \
  -hls_playlist_type vod \
  playlist.m3u8

LL-HLS (Low-Latency HLS)

특징:

  • 지연시간: 2-3초 (기존 HLS의 1/10)
  • 부분 세그먼트 (Partial Segment)
  • HTTP/2 Server Push
#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.5

#EXT-X-PART:DURATION=0.5,URI="part0.m4s"
#EXT-X-PART:DURATION=0.5,URI="part1.m4s"
#EXTINF:6.0,
segment0.m4s

CMAF 장단점

장점:

  • ✅ HLS + DASH 동시 지원
  • ✅ 저장 공간 절약 (50%)
  • ✅ 낮은 지연시간 (LL-HLS)
  • ✅ 미래 지향적

단점:

  • ❌ 최신 기술 (지원 제한적)
  • ❌ 복잡한 구현

WebRTC (Web Real-Time Communication)

WebRTC란?

WebRTCP2P 실시간 통신 프로토콜입니다. 초저지연이 특징입니다.

특징:

  • UDP 기반
  • 지연시간: 0.5-1초
  • 브라우저 네이티브 지원

WebRTC 구조

[발신자] ←→ Signaling Server ←→ [수신자]
    ↓                              ↓
    └──────── P2P 연결 ────────────┘
           (STUN/TURN)

WebRTC 구현 (JavaScript)

발신자:

// 1. MediaStream 획득
const stream = await navigator.mediaDevices.getUserMedia({
    video: true,
    audio: true
});

// 2. RTCPeerConnection 생성
const pc = new RTCPeerConnection({
    iceServers: [
        { urls: 'stun:stun.l.google.com:19302' }
    ]
});

// 3. 스트림 추가
stream.getTracks().forEach(track => {
    pc.addTrack(track, stream);
});

// 4. Offer 생성
const offer = await pc.createOffer();
await pc.setLocalDescription(offer);

// 5. Offer 전송 (Signaling Server)
sendToSignalingServer({ type: 'offer', sdp: offer.sdp });

수신자:

// 1. RTCPeerConnection 생성
const pc = new RTCPeerConnection({
    iceServers: [
        { urls: 'stun:stun.l.google.com:19302' }
    ]
});

// 2. Offer 수신
pc.setRemoteDescription(new RTCSessionDescription(offer));

// 3. Answer 생성
const answer = await pc.createAnswer();
await pc.setLocalDescription(answer);

// 4. Answer 전송
sendToSignalingServer({ type: 'answer', sdp: answer.sdp });

// 5. 스트림 수신
pc.ontrack = (event) => {
    videoElement.srcObject = event.streams[0];
};

WebRTC 장단점

장점:

  • ✅ 초저지연 (0.5-1초)
  • ✅ P2P (서버 부하 적음)
  • ✅ 브라우저 네이티브 지원

단점:

  • ❌ 확장성 제한 (P2P)
  • ❌ 방화벽/NAT 문제
  • ❌ 녹화 어려움

프로토콜 비교

전체 비교표

프로토콜지연시간확장성브라우저 지원주요 용도
RTMP1-5초중간라이브 인제스트
RTSP1-3초낮음IP 카메라
HLS6-30초높음VOD, 라이브
DASH6-30초높음VOD, 라이브
CMAF2-6초높음차세대 스트리밍
WebRTC0.5-1초낮음화상 통화

상황별 추천

1. 라이브 스트리밍 (대규모)

RTMP (인제스트) → HLS/DASH (배포)
지연시간: 10-30초
확장성: 무제한

2. 라이브 스트리밍 (저지연)

RTMP → LL-HLS 또는 WebRTC
지연시간: 1-3초
확장성: 중간

3. VOD (주문형 비디오)

HLS (Apple) + DASH (Android)
또는 CMAF (통합)

4. 화상 통화

WebRTC
지연시간: 1초 미만

5. IP 카메라

RTSP → RTMP/HLS 변환

실전 구현

완전한 라이브 스트리밍 시스템

아키텍처:

[스트리머] → RTMP → [Nginx-RTMP] → HLS/DASH → [CDN] → [시청자]
   (OBS)              (서버)                    (CloudFlare)  (브라우저)

Docker Compose:

version: '3'
services:
  nginx-rtmp:
    image: tiangolo/nginx-rtmp
    ports:
      - "1935:1935"  # RTMP
      - "8080:80"    # HLS/DASH
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf
      - ./hls:/tmp/hls
      - ./dash:/tmp/dash

nginx.conf (완전판):

rtmp {
    server {
        listen 1935;
        chunk_size 4096;
        
        application live {
            live on;
            record off;
            
            # 인증 (선택)
            on_publish http://localhost:8000/auth;
            
            # HLS
            hls on;
            hls_path /tmp/hls;
            hls_fragment 3s;
            hls_playlist_length 60s;
            hls_continuous on;
            hls_cleanup on;
            hls_nested on;
            
            # DASH
            dash on;
            dash_path /tmp/dash;
            dash_fragment 3s;
            dash_playlist_length 60s;
            dash_cleanup on;
            dash_nested on;
            
            # 트랜스코딩 (다중 화질)
            exec ffmpeg -i rtmp://localhost/live/$name
              -c:v libx264 -b:v 5M -s 1920x1080 -f flv rtmp://localhost/hls/$name_1080p
              -c:v libx264 -b:v 2.5M -s 1280x720 -f flv rtmp://localhost/hls/$name_720p
              -c:v libx264 -b:v 1M -s 854x480 -f flv rtmp://localhost/hls/$name_480p;
        }
    }
}

트러블슈팅

1. HLS 지연시간 줄이기

문제: HLS 지연시간이 30초 이상

해결:

# 세그먼트 길이 단축
hls_fragment 2s;  # 6s → 2s

# Playlist 길이 단축
hls_playlist_length 10s;  # 60s → 10s

# 결과: 지연시간 30초 → 6-10초

2. CORS 에러

문제: 브라우저에서 HLS 재생 안됨

해결:

location /hls {
    add_header Access-Control-Allow-Origin *;
    add_header Access-Control-Allow-Methods "GET, OPTIONS";
    add_header Access-Control-Allow-Headers "Range";
}

3. 버퍼링 문제

문제: 영상이 자주 멈춤

해결:

// hls.js 버퍼 설정
const hls = new Hls({
    maxBufferLength: 30,      // 최대 버퍼 (초)
    maxMaxBufferLength: 600,  // 최대 최대 버퍼
    maxBufferSize: 60 * 1000 * 1000,  // 60MB
    maxBufferHole: 0.5        // 버퍼 홀 허용
});

마무리

영상 스트리밍 프로토콜상황에 맞게 선택해야 합니다.

핵심 요약:

프로토콜한 줄 요약
RTMP라이브 업로드 표준
RTSPIP 카메라 표준
HLS가장 범용적
DASH오픈 표준 대안
CMAF차세대 통합 포맷
WebRTC초저지연 P2P

실전 추천:

라이브 스트리밍:
RTMP (인제스트) → HLS (배포)

VOD:
HLS (Apple) + DASH (Android)
또는 CMAF (통합)

저지연 라이브:
WebRTC 또는 LL-HLS

IP 카메라:
RTSP → HLS 변환

다음 단계:

  • H.264 코덱 가이드
  • WebM 컨테이너 포맷
  • Opus 오디오 코덱

영상 스트리밍의 세계에 오신 것을 환영합니다! 🎥