WebRTC 박살내기 첫번째 시리즈 입니다. WebRTC 기본 개념부터 시그널링, Offer/Answer(SDP), Trickle ICE, STUN/TURN, NAT, 그리고 Mesh·SFU·MCU 아키텍처까지 한 번에 정리합니다.
WebRTC 박살내기 세번째 시리즈 입니다. WebRTC의 핵심 RTCPeerConnection을 완벽하게 이해하고, 연결 생성부터 이벤트 처리, 품질 관리, 연결 복구까지 실전 예제와 함께 알아봅니다.
WebRTC 박살내기 마지막 시리즈 입니다. WebRTC의 RTCDataChannel을 이해하고, 채팅·파일 전송·게임 동기화까지 실시간 데이터 전송의 모든 것을 알아봅니다.
WebRTC 박살내기 두번째 시리즈 입니다. WebRTC의 MediaStream과 MediaStreamTrack을 깊이 이해하고, getUserMedia부터 트랙 제어, 품질 관리까지 실전 예제와 함께 알아봅니다.
안녕하세요 프론트엔드 개발자 여찬규입니다! 현재 재직 중인 회사에서 원격 솔루션을 개발하고 있는데요.
그 중 제가 담당하고 있는 서비스의 가장 핵심 기능이 실시간 영상 상담인데, 이 모든 것의 기반 기술이 바로 WebRTC(Web Real-Time Communication)입니다.
처음 WebRTC를 접했을 때는 브라우저에서 영상 통화를 할 수 있게 해주는 기술 정도로만 이해했습니다.
그러나 실제 운영 환경에서 WebRTC를 다뤄보니, 단순한 영상 통화를 넘어서 네트워크, 시그널링, NAT 우회 등이 얽혀 있으며 모든 실시간 상호작용을 가능하게 하는 기반 기술이라는 것을 알게 되었습니다.
이번 글은 WebRTC 박살내기 시리즈의 시작으로, WebRTC를 처음 접하는 개발자도 이해할 수 있도록 WebRTC의 기본 개념부터 실제 연결 구조, 그리고 핵심 기술들을 차근차근 정리해보겠습니다.

