
먼저 WebRTC가 무엇인지 정의해 보겠습니다.
WebRTC는 두 브라우저 간에 오디오 및 비디오와 같은 데이터를 교환하기 위해 피어 투 피어 연결을 설정할 수 있도록 하는 JavaScript API 세트입니다. 이를 통해 오디오 및 비디오 통화 기능을 갖춘 애플리케이션을 개발할 수 있습니다.
WebRTC의 특별한 점은 연결이 수립되면 서버를 거치지 않고 브라우저 간에 데이터를 실시간으로 직접 전송할 수 있다는 것입니다. 서버를 우회함으로써 데이터가 먼저 서버로 전송될 필요가 없기 때문에 지연 시간을 줄일 수 있으며, 이는 WebRTC가 오디오 및 비디오 교환에 매우 적합하게 만듭니다.
전체 동영상 강좌: “WebRTC는 어떻게 작동하나요? | 기본 강좌”
WebRTC Vs WebSockets
이 모든 것이 어떻게 작동하는지에 대해 논의하기 전에, WebRTC와 WebSockets의 비교를 살펴보겠습니다. 왜냐하면 많은 분들이 “이건 WebSockets와 매우 비슷해 보이는데, 왜 WebRTC가 필요한 걸까?”라고 생각하시거나, 반대로 생각하시는 분들도 있을 테니까요.

웹소켓을 사용하면 피어 간에 실시간으로 데이터를 교환하기 위해 연결을 설정할 수 있지만, 이 연결은 클라이언트와 서버 사이에서 이루어집니다. 따라서 피어에게 메시지를 전송하면 해당 메시지는 먼저 서버로 전송되며, 서버는 그 메시지를 다른 피어에게 전송합니다. 이 교환은 일반적으로 매우 빠르게 이루어지기 때문에, 채팅 메시지나 알림과 같은 것을 전송할 때 지연 시간이 있더라도 아마도 이를 알아차리지 못할 것입니다.
이제 웹소켓을 사용하여 오디오나 비디오를 교환하고 싶다고 가정해 보겠습니다. 결국 이는 가능합니다.
여기서의 문제는 오디오와 비디오에 있어서 가장 작은 지연이라도 매우 눈에 띄게 느껴지고 많은 문제를 일으킬 수 있다는 점입니다. 따라서 비디오 데이터가 서버에 도착하고 다시 피어로 돌아올 때까지 상당한 지연이 발생하게 됩니다.
여기서 웹RTC가 유용합니다. 두 브라우저 간 연결을 설정하고 데이터를 교환함으로써 서버가 추가할 수 있는 지연을 제거합니다. 웹RTC는 사용자 데이터그램 프로토콜(UDP)을 사용하는데, 이는 데이터를 매우 빠르게 전송하는 데 적합하지만 이에 대해稍후에 자세히 설명하겠습니다.
webRTC 그렇게 빠르다면 왜 웹소켓에를 사용할까요?
웹RTC에는 특정 제한 사항이 있으므로 일반적으로 웹RTC와 웹소켓을 함께 사용하는 것이 더 일반적인 관행입니다.
먼저, webRTC는 UDP를 사용하며, UDP는 중요한 데이터를 전송하는 데 신뢰할 수 있는 프로토콜이 아닙니다. UDP는 데이터를 매우 빠르게 전송하는 데는 우수하지만, 데이터가 수신되었는지 여부를 확인하지 않습니다. 따라서 UDP는 비디오 전송에 적합합니다. 데이터가 빠르게 도착하고 몇 프레임을 잃더라도 큰 문제가 되지 않기 때문입니다. 하지만 이가 전송해야 할 파일이라면 데이터의 몇 바이트를 잃어도 전체 파일이 손상될 수 있습니다.
WebRTC에는 내장된 신호 전송 기능이 없기 때문에 단독으로 피어 투 피어 연결을 설정하는 데 사용할 수 없습니다. WebRTC는 연결이 설정된 후에는 모든 것을 처리해 주지만, 두 피어를 연결하기 위해 초기 데이터를 전송하는 방법은 사용자에게 맡겨집니다.
그래서 이 모든 것이 어떻게 작동하는 건가요?

