WebRTC 프로토콜 실시간 통신 | 시그널링·ICE·STUN/TURN·DTLS·SRTP 실전

WebRTC 프로토콜 실시간 통신 | 시그널링·ICE·STUN/TURN·DTLS·SRTP 실전

이 글의 핵심

WebRTC는 UDP 기반으로 ICE·STUN/TURN으로 경로를 찾고, DTLS로 제어·키를 협상하며, SRTP로 미디어를 암호화하는 브라우저 네이티브 실시간 스택입니다.

들어가며

WebRTC(Web Real-Time Communication)는 브라우저와 네이티브 앱에서 플러그인 없이 음성·영상·데이터 채널을 P2P 또는 준-P2P로 제공하기 위한 W3C·IETF 표준 묶음입니다. NAT traversal, 동적 코덱 협상, 암호화된 미디어가 한 스택에 들어 있어 화상 회의, 라이브 스트리밍(저지연), 온라인 게임 보이스, P2P 파일 전송 등에서 널리 쓰입니다.

다만 “브라우저 API 몇 줄” 뒤에는 시그널링 서버, ICE 후보, TURN 비용, 방화벽 정책이 숨어 있습니다. 이 글은 표준 문서·실무 트러블슈팅을 잇는 아키텍처 지도를 목표로 합니다.

멀티미디어 비유로 이해하기

  • 코덱은 원본 영상·음성을 압축·복원하는 장치에 가깝습니다. 대역폭CPU 사이를 조절합니다.
  • 컨테이너(예: RTP 위의 페이로드 포맷)압축된 조각을 시간 순으로 담는 보관함에 가깝습니다. WebRTC는 브라우저 안에서 이 조합을 표준 API로 묶습니다.

왜 WebRTC인가요?

플러그인 없이 브라우저 간 저지연 미디어를 목표로 하며, NAT traversal·암호화·코덱 협상한 스택으로 제공하기 때문입니다. 대규모 방송(HLS 등)과는 역할이 다르고, 인터랙티브에 강합니다.

프로덕션에서 주의할 점

  • TURN대역·비용이 커집니다. 지역 배치·사용량 모니터링 없이 무제한 켜두면 청구가 튈 수 있습니다.
  • 시그널링은 보통 HTTPS/WebSocket이므로, 인증·세션 하이재킹을 서버 측에서 막아야 합니다.
  • 기업망UDP 차단이 흔합니다. TCP/TLS TURN 폴백지연·비용이 커질 수 있어 정책과 함께 설계합니다.

이 글을 읽으면

  • SDP·시그널링·ICE의 역할과 순서(offer/answer)를 설명할 수 있습니다
  • STUN vs TURN, 호스트/서버/릴레이 후보를 구분할 수 있습니다
  • DTLS·SRTP어디에 쓰이는지 개략적으로 그릴 수 있습니다
  • JavaScript·Python·C++에서 시그널링·클라이언트 패턴을 시작할 수 있습니다

목차

  1. 프로토콜 개요
  2. 동작 원리
  3. 실전 프로그래밍
  4. 성능 특성
  5. 실무 활용 사례
  6. 최적화 팁
  7. 흔한 문제와 해결
  8. 마무리

프로토콜 개요

역사 및 개발 배경

WebRTC는 2011년경 Google이 오픈소스로 내놓은 기술을 바탕으로 IETF(RTCWEB WG)W3C에서 표준화되었습니다. VP8/VP9/H.264, Opus, RTP/RTCP, ICE, STUN, TURN, DTLS-SRTP기존 인터넷 프로토콜을 조합해 브라우저 호환 실시간 스택을 완성했습니다. 2026년 현재 모든 주요 브라우저가 핵심 API를 지원하며, iOS Safari도 실무에서 동일 스택으로 맞추는 것이 일반적입니다.

OSI 7계층에서의 위치

엄밀히 단일 레이어로 잘리지 않습니다. 전송(UDP/TCP), 세션·표현(미디어·암호화 협상), 애플리케이션(시그널링)이 함께 묶입니다. 실무에서는 “UDP 위의 RTP+보안+ICE”로 이해하면 운영·디버깅이 쉽습니다.

