WebRTC 연결 기초 — ICE, STUN, TURN, NAT
WebRTC의 media·data 연결과 signaling의 경계를 소개하고, NAT와 firewall 환경에서 ICE가 candidate pair를 검사하는 과정을 설명합니다. STUN으로 server-reflexive candidate를 얻고 TURN relay를 사용하는 경우를 구분하며, Agora Web SDK가 제공하는 channel·track API와 browser WebRTC 구현의 관계도 정리합니다.
목차(16개 항목)
- WebRTC란?
- NAT와 P2P 연결의 한계
- STUN (Session Traversal Utilities for NAT)
- TURN (Traversal Using Relays around NAT)
ICE (Interactive Connectivity Establishment)
- WebRTC API 관점에서 정리
Agora Web SDK를 쓰면? 인프라는 SDK가 처리해 줍니다
- 관련 글
- 참고 자료
WebRTC(Web Real-Time Communication)는 플러그인이나 별도 소프트웨어 없이 브라우저 간에 오디오·영상·데이터를 실시간으로 주고받을 수 있게 하는 웹 표준입니다. 화상 통화, 화면 공유, P2P 파일 전송 등에 쓰입니다. Agora Web SDK처럼 브라우저에서 동작하는 관리형 RTC SDK는 이 브라우저 기능을 감싸 채널·토큰·미디어 트랙 API를 제공합니다. 이 글에서는 WebRTC와 P2P 연결에 함께 등장하는 NAT, STUN, TURN, ICE의 역할을 정리합니다.
WebRTC란?
MDN WebRTC API 문서에 따르면, WebRTC는 다음을 가능하게 합니다.
- 미디어 캡처·스트리밍: 카메라, 마이크 등에서 오디오·영상을 가져와 브라우저 간에 전송
- 임의 데이터 교환: 플러그인 없이 피어 간 직접 데이터 채널로 바이너리·텍스트 전송
- 종단 간 통신: 중간 서버 없이 두 피어가 직접 연결되는 P2P 구조를 목표로 함
두 피어 간 연결은 RTCPeerConnection 인터페이스로 다루며, 연결이 수립되면 미디어 스트림(MediaStream)이나 데이터 채널(RTCDataChannel)을 붙여서 음성·영상·파일 등을 주고받습니다. 다만 실제 네트워크에는 NAT·방화벽이 있어서, “서로의 주소만 알면 바로 연결”이 되지 않는 경우가 많습니다. 이때 STUN, TURN, ICE가 필요합니다.
NAT와 P2P 연결의 한계
NAT는 내부망과 외부망 사이에서 사설 IP:포트와 공인 IP:포트를 매핑합니다. 외부에서는 “공인 IP:포트”로만 보이기 때문에, 상대방이 “내가 보이는 주소”를 모르면 P2P 연결을 시도하기 어렵습니다. 또한 NAT의 매핑·필터링 동작에 따라 외부에서 들어오는 패킷의 허용 범위가 달라져 P2P 연결에 제약이 생깁니다.
- Full Cone NAT: 한 번 매핑되면 다른 쪽에서도 해당 포트로 접속 가능
- Restricted Cone NAT: 클라이언트가 접속했던 서버(IP 기준)만 해당 포트로 접속 가능
- Port Restricted Cone NAT: 접속했던 서버의 IP·포트만 접속 가능
- Symmetric NAT: 목적지에 따라 매핑된 포트가 달라질 수 있어 직접 연결이 까다로움
이 네 가지는 RFC 3489의 레거시 분류입니다. 현행 NAT 동작은 RFC 4787처럼 매핑과 필터링을 분리해 설명하는 편이 정확합니다.
그래서 “내가 외부에 어떻게 보이는지 알아내는 것”과 “그 정보를 상대에게 전달해 서로 연결을 시도하는 것”을 표준화한 프로토콜이 STUN, TURN, ICE입니다.
STUN (Session Traversal Utilities for NAT)
STUN은 현행 RFC 8489에 정의된 프로토콜입니다. RFC 8489는 이전 규격인 RFC 5389를 대체합니다.
- STUN 서버가 관찰한 IP·포트 매핑을 응답으로 돌려줌
- ICE가 사용할 Server Reflexive Candidate를 수집하게 함
클라이언트가 STUN 서버에 요청을 보내면, 서버는 요청에서 관찰한 매핑 주소를 응답으로 돌려줍니다. ICE는 이 주소를 Server Reflexive Candidate로 상대에게 전달하고 직접 연결을 검사합니다. STUN 자체는 미디어를 중계하지 않습니다. TURN 사용 비율은 NAT·기업 방화벽·통신사망 정책에 따라 달라지므로 고정 비율을 일반화할 수 없으며, 운영 서비스의 ICE 후보 통계로 측정해야 합니다.
TURN (Traversal Using Relays around NAT)
TURN은 현행 RFC 8656에 정의된 릴레이 프로토콜입니다. RFC 8656은 RFC 5766을 대체합니다. 직접 후보 쌍의 연결 검사에 실패하면 TURN 서버가 중간에서 데이터를 받아 다른 피어에게 전달하는 relayed candidate를 사용할 수 있습니다.
- 클라이언트는 TURN 서버에 Allocate Request를 보내고, 서버가 할당한 Relayed Transport Address를 받습니다.
- 이 주소를 시그널링을 통해 상대에게 전달하면, 상대는 그 주소(TURN 서버)로 접속하고, TURN 서버가 해당 클라이언트와의 세션으로 패킷을 릴레이합니다.
TURN 경로에서는 실제 미디어가 서버를 경유하므로 서버 대역폭·비용이 듭니다. 대신 직접 후보 쌍이 연결되지 않는 환경에서 통신 경로를 제공합니다.
ICE (Interactive Connectivity Establishment)
ICE는 사용 가능한 모든 연결 후보(Candidate) 를 모아서, 그중에서 실제로 연결 가능한 경로를 선택하는 방식입니다. 후보는 대략 세 가지입니다.
- Host Candidate: 로컬 네트워크 인터페이스의 주소(같은 LAN 내 연결용)
- Server Reflexive Candidate: STUN을 통해 얻은 공인 IP:포트
- Relayed Candidate: TURN 서버가 할당한 릴레이 주소
ICE는 이 후보들을 상대에게 전달하고(SDP/시그널링), 후보 쌍마다 STUN 연결 검사를 수행합니다. 그런 다음 RFC 8445의 후보·후보 쌍 우선순위와 nomination 절차에 따라 사용할 쌍을 정합니다. 측정된 대역폭이나 장기 안정성을 비교해 경로를 최적화하는 알고리즘은 아닙니다. WebRTC에서는 이 과정이 RTCPeerConnection 설정 중 수행되며, 애플리케이션은 RTCConfiguration.iceServers에 STUN/TURN 서버를 지정합니다.
핵심 흐름 순서
- ① STUN 요청 → 공인 IP:포트 획득
- ② SDP/ICE 후보 → Signaling Server 통해 교환
- ③ ICE 체크 → 최적 경로 선택
- P2P 직접 연결 또는 ④ TURN 릴레이 (Fallback) (클릭 시 연결 흐름 이미지)
WebRTC API 관점에서 정리
MDN WebRTC API 문서에서 강조하는 것처럼, WebRTC는 다음처럼 구성됩니다.
- RTCPeerConnection: 피어 간 연결의 생성·관리
- MediaStream / MediaStreamTrack: 오디오·영상 캡처 및 스트리밍
- RTCDataChannel: 임의 데이터(파일, 채팅 등) 교환
- RTCIceCandidate, RTCSessionDescription: ICE 후보와 SDP를 이용한 시그널링
시그널링(누가 누구에게 어떤 주소·코덱을 쓸지 협상)은 WebRTC 표준 밖에 있으므로, 웹소켓·HTTP 등으로 구현합니다. Agora Web SDK는 이 저수준 시그널링과 채널 연결을 애플리케이션 API 뒤로 감춥니다. Agora의 비공개 내부 경로 선택 구현을 표준 ICE 동작과 동일하다고 단정해서는 안 됩니다.
WebRTC API 요약 코드
아래는 위 네 가지를 브라우저 JavaScript로 다룰 때의 요약 예시입니다. 시그널링(offer/answer·ICE 교환)은 웹소켓 등 별도 채널로 전달한다고 가정합니다.
RTCPeerConnection: 피어 간 연결의 생성·관리
MediaStream / MediaStreamTrack: 오디오·영상 캡처 및 스트리밍
RTCDataChannel: 임의 데이터(파일, 채팅 등) 교환
RTCIceCandidate, RTCSessionDescription: ICE 후보와 SDP를 이용한 시그널링
위 순서(offer → answer → ICE 후보 교환)와 SDP·ICE 후보를 웹소켓 등으로 주고받는 부분이 시그널링이며, WebRTC 표준에는 포함되지 않습니다.
Agora Web SDK를 쓰면? 인프라는 SDK가 처리해 줍니다
네이티브 WebRTC로 화상 통화를 만들면 RTCPeerConnection 생성, offer/answer, ICE 후보 교환, 미디어 트랙 연결을 직접 구현해야 합니다. Agora Web SDK(JavaScript) 는 이 저수준 연결 절차를 join·publish·subscribe API로 추상화합니다. 다만 애플리케이션은 토큰을 백엔드에서 안전하게 발급하고, 권한·트랙·이벤트·재연결 UI를 관리해야 합니다.
Agora Web SDK로 화상 통화 시작하기 (간단 예시)
- RTCPeerConnection, offer/answer, ICE 후보 교환, addTrack/ontrack 같은 코드를 직접 쓸 필요가 없습니다.
- 채널 토큰만 백엔드에서 받아서
join에 넘기면, 나머지 연결·경로 선택은 Agora Web SDK와 서버가 알아서 처리합니다.
실제 동작하는 데모는 RTC 데모에서, 구현 단계는 Agora RTC를 활용한 실시간 화상 통화 구현하기에서 자세히 다룹니다.
실제 Agora RTC를 이용한 화상 통화 구현은 Agora RTC를 활용한 실시간 화상 통화 구현하기 글을 참고하면 됩니다.
관련 글
- #8 왜 P2P가 막히는가 — NAT/STUN/TURN — 이 글의 NAT/STUN/TURN 개념을 한 단계 더 깊이 파고든 후속편
- #9 Agora 기업 방화벽 우회 — Cloud Proxy — STUN/TURN로도 안 뚫리는 엄격한 기업망에서의 우회 전략
- #2 Agora RTC 실시간 화상통화 구현 — 본문의 WebRTC 원리를 Agora SDK로 실제 구현하는 튜토리얼
- #3 RTM 실시간 채팅 시스템 구축 — WebRTC 표준 밖에 있는 시그널링 계층을 다루는 메시징 SDK
- #23 오디오 파이프라인 해부 — Opus/RTP/Jitter Buffer — ICE로 경로가 잡힌 뒤 미디어가 RTP로 실제 흐르는 과정
참고 자료
- WebRTC API - MDN — WebRTC 개념·인터페이스·가이드 종합
- RFC 8489 — Session Traversal Utilities for NAT (STUN) — RFC 5389를 개정한 현행 STUN 표준
- RFC 8656 — Traversal Using Relays around NAT (TURN) — RFC 5766을 개정한 현행 TURN 릴레이 표준
- RFC 8445 — Interactive Connectivity Establishment (ICE) — 후보 수집·연결 체크·경로 선택을 정의한 ICE 표준 (RFC 5245 개정)
- W3C WebRTC 1.0 (RTCPeerConnection 등) — RTCPeerConnection·RTCDataChannel 등 브라우저 API 명세
- Agora RTC Web quickstart — 관리형 Web SDK의 채널 참여·퍼블리시·구독 흐름
실제 데모
/agora-demo/rtc