플러그인 설치 없이, 서버를 최소한만 거쳐서, P2P 실시간으로 통신할 수 있습니다.
💡 P2P(Peer-to-Peer)란?
마치 두 사람이 직접 만나서 대화하듯, 서버를 거치지 않고 브라우저끼리 바로 연결되는 방식입니다.
중간에 전달자가 없으니 빠르고, 서버 비용도 절약됩니다.
2011년 Google이 오픈소스로 공개한 이후, 현재는 모든 주요 브라우저가 지원하는 웹 표준입니다.
Flash나 ActiveX 설치 없이 브라우저만 있으면 됩니다.
사용자가 별도로 뭔가 깔 필요가 없다는 건 엄청난 장점이죠.
| 서비스 | 지연 시간 | 기술 |
|---|---|---|
| YouTube 라이브 | 2-5초 | RTMP/HLS |
| 인스타그램 라이브 | 3-8초 | RTMP |
| WebRTC (P2P) | 50-200ms | WebRTC |
| WebRTC (SFU) | 200-500ms | WebRTC |
1초도 안 되는 지연 시간으로, 거의 실시간 대화가 가능합니다.
💡 지연 시간(Latency)이란?
내가 "안녕?"이라고 말했을 때, 상대방이 듣기까지 걸리는 시간입니다.
0.2초라면 거의 직접 대화하는 것처럼 느껴집니다.
모든 데이터가 DTLS와 SRTP로 암호화됩니다.
중간에 누가 가로챈다 해도 내용을 볼 수 없습니다.
💡 DTLS와 SRTP란?
DTLS는 "이 사람이 진짜 맞나?" 확인하고 암호 키를 나누는 역할,
SRTP는 그 키로 실제 영상과 음성을 잠그는 역할입니다.
코덱은 브라우저끼리 협상해서 자동으로 결정됩니다.
| 브라우저 | 지원 버전 | 특이사항 |
|---|---|---|
| Chrome | 23+ | 완전 지원 |
| Firefox | 22+ | 완전 지원 |
| Safari | 11+ | VP8/VP9 제한적 (17+부터 VP9 지원) |
| Edge | 79+ | Chrome과 동일 |
최신 브라우저에서는 문제없지만, 구버전 지원이 필요하면 폴백 전략이 필요합니다.
NAT 환경에서 P2P 연결을 하기 위해서는 특별한 서버의 도움이 필요합니다
"서버 없이 P2P"라고 했는데 서버가 필요하다고요?
네, 정확히는 연결을 시작할 때만 서버가 필요합니다.
대부분의 사용자는 공유기(NAT) 뒤에 숨어있어서, 서로를 찾기 위한 도움이 필요하거든요.
STUN/TURN에 대해서는 조금 뒤에 자세히 다룰게요.
WebRTC 연결은 마치 처음 만나는 두 사람이 대화를 시작하는 과정과 비슷합니다.
하나씩 살펴볼게요.
두 브라우저가 만나기 위한 사전 조율 과정입니다.
브라우저 A: "나 720p 지원해, H.264 코덱 써"
브라우저 B: "나도! 그럼 그걸로 하자"
이런 정보를 주고받는 과정을 시그널링이라고 합니다.
WebRTC 표준에는 시그널링 방법이 정의되어 있지 않습니다.
일반적인 방법들🧐 왜 표준에 없을까?
서비스마다 환경이 다르니까요.
어떤 곳은 WebSocket을 쓰고, 어떤 곳은 REST API를 씁니다.
선택의 자유를 주는 거죠.
Offer/Answer는 SDP(Session Description Protocol)를 교환하는 과정입니다.
즉, Offer는 자신의 미디어 정보(SDP)를 제안하고, Answer는 그 제안에 대한 수락(응답) SDP를 보내 두 피어가 미디어 세션 구성을 합의하는 절차입니다.
SDP(Session Description Protocol)는 "우리 이렇게 통신할래?"를 설명하는 메뉴판입니다.
마치 식당 메뉴판처럼
이런 정보가 담겨 있습니다.
수신자 (Answer)나는 이런 걸 지원해!
- 비디오: H.264, 720p
- 오디오: Opus, 48kHz
- 암호화: 이렇게 할래
협상 완료!나도 그거 지원해!
그럼 H.264로 하고
Opus로 하자
둘 다 지원하는 최적의 방법으로 합의 완료.
v=0
o=- 46117327 2 IN IP4 127.0.0.1
s=-
c=IN IP4 192.168.0.10
t=0 0
m=audio 49170 RTP/AVP 0
a=rtpmap:0 PCMU/8000
m=video 5004 RTP/AVP 96
a=rtpmap:96 H264/90000 | 필드 | 의미 | 예시 |
|---|---|---|
v= | SDP 버전 | v=0 |
o= | 세션 발신자 정보 | 사용자명, 세션 ID, IP |
c= | 연결 정보 (IP 주소) | c=IN IP4 192.168.0.10 |
m= | 미디어 정보 | m=audio 49170 ... |
a= | 속성 (코덱, 방향 등) | a=rtpmap:0 PCMU/8000 |
💡 SDP를 직접 볼 일 있나요?
대부분 라이브러리가 자동으로 처리해줍니다.
다만 디버깅할 때 SDP를 읽을 수 있으면 문제를 빠르게 찾을 수 있어요.
대부분의 사용자는 공유기(NAT) 뒤에 숨어 있습니다.
일반적인 상황
문제는 외부에서 192.168.0.5로 직접 접근할 수 없다는 거죠.
💡 NAT(Network Address Translation)란?
마치 아파트 우편함처럼, 하나의 공인 IP(아파트 주소)로
여러 기기(각 세대)를 관리하는 시스템입니다.공인 IP가 부족하니까 이렇게 공유해서 쓰는 거죠.
NAT도 종류가 있어서, 어떤 건 쉽게 뚫리고 어떤 건 거의 불가능합니다.
| NAT 타입 | 연결 난이도 | 설명 |
|---|---|---|
| Full Cone | ⭐ | 가장 쉬움 |
| Restricted Cone | ⭐⭐ | 특정 조건 필요 |
| Port Restricted Cone | ⭐⭐⭐ | 더 까다로움 |
| Symmetric NAT | ⭐⭐⭐⭐ | 거의 불가능 (TURN 필요) |
ICE(Interactive Connectivity Establishment)는 모든 가능한 경로를 찾아서 테스트하는 프레임워크입니다.
ICE의 작동 순서ICE가 연결 경로를 찾기 위해서는 두 가지 특별한 서버의 도움이 필요합니다.
STUN은 내 공인 IP를 알려주는 길잡이이고, TURN은 직접 연결이 안 될 때 중간에서 데이터를 전달해주는 중개인이에요.
STUN(Session Traversal Utilities for NAT)은 내 공인 IP를 알려주는 서버입니다.
const peerConnection = new RTCPeerConnection({
iceServers: [{ urls: "stun:stun.l.google.com:19302" }]
}); 
장점: 무료, 빠름, 가벼움
단점: Symmetric NAT 같은 복잡한 환경에서는 연결불가
TURN(Traversal Using Relays around NAT)은 직접 연결이 불가능할 때 중계해주는 서버입니다.
const peerConnection = new RTCPeerConnection({
iceServers: [
{ urls: "stun:stun.l.google.com:19302" },
{
urls: "turn:your-turn-server.com:3478",
username: "user",
credential: "password"
}
]
}); 
장점: 어떤 환경에서도 100% 연결 보장
단점: 서버 비용 발생, 대역폭 소모, 약간의 지연
💡 언제 TURN이 필요할까?
- 기업 방화벽 뒤 (UDP 차단)
- Symmetric NAT 환경
- 이중 NAT (공유기 뒤에 또 공유기)
예전 방식은 모든 후보를 수집한 후에 교환했습니다.
이러면 시간이 오래 걸리죠.
Trickle ICE는 후보를 찾는 즉시 바로 전송합니다.
기존 방식