핵심 특징

특징설명
P2P 우선가능하면 직접 UDP 경로로 미디어를 보냅니다.
NAT traversalICE여러 후보 경로를 시도합니다.
보안DTLS-SRTP로 미디어·키 협상을 보호합니다(브라우저 정책).
저지연TCP 재전송에 묶이지 않도록 UDP+RTP를 기본으로 합니다.
시그널링 분리SDP 교환 방식은 앱이 정함(WebSocket, HTTP, Firebase 등).

동작 원리

시그널링(Signaling)

시그널링SDP(Session Description Protocol)로 코덱·주소 힌트·DTLS fingerprint 등을 교환하는 제어 평면입니다. WebRTC 표준은 특정 전송을 강제하지 않으며, 대부분 HTTPS 또는 Secure WebSocket을 씁니다. 미디어 자체는 시그널링 경로를 타지 않습니다.

ICE(Interactive Connectivity Establishment)

ICE호스트·서버 reflexive(STUN)·릴레이(TURN) 후보를 모아 연결 검사(connectivity checks)를 수행해 최적 경로를 고릅니다. 실패 시 다음 후보로 넘어갑니다.

STUN / TURN

  • STUN: “내가 NAT 밖에서 보이는 주소·포트는?”을 알려줍니다. 직접 연결에 성공하면 추가 비용이 거의 없습니다.
  • TURN: 대칭 NAT·방화벽 등으로 P2P가 불가할 때 서버가 미디어를 중계합니다. 대역폭·비용이 커지므로 최소화가 운영 핵심입니다.

DTLS

DTLS(Datagram TLS)는 UDP 위에서 TLS와 유사한 핸드셰이크를 수행합니다. 데이터 채널(SCTP over DTLS)키 재료 협상에 관여합니다.

SRTP

SRTP(Secure RTP)RTP 페이로드·헤더를 암호화·무결성 보호합니다. 시그널링에 실리는 fingerprint·SDP 속성DTLS 교환을 통해 연결됩니다(구현 세부는 브라우저·스택에 따름).

sequenceDiagram
  participant A as Peer A
  participant Sig as Signaling (HTTPS/WS)
  participant B as Peer B
  participant S as STUN/TURN
  A->>Sig: SDP offer
  Sig->>B: forward offer
  B->>Sig: SDP answer
  Sig->>A: forward answer
  A->>S: ICE binding / allocate
  B->>S: ICE binding / allocate
  A-->>B: ICE connectivity checks (UDP)
  Note over A,B: DTLS handshake, SRTP media

실전 프로그래밍

JavaScript (브라우저, 수동 SDP 교환 데모)

동일 기기·두 탭에서 시그널링을 복사-붙여넣기로 대체한 최소 학습용 예입니다. 실서비스는 시그널링 서버로 바꿉니다.

아래 HTML 골격스크립트를 한 파일로 합치면 됩니다(</script>가 마크다운/HTML 파서와 충돌하지 않도록 분리해 적습니다).

<!DOCTYPE html>
<html>
<head><meta charset="utf-8"><title>WebRTC minimal</title></head>
<body>
  <h3>Peer A</h3>
  <button id="aGo">A: create offer</button>
  <pre id="aOffer"></pre>
  <textarea id="aPasteAnswer" rows="6" cols="80" placeholder="Paste answer SDP here"></textarea>
  <button id="aApply">A: set answer</button>

  <h3>Peer B</h3>
  <textarea id="bPasteOffer" rows="6" cols="80" placeholder="Paste offer SDP here"></textarea>
  <button id="bApplyOffer">B: set offer &amp; create answer</button>
  <pre id="bAnswer"></pre>
  <script src="webrtc-demo.js"></script>
</body>
</html>
// webrtc-demo.js — 위 HTML과 같은 디렉터리에 저장
const cfg = { iceServers: [{ urls: "stun:stun.l.google.com:19302" }] };

