<chan9yu />
홈포스트시리즈태그About


@chan9yu's dev blog

프론트엔드 개발의 아이디어와 경험을 기록하는 개발 블로그
코드와 디자인, 사용자 경험을 아우르는 인사이트를 담습니다.

RSSGitHubEmail
© 2026 chan9yu. All rights reserved.

[WebRTC 박살내기 #1] WebRTC 개념과 연결 구조 완전 정리

WebRTC 박살내기 첫번째 시리즈 입니다. WebRTC 기본 개념부터 시그널링, Offer/Answer(SDP), Trickle ICE, STUN/TURN, NAT, 그리고 Mesh·SFU·MCU 아키텍처까지 한 번에 정리합니다.

2025년 10월 11일
 
WebRTC실시간통신P2PSDPICESTUNTURN

시리즈

WebRTC 박살내기!
1 / 4
이전 글첫 번째 글입니다
다음 글[WebRTC 박살내기 #2] 미디어 스트림과 트랙 완벽 이해
시리즈 전체 보기
[WebRTC 박살내기 #1] WebRTC 개념과 연결 구조 완전 정리
이전 글

항해플러스 프론트엔드 6기 완주 후기

다음 글

[WebRTC 박살내기 #2] 미디어 스트림과 트랙 완벽 이해

이런 글도 읽어보세요

[WebRTC 박살내기 #3] PeerConnection API와 이벤트 흐름

[WebRTC 박살내기 #3] PeerConnection API와 이벤트 흐름

2025년 10월 20일

WebRTC 박살내기 세번째 시리즈 입니다. WebRTC의 핵심 RTCPeerConnection을 완벽하게 이해하고, 연결 생성부터 이벤트 처리, 품질 관리, 연결 복구까지 실전 예제와 함께 알아봅니다.

WebRTCRTCPeerConnection+4
1분
[WebRTC 박살내기 #4] 데이터 채널 구조와 활용법

[WebRTC 박살내기 #4] 데이터 채널 구조와 활용법

2025년 10월 24일

WebRTC 박살내기 마지막 시리즈 입니다. WebRTC의 RTCDataChannel을 이해하고, 채팅·파일 전송·게임 동기화까지 실시간 데이터 전송의 모든 것을 알아봅니다.

WebRTCRTCDataChannel+3
1분
[WebRTC 박살내기 #2] 미디어 스트림과 트랙 완벽 이해

[WebRTC 박살내기 #2] 미디어 스트림과 트랙 완벽 이해

2025년 10월 13일

WebRTC 박살내기 두번째 시리즈 입니다. WebRTC의 MediaStream과 MediaStreamTrack을 깊이 이해하고, getUserMedia부터 트랙 제어, 품질 관리까지 실전 예제와 함께 알아봅니다.

WebRTCMediaStream+2
1분

댓글

목차

  • 서론
  • WebRTC가 뭘까?
  • WebRTC의 특별한 점
  • 플러그인이 필요 없어요
  • 진짜 실시간 통신이에요
  • 보안이 기본으로 들어있어요
  • 다양한 코덱을 지원해요
  • WebRTC의 약점
  • 구버전 브라우저는 안 돼요
  • NAT 문제를 해결하려면?
  • WebRTC의 연결 프로세스
  • Step 1: 시그널링 - 약속 잡기
  • 시그널링이 뭐죠?
  • 어떻게 주고받나요?
  • Step 2: Offer/Answer - 서로 맞추기
  • SDP가 뭐죠?
  • Offer와 Answer
  • SDP 실제 모습
  • Step 3: ICE - 길 찾기
  • 왜 길 찾기가 필요한가요?
  • NAT 종류와 난이도
  • ICE가 해결합니다
  • STUN과 TURN - 길잡이와 중개인
  • STUN: "너의 공인 IP는 이거야!"
  • TURN: "내가 대신 전달해줄게"
  • Trickle ICE: 더 빠른 연결
  • 연결 완료! 이제 통신 시작
  • 여러 명을 연결하려면?
  • Mesh: 직접 연결
  • 어떻게 동작하나요?
  • 부하는 어떻게 될까요?
  • 언제 사용하나요?
  • SFU: 서버가 중계
  • 어떻게 동작하나요?
  • 부하는 어떻게 될까요?
  • 언제 사용하나요?
  • MCU: 서버가 합성
  • 어떻게 동작하나요?
  • 부하는 어떻게 될까요?
  • 언제 사용하나요?
  • 아키텍처 비교 요약
  • 마무리
  • 정리

서론

안녕하세요 프론트엔드 개발자 여찬규입니다! 현재 재직 중인 회사에서 원격 솔루션을 개발하고 있는데요.
그 중 제가 담당하고 있는 서비스의 가장 핵심 기능이 실시간 영상 상담인데, 이 모든 것의 기반 기술이 바로 WebRTC(Web Real-Time Communication)입니다.

처음 WebRTC를 접했을 때는 브라우저에서 영상 통화를 할 수 있게 해주는 기술 정도로만 이해했습니다.
그러나 실제 운영 환경에서 WebRTC를 다뤄보니, 단순한 영상 통화를 넘어서 네트워크, 시그널링, NAT 우회 등이 얽혀 있으며 모든 실시간 상호작용을 가능하게 하는 기반 기술이라는 것을 알게 되었습니다.

이번 글은 WebRTC 박살내기 시리즈의 시작으로, WebRTC를 처음 접하는 개발자도 이해할 수 있도록 WebRTC의 기본 개념부터 실제 연결 구조, 그리고 핵심 기술들을 차근차근 정리해보겠습니다.


WebRTC가 뭘까?

WebRTC 란?

"브라우저끼리 직접 연결해서 영상, 음성, 데이터를 주고받는 기술"

플러그인 설치 없이, 서버를 최소한만 거쳐서, P2P 실시간으로 통신할 수 있습니다.

💡 P2P(Peer-to-Peer)란?

마치 두 사람이 직접 만나서 대화하듯, 서버를 거치지 않고 브라우저끼리 바로 연결되는 방식입니다.
중간에 전달자가 없으니 빠르고, 서버 비용도 절약됩니다.

2011년 Google이 오픈소스로 공개한 이후, 현재는 모든 주요 브라우저가 지원하는 웹 표준입니다.


WebRTC의 특별한 점

플러그인이 필요 없어요

Flash나 ActiveX 설치 없이 브라우저만 있으면 됩니다.
사용자가 별도로 뭔가 깔 필요가 없다는 건 엄청난 장점이죠.

진짜 실시간 통신이에요

서비스지연 시간기술
YouTube 라이브2-5초RTMP/HLS
인스타그램 라이브3-8초RTMP
WebRTC (P2P)50-200msWebRTC
WebRTC (SFU)200-500msWebRTC

1초도 안 되는 지연 시간으로, 거의 실시간 대화가 가능합니다.

💡 지연 시간(Latency)이란?

내가 "안녕?"이라고 말했을 때, 상대방이 듣기까지 걸리는 시간입니다.
0.2초라면 거의 직접 대화하는 것처럼 느껴집니다.

보안이 기본으로 들어있어요

모든 데이터가 DTLS와 SRTP로 암호화됩니다.
중간에 누가 가로챈다 해도 내용을 볼 수 없습니다.

💡 DTLS와 SRTP란?

DTLS는 "이 사람이 진짜 맞나?" 확인하고 암호 키를 나누는 역할,
SRTP는 그 키로 실제 영상과 음성을 잠그는 역할입니다.

다양한 코덱을 지원해요

비디오 코덱
  • VP8, H.264: 기본으로 지원 (모든 브라우저)
  • VP9: 더 좋은 화질 (선택 사항)
  • AV1: 최신 고효율 코덱 (Chrome 93+, Firefox 111+)
    • VP9보다 30% 더 압축
    • 느린 인터넷에서도 고화질 가능

코덱은 브라우저끼리 협상해서 자동으로 결정됩니다.


WebRTC의 약점

구버전 브라우저는 안 돼요

브라우저지원 버전특이사항
Chrome23+완전 지원
Firefox22+완전 지원
Safari11+VP8/VP9 제한적 (17+부터 VP9 지원)
Edge79+Chrome과 동일

최신 브라우저에서는 문제없지만, 구버전 지원이 필요하면 폴백 전략이 필요합니다.

NAT 문제를 해결하려면?

NAT 환경에서 P2P 연결을 하기 위해서는 특별한 서버의 도움이 필요합니다
"서버 없이 P2P"라고 했는데 서버가 필요하다고요?

네, 정확히는 연결을 시작할 때만 서버가 필요합니다.
대부분의 사용자는 공유기(NAT) 뒤에 숨어있어서, 서로를 찾기 위한 도움이 필요하거든요.

  • STUN 서버: "너의 공인 IP는 이거야!" (무료로 많음)
  • TURN 서버: "내가 대신 전달해줄게" (비용 발생)

STUN/TURN에 대해서는 조금 뒤에 자세히 다룰게요.


WebRTC의 연결 프로세스

WebRTC 연결은 마치 처음 만나는 두 사람이 대화를 시작하는 과정과 비슷합니다.

  1. 시그널링: "만날 장소를 정하자" (메신저로 약속 잡기)
  2. Offer/Answer: "나는 한국어 할 수 있어" "나도!" (언어 맞추기)
  3. ICE: "카페 1번 테이블에서 만나자" (정확한 위치 찾기)
  4. 연결 완료: 드디어 대화 시작! (영상/음성 전송)

하나씩 살펴볼게요.

Step 1: 시그널링 - 약속 잡기

시그널링이 뭐죠?

두 브라우저가 만나기 위한 사전 조율 과정입니다.

브라우저 A: "나 720p 지원해, H.264 코덱 써"
브라우저 B: "나도! 그럼 그걸로 하자"

이런 정보를 주고받는 과정을 시그널링이라고 합니다.

어떻게 주고받나요?

WebRTC 표준에는 시그널링 방법이 정의되어 있지 않습니다.

🧐 왜 표준에 없을까?

서비스마다 환경이 다르니까요.
어떤 곳은 WebSocket을 쓰고, 어떤 곳은 REST API를 씁니다.
선택의 자유를 주는 거죠.

일반적인 방법들
  • WebSocket (가장 흔함)
  • MQTT Protocol
  • REST API + 폴링
  • Firebase Realtime Database
최근 표준화된 방법
  • WHIP (WebRTC HTTP Ingestion Protocol): 영상 송신용
  • WHEP (WebRTC HTTP Egress Protocol): 영상 수신용

Step 2: Offer/Answer - 서로 맞추기

Offer/Answer는 SDP(Session Description Protocol)를 교환하는 과정입니다.
즉, Offer는 자신의 미디어 정보(SDP)를 제안하고, Answer는 그 제안에 대한 수락(응답) SDP를 보내 두 피어가 미디어 세션 구성을 합의하는 절차입니다.

SDP가 뭐죠?

SDP(Session Description Protocol)는 "우리 이렇게 통신할래?"를 설명하는 메뉴판입니다.

마치 식당 메뉴판처럼

  • 제공 가능한 요리(코덱)
  • 가격(대역폭)
  • 조리 방법(암호화)

이런 정보가 담겨 있습니다.

Offer와 Answer

발신자 (Offer)

나는 이런 걸 지원해!

  • 비디오: H.264, 720p
  • 오디오: Opus, 48kHz
  • 암호화: 이렇게 할래
수신자 (Answer)

나도 그거 지원해!
그럼 H.264로 하고
Opus로 하자

협상 완료!

둘 다 지원하는 최적의 방법으로 합의 완료.

SDP 실제 모습

주요 필드 설명
필드의미예시
v=SDP 버전v=0
o=세션 발신자 정보사용자명, 세션 ID, IP
c=연결 정보 (IP 주소)c=IN IP4 192.168.0.10
m=미디어 정보

💡 SDP를 직접 볼 일 있나요?

대부분 라이브러리가 자동으로 처리해줍니다.
다만 디버깅할 때 SDP를 읽을 수 있으면 문제를 빠르게 찾을 수 있어요.

Step 3: ICE - 길 찾기

왜 길 찾기가 필요한가요?

대부분의 사용자는 공유기(NAT) 뒤에 숨어 있습니다.

일반적인 상황

NAT 환경

문제는 외부에서 192.168.0.5로 직접 접근할 수 없다는 거죠.

💡 NAT(Network Address Translation)란?

마치 아파트 우편함처럼, 하나의 공인 IP(아파트 주소)로
여러 기기(각 세대)를 관리하는 시스템입니다.

공인 IP가 부족하니까 이렇게 공유해서 쓰는 거죠.

NAT 종류와 난이도

NAT도 종류가 있어서, 어떤 건 쉽게 뚫리고 어떤 건 거의 불가능합니다.

NAT 타입연결 난이도설명
Full Cone⭐가장 쉬움
Restricted Cone⭐⭐특정 조건 필요
Port Restricted Cone⭐⭐⭐더 까다로움
Symmetric NAT⭐⭐⭐⭐거의 불가능 (TURN 필요)

ICE가 해결합니다

ICE(Interactive Connectivity Establishment)는 모든 가능한 경로를 찾아서 테스트하는 프레임워크입니다.

ICE의 작동 순서
  1. 후보 수집: 연결 가능한 모든 경로 찾기
    • 로컬 IP (같은 네트워크)
    • 공인 IP (STUN으로 확인)
    • TURN 중계 서버 경로
  2. 후보 교환: 시그널링으로 서로 공유
  3. 연결 테스트: 모든 경로 조합을 실제로 시도
  4. 최적 경로 선택: 가장 빠르고 안정적인 경로로 확정

STUN과 TURN - 길잡이와 중개인

ICE가 연결 경로를 찾기 위해서는 두 가지 특별한 서버의 도움이 필요합니다.
STUN은 내 공인 IP를 알려주는 길잡이이고, TURN은 직접 연결이 안 될 때 중간에서 데이터를 전달해주는 중개인이에요.

STUN: "너의 공인 IP는 이거야!"

STUN(Session Traversal Utilities for NAT)은 내 공인 IP를 알려주는 서버입니다.

STUN 작동 방식

장점: 무료, 빠름, 가벼움
단점: Symmetric NAT 같은 복잡한 환경에서는 연결불가

TURN: "내가 대신 전달해줄게"

TURN(Traversal Using Relays around NAT)은 직접 연결이 불가능할 때 중계해주는 서버입니다.

작동 방식

TURN 작동 방식

장점: 어떤 환경에서도 100% 연결 보장
단점: 서버 비용 발생, 대역폭 소모, 약간의 지연

💡 언제 TURN이 필요할까?

  • 기업 방화벽 뒤 (UDP 차단)
  • Symmetric NAT 환경
  • 이중 NAT (공유기 뒤에 또 공유기)

Trickle ICE: 더 빠른 연결

예전 방식은 모든 후보를 수집한 후에 교환했습니다.
이러면 시간이 오래 걸리죠.

Trickle ICE는 후보를 찾는 즉시 바로 전송합니다.

기존 방식

ICE 기존 방식

Trickle ICE

Trickle ICE 방식

현재 대부분의 WebRTC 구현은 Trickle ICE를 기본으로 사용합니다.

연결 완료! 이제 통신 시작

모든 과정이 끝나면?

  • 시그널링 서버는 더 이상 필요 없음
  • 피어끼리 직접 데이터 전송
  • 영상, 음성, 모든 데이터가 실시간으로 흐름

여러 명을 연결하려면?

1:1은 쉽습니다. 그런데 10명, 100명이 동시에 화상 회의를 한다면?

문제: N명이 참여하면 N(N-1)/2 개의 연결이 필요

  • 4명: 6개 연결
  • 10명: 45개 연결
  • 100명: 4,950개 연결 😱

각 참가자가 다른 모든 사람에게 직접 영상을 보내야 하기 때문에,
참여자가 늘어날수록 연결 수가 기하급수적으로 증가하는 문제가 발생해요.

이제 WebRTC의 다자간 연결 아키텍처를 살펴볼게요.
문제를 해결하는 방식에 따라 크게 3가지로 나뉩니다.

Mesh: 직접 연결

Mesh

어떻게 동작하나요?

가장 단순한 구조입니다.
모든 사람이 모든 사람과 직접 연결됩니다.

5명이 참가하면?

나 → A, B, C, D에게 영상 전송
나 ← A, B, C, D에게서 영상 수신

부하는 어떻게 될까요?

항목5명 기준
내가 보내는 횟수4번 인코딩
받는 영상 개수4개 디코딩
업로드 대역폭약 4-5Mbps
다운로드 대역폭약 4-5Mbps
문제점
  • 업로드 대역폭: 가정용 인터넷 (5-10Mbps)으로는 5명 이상 버거움
  • CPU/GPU: 참가자마다 별도 인코딩 필요
  • 메모리: 모든 연결을 유지해야 함

💡 가정용 인터넷의 한계

다운로드는 100Mbps여도 업로드는 10Mbps인 경우가 많습니다.
Mesh는 업로드가 병목이 되기 쉽습니다.

언제 사용하나요?

✅ 2-4명 소규모 회의
✅ 1:1 화상 통화
✅ 서버 비용 없이 낮은 지연시간이 중요한 경우

🆘 5명 이상
🆘 모바일이나 저사양 기기

SFU: 서버가 중계

SFU

어떻게 동작하나요?

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
개선된 점
  • ✅ 업로드 대역폭 75% 감소 (가장 큰 장점!)
  • ✅ 인코딩 부하 75% 감소
  • ✅ 서버에서 추가 최적화 가능
    • Simulcast: 여러 화질 동시 전송
    • 현재 발언자 강조
    • 네트워크 상황에 맞춰 화질 조절
여전히 남은 부하
  • ⚠️ 디코딩은 여전히 참가자 수만큼 필요
  • ⚠️ 다운로드 대역폭은 동일

언제 사용하나요?

✅ 5-100명 중대규모 회의
✅ Google Meet, Zoom 같은 일반적인 화상 회의
✅ 서버 비용은 있지만 사용자 부담을 줄이고 싶을 때

🆘 100명 이상 대규모
🆘 저사양 모바일 기기가 많은 환경

MCU: 서버가 합성

MCU

어떻게 동작하나요?

MCU(Multipoint Control Unit)는 서버가 모든 영상을 하나로 합쳐서 전달합니다.

마치 TV 뉴스의 화상 회의 화면처럼, 격자 형태로 합성합니다.

핵심: 피어는 항상 1개의 합성된 영상만 받습니다.

5명이 참가해도?

서버: 5개 영상 디코딩 → 합성 → 1개로 인코딩
나: 1개 영상만 디코딩

부하는 어떻게 될까요?

항목SFU (5명)MCU (5명)
서버 인코딩없음5개 디코딩 + 합성
내가 받는 영상4개 디코딩1개만 디코딩
다운로드 대역폭약 4-5Mbps약 1-1.5Mbps
서버 CPU낮음매우 높음
장점
  • ✅ 피어 부하 최소화 (저사양 기기도 OK)
  • ✅ 참가자가 100명이든 영상은 1개
  • ✅ 다운로드 대역폭 75% 감소
  • ✅ 데이터 사용량 예측 가능
단점
  • 🆘 서버 CPU 사용량 매우 높음
  • 🆘 서버 비용 매우 높음
  • 🆘 약간의 지연 시간 증가
  • 🆘 레이아웃을 서버가 결정 (유연성 낮음)

💡 왜 서버 부하가 높을까?

100명 회의를 생각해보면

  • 100개 영상을 각각 디코딩
  • 격자 형태로 실시간 합성
  • 1개로 다시 인코딩

이걸 실시간으로 처리하려면 강력한 CPU가 필요합니다.

언제 사용하나요?

✅ 100명 이상 대규모 웨비나
✅ 저사양 모바일 기기 지원 필수
✅ 제한된 데이터 요금제 사용자가 많을 때
✅ 모든 참가자에게 동일한 화면

🆘 소규모 회의 (비용 낭비)
🆘 낮은 지연 시간이 중요한 경우

아키텍처 비교 요약

구분MeshSFUMCU
서버 역할없음중계 (변환 X)합성 (변환 O)
피어 업로드N-1개1개만1개만
피어 디코딩N-1개N-1개1개만
서버 부하거의 없음대역폭 높음CPU 매우 높음

마무리

WebRTC는 단순히 "화상 통화 기술"이 아닙니다.
네트워크, 미디어, 보안이 총 결합된 실시간 통신 플랫폼입니다.

정리

연결 과정
  1. 시그널링: 약속 잡기
  2. Offer/Answer: 방식 맞추기 (SDP)
  3. ICE: 길 찾기 (STUN/TURN)
  4. 연결 완료: 실시간 통신 시작
NAT 문제 해결
  • STUN: 내 공인 IP 확인
  • TURN: 중계 서버
  • ICE: 최적 경로 자동 선택
다자간 통신 아키텍처
  • Mesh: 2-4명 소규모, 서버 비용 없음
  • SFU: 5-50명 중규모, 가장 일반적
  • MCU: 50명 이상, 저사양 기기 지원

이번 글에서는 WebRTC의 개념과 연결 구조를 다뤘습니다.

다음 글에서는

  • 카메라와 마이크 접근하기
  • 화면 공유 구현하기
  • 트랙 추가/제거/교체하기

을 다루는 미디어 스트림과 트랙에 대해 알아보겠습니다.

끝까지 읽어주셔서 감사합니다!

m=audio 49170 ...
a=속성 (코덱, 방향 등)a=rtpmap:0 PCMU/8000
서버 비용
없음
중간
매우 높음
피어 부하높음중간낮음
적정 인원2-4명5-50명50명 이상
지연 시간가장 낮음낮음약간 높음
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  
const peerConnection = new RTCPeerConnection({  
	iceServers: [{ urls: "stun:stun.l.google.com:19302" }]  
});  
const peerConnection = new RTCPeerConnection({  
	iceServers: [  
		{ urls: "stun:stun.l.google.com:19302" },  
		{  
			urls: "turn:your-turn-server.com:3478",  
			username: "user",  
			credential: "password"  
		}  
	]  
});