스트림 서버 구축하기: 업로드는 한 번, 시청자는 얼마든지

게시일 읽는 시간 17분

서버로는 스트림을 하나만 보내고, 그 스트림으로 서버가 모든 시청자를 담당합니다. 그래서 내 회선이 짊어지는 업로드는 시청자가 열 명이든 천 명이든 언제나 하나뿐입니다. 이 가이드에서는 구축 방법과 프로토콜, 그 뒤에 있는 대역폭 계산을 함께 살펴봅니다.

자체 서버 없이 스트리밍하면 내 화면을 시청자마다 따로 보내게 됩니다. 시청자가 열 명이면 같은 데이터를 열 번, 백 명이면 백 번 보냅니다. 그래서 집이나 사무실의 업로드는 시청자가 몇 명 되지 않아도 금방 꽉 차고, 컴퓨터는 한가한데도 화면이 끊기기 시작합니다.

스트림 서버는 이 구조를 뒤집습니다. 서버로는 스트림을 딱 하나만 보내고, 그 스트림으로 서버가 모든 시청자를 담당합니다. 그래서 내 회선이 짊어지는 업로드는 열 명이 보든 만 명이 보든 언제나 하나뿐입니다. 이 글에서는 이 방식이 왜 그렇게 잘 통하는지, 그런 서버를 어떻게 구축하는지, 프로토콜마다 지연이 얼마나 생기는지, 그리고 트래픽이 실제로 얼마나 쌓이는지 살펴봅니다.

문제: 병목은 내 업로드입니다

영상은 끊이지 않고 흐르는 데이터입니다. 초당 60프레임의 1080p 스트림은 내용에 따라 4.5~8 Mbit/s가 필요하고, 720p는 3~5 Mbit/s 정도입니다. 이 비트레이트가 시청자 한 명마다, 보는 동안 내내, 쉬지 않고 흐릅니다.

독일의 평균적인 가정용 회선은 업로드가 10~50 Mbit/s이고, 광케이블 회선조차 업로드는 50~100 Mbit/s인 경우가 많습니다. 그래서 계산은 금방 끝납니다.

시청자3 Mbit/s일 때6 Mbit/s일 때가정용 회선으로 되나요?
515 Mbit/s30 Mbit/s겨우
2060 Mbit/s120 Mbit/s아니요
100300 Mbit/s600 Mbit/s아니요
10003 Gbit/s6 Gbit/s아니요

여기에 자주 잊히는 두 번째 문제가 더해집니다. 내 회선은 집이나 사무실의 다른 모든 통신과 같은 선을 나눠 씁니다. 누군가 큰 파일을 올리거나 백업이 돌기 시작하면 스트림이 바로 무너집니다. 데이터센터의 서버에는 이 문제가 없습니다. 거기서는 회선이 오직 나만을 위해 놓여 있습니다.

원리: 한 번 올리고 여러 번 내려보내기

구성은 세 부분으로 이루어집니다.

  • 송출 측, 즉 OBS나 ffmpeg 또는 하드웨어 인코더가 스트림 하나를 서버로 보냅니다. 이것을 인제스트라고 합니다.
  • 서버는 이 스트림 하나를 받아 원하는 송출 형식으로 바꿔 두고 대기시킵니다.
  • 시청자는 서버에서 스트림을 받아 갑니다. 이것을 이그레스라고 하며, 시청자 수에 따라 커지는 부분이 바로 여기입니다.

결정적인 것은 비대칭입니다. 나에서 서버까지의 경로는 한 번 지나가고, 서버에서 시청자까지의 경로는 수천 번 지나갑니다. 그래서 내 회선에는 스트림 하나만큼의 업로드만 있으면 되고, 서버에는 시청자 수를 따라갈 수 있는 회선이 필요합니다.

트래픽이 실제로 얼마나 쌓이는지

대역폭은 계산의 절반일 뿐입니다. 더 중요한 것은 전송량입니다. 많은 사업자가 그 기준으로 요금을 매기기 때문입니다. 공식은 간단합니다.

전송량(GB) = 비트레이트(Mbit/s) × 시간(초) × 시청자 수 ÷ 8000