const pcA = new RTCPeerConnection(cfg);
const pcB = new RTCPeerConnection(cfg);

pcA.onicecandidate = (e) => {
  if (!e.candidate) console.log("A ICE gathering done");
};
pcB.onicecandidate = (e) => {
  if (!e.candidate) console.log("B ICE gathering done");
};

pcA.ontrack = (e) => console.log("A got track", e.streams[0]);
pcB.ontrack = (e) => console.log("B got track", e.streams[0]);

document.getElementById("aGo").onclick = async () => {
  pcA.addTransceiver("video", { direction: "recvonly" });
  const offer = await pcA.createOffer();
  await pcA.setLocalDescription(offer);
  document.getElementById("aOffer").textContent = offer.sdp;
};

document.getElementById("bApplyOffer").onclick = async () => {
  const sdp = document.getElementById("bPasteOffer").value;
  await pcB.setRemoteDescription({ type: "offer", sdp });
  pcB.addTransceiver("video", { direction: "recvonly" });
  const answer = await pcB.createAnswer();
  await pcB.setLocalDescription(answer);
  document.getElementById("bAnswer").textContent = answer.sdp;
};

document.getElementById("aApply").onclick = async () => {
  const sdp = document.getElementById("aPasteAnswer").value;
  await pcA.setRemoteDescription({ type: "answer", sdp });
};
  • 카메라 없이 recvonly만 올려 경로 협상 흐름을 볼 수 있습니다. 실제 영상은 **getUserMedia**로 트랙을 추가합니다.
  • SDP 교환만으로는 ICE 후보가 SDP에 포함되도록 trickle ICE 설정을 맞춰야 할 수 있습니다(운영에서는 시그널링으로 candidate JSON을 주고받는 패턴이 흔합니다).

Python (aiortc, 서버·자동화 테스트)

#!/usr/bin/env python3
# pip install aiortc aiohttp
import asyncio
import json
from aiortc import RTCPeerConnection, RTCSessionDescription
from aiohttp import web

async def offer(request):
    params = await request.json()
    offer_desc = RTCSessionDescription(sdp=params["sdp"], type=params["type"])
    pc = RTCPeerConnection()
    # 실무: 트랙 추가, datachannel 등
    await pc.setRemoteDescription(offer_desc)
    answer = await pc.createAnswer()
    await pc.setLocalDescription(answer)
    return web.json_response(
        {"sdp": pc.localDescription.sdp, "type": pc.localDescription.type}
    )

app = web.Application()
app.router.add_post("/offer", offer)
web.run_app(app, port=8080)
  • aiortc테스트 헤드리스, SFU 일부, 서버 사이드 녹화 등에 쓰입니다. 프로덕션 SFUJanus, mediasoup, LiveKit 등을 검토합니다.

C++ (시그널링·미디어 분리 관점)

브라우저 외 C++ 네이티브libwebrtc(대형) 또는 libdatachannel, GStreamer webrtcbin 등을 씁니다. 실행 가능한 최소 단위로는 시그널링만 C++으로 두고 미디어는 브라우저/모바일 SDK에 맡기는 구성이 흔합니다. 예: WebSocket++ / Boost.Beast로 SDP 문자열을 중계하는 서버(HTTPS/TLS는 리버스 프록시와 병행).

// 개념: 시그널링 서버가 offer/answer JSON을 중계 (의사코드)
// 실제로는 JSON 파싱·룸 ID·인증·세션 수명 관리 필요
void relay_sdp(const std::string& from_peer, const std::string& sdp_json) {
  // Redis pub/sub, WebSocket broadcast, DB 저장 등
}

에러 처리·타임아웃

  • **iceconnectionstate / connectionState**를 구독해 failed재시도·TURN 전환을 유도합니다.
  • 시그널링HTTP 5xx, WS 끊김에 대비해 지수 백오프 재연결을 둡니다.

성능 특성

지연 시간(Latency)

P2P 직접 경로가 잡히면 엔드투엔드 지연SFU 한 홉보다 유리한 경우가 많습니다. TURN 릴레이지리적으로 먼 서버를 쓰면 RTT가 증가합니다.