고수준 관점에서 보면, 연결을 설정하기 위해 피어 1은 피어 2에게 다음과 같은 메시지를 전송합니다. “안녕하세요, 저는 당신과 연결하고 싶습니다. 제 정보와 당신께서 저와 연결하는 방법에 대한 정보를 제공합니다. 제 제안을 수락하시겠습니까?”
이 메시지가 어떻게 전송되는지는 중요하지 않습니다. 이 메시지는 이메일, 트윗일 수도 있고, 또는 피어 2에게 전달할 수도 있습니다. 어떤 방식이든 상관없으며, 그 부분은 귀하의 선택에 달려 있습니다.
피어 2가 피어 1로부터 이 정보를 받으면, 연결을 수락할 기회를 얻게 됩니다. 피어 2가 연결을 수락하면, 자신의 네트워크에 대한 정보와 해당 네트워크에 연결하는 방법을 수집한 후, 이 정보를 피어 1에게 다시 전송합니다.
양측의 피어들이 서로의 정보를 교환하면 이제 연결이 완료되며, 서버를 통해 전달할 필요 없이 브라우저 간에 직접 오디오 및 비디오 데이터나 원하는 다른 데이터를 전송할 수 있게 됩니다.
두 클라이언트 사이에 정확히 어떤 데이터가 전송되며, 어떻게 전송되는 것일까요?
먼저, 정보가 전송되는 방식은 일반적으로 '신호 전송'이라는 과정을 통해 이루어집니다. 두 노드가 서로를 알지 못하기 때문에, 일반적으로 WebSockets나 제3자 신호 전송 서비스를 사용하여 두 노드를 채널에 함께 연결하는 방법을 사용합니다.
그들을 동일한 채널이나 방으로 이동시키면, 이제 그들은 연결 세부 정보를 전송할 수 있습니다. 이 연결 세부 정보는 세션 설명 프로토콜(SDP)과 ICE 후보 형태로 제공됩니다.
SDP — 세션 설명 프로토콜(SDP)은 코덱, 주소, 미디어 유형, 오디오 및 비디오 등과 같은 세션 연결에 대한 정보를 포함하는 객체입니다. 양측은 서로 연결하는 방법을 이해하기 위해 SDP를 교환합니다. 하나는 SDP Offer 형태로, 다른 하나는 SDP Answer 형태로 교환됩니다.
ICE 후보 — ICE 후보는 데이터 수신 주소로 사용될 수 있는 공용 IP 주소와 포트입니다. 각 사용자는 일반적으로 STUN 서버에 대한 일련의 요청을 통해 수집된 여러 개의 ICE 후보를 갖게 됩니다.

따라서 다음과 같은 순서로 일이 진행될 것입니다.
먼저 두 노드는 어떤 신호 전송 방법을 통해 SDP를 교환합니다. 두 SDP가 교환되면 노드들은 이제 연결되지만, 아직 데이터를 전송할 수 없습니다.
두 피어 간에 데이터를 교환하려면 여전히 데이터를 전송해야 합니다. 여기서 문제는 현재 대부분의 기기가 방화벽과 NAT 장치 뒤에 위치해 있다는 점입니다. 따라서 공개 IP 주소를 발견하기 위해 ICE(Interactive Connectivity Establishment)라는 방법을 사용합니다.
SDP 제안이 교환되면 각 피어는 STUN 서버에 일련의 요청을 보내게 되며, 이 서버는 사용하기 위한 ICE 후보 목록을 생성합니다. STUN 서버는 비용이 저렴하고 유지보수가 쉽기 때문에, 무료로 사용할 수 있는 서비스가 매우 많기 때문에 별도로 서버를 설정할 필요가 없습니다.
피어 1이 STUN으로부터 ICE 후보를 수신하면 이를 피어 2로 전송하고 네트워크가 가장 적합한 후보를 결정하도록 합니다. 피어 2도 동일한 과정을 반복하여 자신의 ICE 후보를 요청한 후 이를 피어 1로 전송합니다.
이 후보들이 교환되고 최적의 경로가 발견되면 두 피어 간에 데이터가 흐르기 시작할 수 있습니다.
점차적으로 증가하는 ICE 후보자
아이스 후보를 검색하는 과정에는 한 가지 문제가 있습니다. 바로 이 과정이 시간이 많이 소요될 수 있다는 점입니다. 따라서 이 문제를 해결하기 위해 일반적으로 “Trickle ICE”라는 방법을 사용합니다. 이 방법은 STUN 서버로부터 각 아이스 후보를 수신할 때마다 단순히 하나씩 차례로 전송하는 것을 의미하며, 이로 인해 아이스 후보들이 “점차적으로 유입된다”는 의미입니다.
실제로 작동하는 모습을 보는 것
SDP 전송 프로세스가 신호 서버 없이 어떻게 작동하는지 확인하실 수 있도록 라이브 데모를 준비했습니다. 이 라이브 데모를 통해 두 개의 탭을 옆에 나란히 열고, 두 피어 간에 SDP 제안과 응답을 생성하고 전송하는 과정을 체험하실 수 있습니다. ICE 후보에 대한 Trickling 처리를 따로 처리할 필요가 없습니다. 왜냐하면 ICE 후보는 SDP 제안 생성 시 자동으로 추가되기 때문입니다.
여기에서 라이브 데모를 확인할 수 있습니다.