현실적인 예를 몇 가지 보겠습니다.

시나리오비트레이트시간시청자전송량
주 1회 강연3 Mbit/s2시간50135 GB
매일 하는 방송6 Mbit/s3시간200하루 1.6 TB
24시간 상시 채널4 Mbit/s24시간30하루 1.3 TB
일회성 대형 행사6 Mbit/s4시간200021.6 TB

마지막 열의 숫자가 바로 스트리밍과 전송량 기반 요금제가 잘 맞지 않는 이유입니다. 사람이 많이 모인 중계 한 번으로 한 달 기본 전송량을 다 써 버릴 수 있고, 그다음부터는 추가 테라바이트마다 요금이 따로 붙습니다. 무제한 트래픽 요금제에서는 이 계산이 아예 없어집니다. 회선으로 200 GB가 지나가든 50 TB가 지나가든 월 요금은 그대로입니다.

어떤 소프트웨어가 맞는지

소프트웨어강점어울리는 용도
nginx와 RTMP 모듈가볍고 안정적이며 RTMP와 HLS를 동시에 처리가장 전형적인 출발점, 플랫폼으로 전달
MediaMTX실행 파일 하나, SRT와 WebRTC 기본 제공손을 많이 대지 않고 낮은 지연
SRS기능이 매우 많고 클러스터 구성 가능노드 여러 개를 쓰는 큰 구성
Owncast웹 인터페이스와 채팅까지 갖춘 완성형직접 운영하는 작은 스트리밍 사이트

처음 시작할 때는 RTMP 모듈을 올린 nginx가 가장 자연스러운 선택입니다. 어디서나 구할 수 있고 문서도 잘 되어 있으며, 같은 서버를 나중에 손대지 않고 시청자 페이지용 웹서버로 함께 쓸 수 있습니다.

nginx와 RTMP로 스트림 서버 구축하기

설치하기

Debian과 Ubuntu에서는 libnginx-mod-rtmp 패키지가 모듈을 함께 제공하므로, 직접 컴파일할 것이 없습니다.

apt update
apt install -y nginx libnginx-mod-rtmp ffmpeg

AlmaLinux와 Rocky Linux에서는 모듈이 EPEL 저장소에서 옵니다.

dnf install -y epel-release
dnf install -y nginx nginx-mod-rtmp ffmpeg

설정하기

RTMP 부분은 nginx.conf의 http 블록 바깥에 둡니다. 가장 흔한 초보자 실수가 바로 이것입니다. 가볍게 쓰면서도 제대로 동작하는 설정은 다음과 같습니다.

rtmp {
    server {
        listen 1935;
        chunk_size 4096;

        application live {
            live on;
            record off;

            # 일반 시청자용 HLS
            hls on;
            hls_path /var/www/stream/hls;
            hls_fragment 2s;
            hls_playlist_length 12s;

            # 내 주소에서만 송출할 수 있게 한다
            allow publish 203.0.113.10;
            deny publish all;

            # 시청은 누구나 가능
            allow play all;
        }
    }
}

HLS 파일은 일반 웹서버가 내보냅니다. 그러려면 http 부분에 작은 블록 하나만 있으면 됩니다.

server {
    listen 80;
    server_name stream.example.com;

    location /hls {
        types {
            application/vnd.apple.mpegurl m3u8;
            video/mp2t ts;
        }
        root /var/www/stream;
        add_header Cache-Control no-cache;
        add_header Access-Control-Allow-Origin *;
    }
}

디렉터리를 만들고, 설정을 검사하고, 다시 불러옵니다.

mkdir -p /var/www/stream/hls
chown -R www-data:www-data /var/www/stream
nginx -t && systemctl reload nginx

포트 열기

RTMP는 1935 포트를 쓰고, 송출은 80과 443으로 나갑니다. nftables나 ufw에서는 이렇게 합니다.

ufw allow from 203.0.113.10 to any port 1935 proto tcp
ufw allow 80/tcp
ufw allow 443/tcp

첫 줄을 잘 보세요. 송출 포트는 내 주소에만 열려 있습니다. 전 세계에 열려 있는 RTMP 포트는 며칠 안에 발견됩니다. 주소 범위 전체가 자동으로 검색되기 때문이고, 그러면 다른 사람이 내 회선으로 송출하게 됩니다.