처리량(Throughput)

대역폭 적응(congestion control, GCC 등)수신 RTCP 피드백을 바탕으로 비트레이트를 조절합니다. simulcast여러 해상도를 동시에 보내 구독자 네트워크에 맞게 선택하게 합니다.

오버헤드

UDP+RTP 헤더, SRTP, RTCP, ICE keepalive가 더해집니다. TURN서버 CPU·대역 오버헤드가 큽니다.

벤치마크 참고

동일 회선에서도 코덱·해상도·패킷 손실에 따라 체감 품질이 크게 달라집니다. 실측Chrome webrtc-internals, 원격 로그의 RTT·jitter·packetsLost로 확인합니다.


실무 활용 사례

화상 회의

Zoom/Meet/Teams류는 내부적으로 전용 인프라·SFU를 쓰는 경우가 많지만, 브라우저 SDK 노출부는 WebRTC 표준 API와 맞춥니다.

P2P 파일 공유

데이터 채널(SCTP/DTLS)파일 청크 전송을 구현합니다. 대용량이면 동시성·재전송·백프레셔를 앱에서 설계합니다.

라이브 스트리밍

저지연 인터랙티브에는 WebRTC가 적합하고, 대규모 일방향 방송HLS/DASH역할 분담이 흔합니다(하이브리드 아키텍처).


최적화 팁

TURN 최소화

  • 지역별 TURN을 가깝게 배치합니다.
  • UDP가 막히면 TCP/TLS TURN 폴백이 지연·비용을 키울 수 있어 네트워크 정책과 함께 봅니다.

대역폭 적응

  • GCC(구글 혼잡 제어) 등 구현체에 의존하지만, 송출 측 캡(max bitrate)·프레임레이트앱에서 제한하면 안정성이 좋아집니다.

Simulcast

  • 다양한 단말이 동시에 참여하면 simulcast + SFU불필요한 대역 낭비를 줄입니다.

흔한 문제와 해결

흔한 실수와 해결

실수결과해결
시그널링만 HTTPS인 줄 알고 미디어까지 보호됐다고 가정시그널링과 미디어 경로는 분리DTLS-SRTP·TURN 자격 증명을 별도 검증
STUN만 켜고 TURN을 안 둠대칭 NAT 등에서 연결 실패TURN을 운영·비용 포함해 설계
ICE 실패 시 원인 없이 재시도만사용자 무한 로딩iceconnectionstate·통계로 원인 분류
개발망에서만 테스트실제 사용자는 방화벽 뒤기업망·모바일 시나리오 포함

NAT traversal 실패

  • 대칭 NAT, 엔터프라이즈 방화벽에서 직접 연결 불가TURN 필수입니다.
  • mDNS 로컬 후보만 보이는 경우 VPN·서브넷 설정을 확인합니다.

방화벽 이슈

  • UDP 차단이면 TURN over TLS정책 허용 포트로 우회합니다(비용·지연 증가).
  • 기업 프록시WebSocket 시그널링도 막을 수 있어 443만 허용 설계를 검토합니다.

보안·준수

  • TURN 자격 증명단기 크리덴셜 패턴이 일반적입니다.
  • 녹화·감사 요구가 있으면 미디어 경로 설계(SFU 녹화 등)를 별도로 잡습니다.

마무리

핵심 요약

  • WebRTC는 시그널링(보통 TCP) + ICE + UDP 미디어 + DTLS/SRTP의 조합입니다.
  • STUN은 가능한 직접 연결, TURN은 최후의 릴레이로 이해하면 운영 비용이 보입니다.
  • 브라우저 이벤트·RTC 통계지연·손실을 계측하는 습관이 중요합니다.

추천 사용 시나리오

  • 브라우저 간 실시간 음성·영상·데이터에는 WebRTC가 사실상 표준입니다. 전송 계층 기초는 TCP 가이드·UDP 가이드와 연결해 읽으면 전체 그림이 선명해집니다.