현재 대부분의 WebRTC 구현은 Trickle ICE를 기본으로 사용합니다.
모든 과정이 끝나면?
1:1은 쉽습니다. 그런데 10명, 100명이 동시에 화상 회의를 한다면?
문제: N명이 참여하면 N(N-1)/2 개의 연결이 필요
각 참가자가 다른 모든 사람에게 직접 영상을 보내야 하기 때문에,
참여자가 늘어날수록 연결 수가 기하급수적으로 증가하는 문제가 발생해요.
이제 WebRTC의 다자간 연결 아키텍처를 살펴볼게요.
문제를 해결하는 방식에 따라 크게 3가지로 나뉩니다.

가장 단순한 구조입니다.
모든 사람이 모든 사람과 직접 연결됩니다.
나 → A, B, C, D에게 영상 전송
나 ← A, B, C, D에게서 영상 수신
| 항목 | 5명 기준 |
|---|---|
| 내가 보내는 횟수 | 4번 인코딩 |
| 받는 영상 개수 | 4개 디코딩 |
| 업로드 대역폭 | 약 4-5Mbps |
| 다운로드 대역폭 | 약 4-5Mbps |
💡 가정용 인터넷의 한계
다운로드는 100Mbps여도 업로드는 10Mbps인 경우가 많습니다.
Mesh는 업로드가 병목이 되기 쉽습니다.
✅ 2-4명 소규모 회의
✅ 1:1 화상 통화
✅ 서버 비용 없이 낮은 지연시간이 중요한 경우
🆘 5명 이상
🆘 모바일이나 저사양 기기

SFU(Selective Forwarding Unit)는 서버가 중계자 역할을 합니다.
핵심: 서버는 영상을 변환하지 않고 그대로 전달만 합니다.
5명이 참가하면?나 → 서버에 영상 1번만 전송
서버 → A, B, C, D에게 내 영상 전달
| 항목 | Mesh (5명) | SFU (5명) |
|---|---|---|
| 내가 보내는 횟수 | 4번 인코딩 | 1번만 인코딩 |
| 받는 영상 개수 | 4개 디코딩 | 4개 디코딩 |
| 업로드 대역폭 | 약 4-5Mbps | 약 1-1.5Mbps |
| 다운로드 대역폭 | 약 4-5Mbps | 약 4-5Mbps |
✅ 5-100명 중대규모 회의
✅ Google Meet, Zoom 같은 일반적인 화상 회의
✅ 서버 비용은 있지만 사용자 부담을 줄이고 싶을 때
🆘 100명 이상 대규모
🆘 저사양 모바일 기기가 많은 환경

MCU(Multipoint Control Unit)는 서버가 모든 영상을 하나로 합쳐서 전달합니다.
마치 TV 뉴스의 화상 회의 화면처럼, 격자 형태로 합성합니다.
핵심: 피어는 항상 1개의 합성된 영상만 받습니다.
5명이 참가해도?서버: 5개 영상 디코딩 → 합성 → 1개로 인코딩
나: 1개 영상만 디코딩
| 항목 | SFU (5명) | MCU (5명) |
|---|---|---|
| 서버 인코딩 | 없음 | 5개 디코딩 + 합성 |
| 내가 받는 영상 | 4개 디코딩 | 1개만 디코딩 |
| 다운로드 대역폭 | 약 4-5Mbps | 약 1-1.5Mbps |
| 서버 CPU | 낮음 | 매우 높음 |
💡 왜 서버 부하가 높을까?
100명 회의를 생각해보면
- 100개 영상을 각각 디코딩
- 격자 형태로 실시간 합성
- 1개로 다시 인코딩
이걸 실시간으로 처리하려면 강력한 CPU가 필요합니다.
✅ 100명 이상 대규모 웨비나
✅ 저사양 모바일 기기 지원 필수
✅ 제한된 데이터 요금제 사용자가 많을 때
✅ 모든 참가자에게 동일한 화면
🆘 소규모 회의 (비용 낭비)
🆘 낮은 지연 시간이 중요한 경우
| 구분 | Mesh | SFU | MCU |
|---|---|---|---|
| 서버 역할 | 없음 | 중계 (변환 X) | 합성 (변환 O) |
| 피어 업로드 | N-1개 | 1개만 | 1개만 |
| 피어 디코딩 | N-1개 | N-1개 | 1개만 |
| 서버 부하 | 거의 없음 | 대역폭 높음 | CPU 매우 높음 |
WebRTC는 단순히 "화상 통화 기술"이 아닙니다.
네트워크, 미디어, 보안이 총 결합된 실시간 통신 플랫폼입니다.
이번 글에서는 WebRTC의 개념과 연결 구조를 다뤘습니다.
다음 글에서는
을 다루는 미디어 스트림과 트랙에 대해 알아보겠습니다.
끝까지 읽어주셔서 감사합니다!
| 없음 |
| 중간 |
| 매우 높음 |
| 피어 부하 | 높음 | 중간 | 낮음 |
| 적정 인원 | 2-4명 | 5-50명 | 50명 이상 |
| 지연 시간 | 가장 낮음 | 낮음 | 약간 높음 |