OBS로 송출하기

OBS의 설정, 방송 항목에서 서비스를 “사용자 지정”으로 지정합니다.

항목값
서버rtmp://stream.example.com/live
스트림 키직접 정한 이름, 예를 들어 kanal1

비트레이트는 출력 항목에서 설정합니다. 기준값은 1080p60에 6000 kbit/s, 1080p30에 4500 kbit/s, 720p30에 3000 kbit/s입니다. 키프레임 간격은 2초로 맞추세요. 그러지 않으면 HLS 세그먼트가 불규칙해지고, 플레이어가 전환할 때 끊깁니다.

시청하기

스트림은 그 뒤 https://stream.example.com/hls/kanal1.m3u8에 올라오고, HLS를 지원하는 플레이어로 열 수 있습니다. 브라우저에서는 hls.js나 Video.js를 쓰면 됩니다. 빨리 확인만 하려면 VLC의 “네트워크 스트림 열기”로도 충분합니다.

여러 플랫폼에 동시에 송출하기

이것이 자체 서버의 두 번째 큰 장점입니다. 업로드를 세 개 동시에 올려 회선을 터뜨리는 대신, 서버로 한 번만 보내고 배포는 서버가 맡습니다. 그러려면 application 블록에 목적지마다 한 줄씩 추가합니다.

application live {
    live on;
    record off;

    push rtmp://live.plattform-a.example/app/STREAM_KEY;
    push rtmp://live.plattform-b.example/app/STREAM_KEY;
}

그동안에도 내 업로드는 스트림 하나로 그대로입니다. 복제는 서버가 맡고, 서버에서 대역폭은 바로 그 일을 하기 위해 있는 것입니다.

지연: 어떤 프로토콜을 어디에

지연은 올리는 단계가 아니라 거의 전부 송출 단계에서 생깁니다. 많은 사람이 엉뚱한 곳을 들여다보기 때문에 이 점을 이해하는 것이 중요합니다.

송출 방식지연적합한 용도
HLS, 기본 설정20~30초강연, 예배, 베팅 없는 스포츠
세그먼트를 짧게 잡은 HLS6~10초가장 흔한 절충안
Low-Latency HLS2~5초채팅이 있는 스트림
SRT1초 미만지점 간 중계 전송
WebRTC0.5초 미만대화, 경매, 원격 제어

지연이 낮아질수록 시청자 한 명에 드는 비용은 올라갑니다. HLS는 모든 웹서버와 모든 캐시가 내보낼 수 있는 단순한 파일로 이루어져 있어 가장 저렴합니다. 반면 WebRTC는 시청자마다 연결을 따로 열어 두므로 연산 부담이 훨씬 큽니다. 낮은 지연은 정말 필요한 곳에만 쓰세요.

트랜스코딩: 언제 값을 하는지

서버가 스트림을 그대로 넘기기만 하는 동안에는 연산이 거의 필요하지 않습니다. 최신 코어 하나로 이런 방식으로 시청자 수백 명을 감당하며, 병목은 오직 회선입니다.

연결이 약한 시청자도 볼 수 있도록 화질 단계를 여럿 제공하려 하면 사정이 달라집니다. 단계가 하나 늘어날 때마다 계산이 필요합니다.

ffmpeg -i rtmp://127.0.0.1/live/kanal1 \
  -c:v libx264 -preset veryfast -b:v 3000k -s 1280x720 -c:a copy -f flv rtmp://127.0.0.1/live/kanal1_720 \
  -c:v libx264 -preset veryfast -b:v 1200k -s 854x480  -c:a copy -f flv rtmp://127.0.0.1/live/kanal1_480

단계마다 코어 두 개에서 네 개를 잡으세요. 그러면 세 단계만으로 벌써 코어 여덟 개에서 열두 개가 상시로 묶입니다. 그래서 정말 필요한지 잘 따져 보세요. 대부분 컴퓨터나 무선 랜으로 보는 시청자라면 잘 고른 한 단계로 충분한 경우가 많습니다.

보안: 누가 송출할 수 있는지

스트림 서버는 밖에서 보이고, 결국 발견됩니다. 평소 운영에는 세 가지 조치로 충분합니다.

  • 송출 포트에 방화벽. 1935 포트에는 내 주소만 들어올 수 있게 합니다. 주소가 바뀌는 환경이라면 대신 서버로 들어오는 VPN 접속을 쓰세요.
  • 스트림 키 검사. on_publish를 쓰면 nginx가 송출 시도마다 작은 스크립트를 호출해 키를 목록과 비교하고, 맞지 않으면 거부합니다.
  • 과부하에 대한 기본 방어. 스트림 서버는 장애가 즉시 눈에 보이기 때문에 노려 볼 만한 표적이 됩니다. KernelHost에서는 3.2 Tbps 용량의 플러드 방어가 모든 서버 앞에 놓여 있어 따로 설정할 것이 없습니다. 자세한 내용은 DDoS 방어 페이지에 있습니다.

위치 선택과 서버 여러 대

서버는 내 근처가 아니라 시청자 근처에 있어야 합니다. 서버로 가는 내 연결은 한 번 맺어지면 대륙 절반을 건너서도 안정적으로 유지됩니다. 반면 시청자와의 연결은 로딩 시간과 이탈률을 좌우합니다.

시청자가 대부분 유럽에 있다면 독일 위치가 맞습니다. 여러 대륙에 흩어져 있다면 두 번째 서버를 두고 DNS로 분산해, 시청자마다 가장 가까운 서버로 가게 하는 편이 유리합니다. KernelHost는 이를 위해 독일, 미국 서부, 미국 동부, 싱가포르, 한국에 위치를 제공하며, 전체 목록은 서버 위치에서 볼 수 있습니다.

실시간 화면이 아니라 파일, 즉 업데이트나 이미지, 영상 보관함을 배포한다면 맞는 도구는 스트림 서버가 아니라 그 앞에 두는 캐시입니다. 그 방식은 자체 CDN 서버 구축하기 글에 있습니다.

어떤 서버가 맞는지

스트림 서버에서는 웹서버와 중요도 순서가 다릅니다.

  1. 회선과 트래픽. 병목은 여기이고, 언제나 그렇습니다. 속도 조절 없는 진짜 기가비트 회선은 6 Mbit/s 기준으로 시청자 약 160명을 감당합니다.
  2. 무제한 트래픽. 성공한 저녁 한 번이 한 달 전송량을 다 써 버리기 때문에, 전송량 기반 요금제는 스트리밍에서 거의 계산이 서지 않습니다.
  3. CPU. 트랜스코딩을 하지 않는 동안은 뒷순위입니다. 트랜스코딩을 시작하면 두 번째 병목이 됩니다.
  4. 메모리와 디스크. 가장 덜 중요합니다. 녹화를 보관하기 시작할 때에야 디스크 용량이 문제가 됩니다.

바로 이런 경우에 맞춰 만든 것이 KernelHost의 무제한 트래픽 루트 서버입니다. 서버마다 진짜 2 × 1 Gbit/s 회선, 속도 조절 없는 무제한 전송량, 전송한 양과 무관한 고정 월 요금, 그리고 기본으로 제공되는 3.2 Tbps 플러드 방어가 들어 있습니다. 서버는 30초 안에 준비되며, 전체 루트 권한과 IPv4 주소, /64 IPv6 네트워크가 함께 제공됩니다. 요금은 PrePaid 방식으로 청구되고 월 단위로 해지할 수 있으니, 작은 요금제로 시작해 시청자가 늘어나면 함께 키우면 됩니다.

자주 묻는 질문

스트림 서버가 왜 필요한가요?
서버가 없으면 내 컴퓨터가 시청자마다 스트림을 따로 보냅니다. 시청자 열 명에 6 Mbit/s이면 업로드가 60 Mbit/s, 백 명이면 벌써 600 Mbit/s입니다. 일반적인 가정용 회선의 업로드는 10~50 Mbit/s 정도입니다. 스트림 서버를 쓰면 송출은 딱 한 번만 하고, 배포는 서버가 맡습니다.
서버에는 대역폭이 얼마나 필요한가요?
비트레이트에 동시 시청자 수를 곱하면 됩니다. 6 Mbit/s로 시청자 500명이면 3 Gbit/s입니다. 다만 순간 최대치보다 중요한 것은 월 전송량입니다. 같은 시청자 500명이 두 시간을 보면 약 2.7 TB가 나옵니다. 그래서 스트리밍에서 결정적인 조건은 CPU가 아니라 무제한 트래픽입니다.
어떤 소프트웨어가 가장 좋나요?
처음에는 RTMP 모듈을 올린 nginx가 좋습니다. 가볍고 RTMP와 HLS를 동시에 처리할 수 있습니다. MediaMTX는 SRT와 WebRTC를 기본으로 갖춘 좀 더 현대적인 대안입니다. SRS는 기능이 가장 많지만 익히는 데 시간이 더 듭니다. Owncast는 웹 인터페이스와 채팅까지 갖춘 완성형 솔루션입니다.
지연은 얼마나 생기나요?
서버까지 올리는 RTMP 구간은 1초가 채 걸리지 않습니다. 지연은 거의 전부 송출 단계에서 생깁니다. 기본 설정의 HLS는 20~30초, 세그먼트를 짧게 잡으면 6~10초, Low-Latency HLS는 2~5초입니다. SRT와 WebRTC는 1초 미만이지만, 그만큼 시청자 한 명당 연산 부담이 큽니다.
트랜스코딩이 필요한가요? 비용은 어느 정도인가요?
화질 단계를 여럿 제공하려는 경우에만 필요합니다. 다시 인코딩하지 않고 그대로 넘기기만 하면 CPU는 거의 쓰지 않고, 코어 하나로 시청자 수백 명을 감당합니다. 1080p 스트림을 720p와 480p로도 함께 내보내려면 단계마다 최신 코어 두 개에서 네 개 정도가 필요합니다. 트랜스코딩은 정말 필요해진 다음에 계획하세요.
Twitch와 YouTube에 동시에 송출할 수 있나요?
네, 서버가 바로 그 일에 좋습니다. 내 서버로 한 번만 보내면 서버가 같은 스트림을 원하는 만큼 여러 플랫폼으로 전달합니다. nginx-RTMP에서는 목적지마다 push 한 줄만 있으면 됩니다. 그래도 내 회선이 짊어지는 업로드는 하나뿐입니다.
다른 사람이 내 서버로 송출하는 것을 어떻게 막나요?
방화벽에서 인제스트 포트를 내 주소로만 열고, 추가로 on_publish로 스트림 키를 검사하세요. 이 두 가지가 없으면 열려 있는 RTMP 서버는 며칠 안에 낯선 스트림을 받게 됩니다. 주소 범위 전체가 자동으로 검색되기 때문입니다.
서버는 어디에 두어야 하나요?
내 근처가 아니라 시청자 근처입니다. 나에서 서버까지의 경로는 한 번 지나가지만, 서버에서 시청자까지의 경로는 수천 번 지나갑니다. 시청자가 유럽에 있다면 서버도 유럽에 둡니다. 시청자가 여러 대륙에 흩어져 있다면 두 번째 서버를 두고 DNS로 분산하는 편이 유리합니다.
VPS로 충분한가요, 아니면 전용 서버가 필요한가요?
트랜스코딩 없이 그대로 전달만 한다면 코어가 몇 개뿐인 VPS로도 충분합니다. 병목은 연산이 아니라 회선이기 때문입니다. 화질 단계를 여럿 트랜스코딩하거나 채널을 여러 개 동시에 돌릴 때에야 전용 하드웨어가 값을 합니다.
서버가 부하를 견디는지 어떻게 시험하나요?
스트림을 켠 다음 여러 도구로 동시에 열어 보세요. 예를 들어 ffmpeg를 공회전 모드로 쓰면 됩니다. 그러면서 네트워크 처리량과 사용률을 지켜보세요. CPU가 더워지기 전에 회선 한계에 먼저 도달한다면 계산이 맞아떨어진 것이고, 필요한 것은 코어가 아니라 대역폭입니다.

Streaming RTMP HLS SRT nginx OBS Restream Unlimited Traffic