Getting Started with WebRTC 정리 02

This post is a summary of the book Rob Manson’s Getting Started with WebRTC


A More Thechnical Introduction to Web-based Real-Time Communication

이 장에서는 새로운 Web 기반 실시간 통신(WebRTC)의 기술적인 컨셉에 대해 설명한다.

통신 설정하기 (setting up)

WebRTC 통신의 기초는 peer-to-peer 이지만, 이 통신의 설정(settint up)을 시작하기 위해서는 약간의 조정이 필요하다.
이는 주로 웹 서버와/또는 시그널링 서버가 제공한다.
이를 통해 2개 이상의 WebRTC가 가능한 디바이스나 peer들이 서로를 찾고, 상세 연결 정보를 교환하고, 어떻게 peer들이 통신할지를 정의하는 세션을 협상(negotiate)한다.
그리고 이제 마지막으로 peer들 사이의 직접적인 peer-to-peer 미디어 스트림이 성립(establish)된다.

일반적인 흐름

아래는 두 브라우저가 단순한 WebRTC를 사용하여 비디오 통화를 설정할 때 할 때의 일반적인 흐름의 요약이다.

  • 사용자들을 연결한다.
  • 시그널을 시작한다.
  • 후보자들(candidates)을 찾는다.
  • 미디어 세션을 협상한다.
  • RTCPeerConnection 스트림을 시작한다.

사용자 연결

이 프로세스의 가장 처음 단계는 두 사용자가 어떻게든 연결하는 것이다.
가장 단순한 방법으로는 두 사용자가 같은 웹사이트를 들어가는 것이다.
이 페이지는 각 브라우저를 식별하고 WebSocket API 등을 사용하여 공유된 시그널링 서버에 연결시킬 수 있다.
이런 웹페이지는 주로 두 브라우저 사이에 통신을 연결하기 위해 사용되는 unique 토큰을 할당한다.
첫 번째 사용자가 웹페이지로부터 받은 unique 토큰이 포함된 unique URL을 두 번째 사용자에게 보내면, 둘이 서로 같은 URL을 접속하면 첫 번째 단계는 완료된다.

시그널 시작

이제 두 사용자가 토큰을 공유하고 있고, WebRTC 연결을 설정을 협상하는 시그널링 메시지를 교환할 수 있다.
이 컨텍스트 내에서, 시그널링 메시지는 단순한 통신의 어느(any) 형식으로, 두 브라우저가 WebRTC 연결을 성립(establish)하고 제어(control)하는 것을 도와준다.
WebRTC는 정확하게 이를 정확히 정의해놓지 않았기 때문에 XHR polling, Server-Send Events, 웹소켓, 또는 여러 조합들을 통해 개발자가 편한 방식으로 구현할 수 있다.

후보자들(candidates) 찾기

다음 단계는 두 브라우저가 자신의 네트워크와 어떻게 접근할 수 있는지에 대한 정보를 교환하는 것이다.
이 과정은 주로 후보자들 찾기(finding cadidates)로 설명되며,
결국에 각 브라우저는 직접 접근할 수 있는 네트워크 인터페이스와 포트에 매핑되어야한다.

각 브라우저는 아마 NAT(Network Address Translation)를 사용하는 라우터 뒤에 있을 것이다.
이 라우터를 통해 연결 방법을 찾는 방법은 NAT Traversal이라고 알려져 있고, WebRTC 통신을 성립할 때 매우 중요하다.

NAT Traversal의 일반적인 방법은 STUN(Session Traversal Utilities for NAT) 서버를 사용하는 것이다.
STUN 서버는 public 인터넷으로부터 어떻게 접근하는지를 식별하고 유용한 형식(useful form)으로 이 정보를 돌려준다.

만약 STUN 서버가 public 인터넷으로 부터 브라우저로 접속할 수 있는 방법을 찾지 못할 경우,
TURN(Traversal Using Relay NAT) 서버와 같은 미디어 중계(realy) 솔루션을 사용하는 옵션 밖에 없다.

WebRTC에서는, 이 전체 과정이 주로 하나의 ICE(Interactive Connectivity Establishment) framework로 묶여있다.
ICE framework는 STUN 서버로 접속과 필요할 때 TURN 서버로 전환(falling back)하는 것을 다룬다.

미디어 세션 협상

이제 두 브라우저는 어떻게 서로에게 통신할 지를 알고 있다.
이들은 오디오나 비디오 같은 미디어의 타입과 형식(format)을 동의해야만 하고,
이들은 코덱, 해상도, 비트레이트 등을 교환할 것이다.
이는 주로 SDP(Session Description Protocol) 위에서 만들어진 offer/answer 기반의 모델을 사용해서 협상된다.
이는 JSEP(JavaScript Session Establishment Protocol)으로 정의되어있다.

RTCPeerConnection 스트림 시작

위 과정이 완료되면, 브라우저들은 직접 peer-to-peer 연결이나 fall back 용으로 사용하는 어느 media realy gateway를 통해서 드디어 서로에게 미디어 스트리밍을 시작한다.

이 단계에서, 브라우저들은 같은 WebRTC 통신을 제어하기 위한 통신 공유용 시그널링 서버 솔루션을 계속 사용할 수 있다.
혹은 서로 이를 직접하기 위해 특정한 타입의 WebRTC 데이터 채널을 사용할 수 있다.

웹소켓 사용하기

WebSocket API는 웹 애플리케이션에서 양방향 통신을 쉽게 사용할 수 있게해주었다.
WebSocket API의 주요 장점은 메시징이 양방향에 빠르고 가볍다는 것이다.
XHR polling/long-polling 모델과는 달리 지연이나 지속적인 네트워크 트래픽이 없고
이는 WebRTC 통신을 설정하기 위해 필요한 offer/answer dance에 있어 이상적이다.

다른 시그널링 옵션

브라우저들이 서버를 통해 메세지를 주고 받을 수 있는 그 어떤 접근 방법이라도 WebRTC 시그널링에 사용될 수 있다.

가장 간단한 모델은 XHR API를 사용하여 새로운 메세지를 가져오기 위해 주기적으로 서버에 polling하는 것이다.
하지만 이는 많은 문제점이 있는데, 각 polling 사이클의 주기에 따라 딜레이가 있고,
또한 메세지가 없어도 polling을 반복함으로써 네트워크 대역폭을 낭비한다.

polling 기반의 약간 더 세련된 접근법은 long-polling이다.
만약 새로운 메세지가 없다면, HTTP 1.1 keep-alive 메카니즘을 사용하여 네트워크 접속은 메세지가 있을 때까지 계속 살아있는다.
서버가 새로운 정보가 있다면, 이를 클라이언트에게 보내게되고 요청이 완료된다.
이를 통해 네트워크 polling 오버헤드가 줄어든다.
하지만 여전히 웹소켓과 같은 모던한 해법들에 비해선 오래되고 비효율적인 방식이다.

또다른 옵션으로는 Server-Sent Event가 있다.
이를 통해 서버가 클라이언트에게 직접 메세지를 보낼 수 있고, 클라이언트는 메세지가 발생하자마자 이를 받을 수 있다.
메세지를 서버에 보내기 위해 XHR과 같은 별도의 채널을 사용해야한다.
이는 두 개의 나뉘어진 채널들을 관리하고 동기화해야한다는 것이다.
이 조합은 쓸만하지만, 이 역시 웹소켓과 같은 진정한 양방향 채널의 우아함을 갖진 않는다.

MediaStream API

MediaStream API는 이를 통해 카메라나 마이크로폰 같은 로컬 입력 디바이스들로부터 미디어 스트림에 접근하도록 설계되었다.
초기에는 getUserMedia API에 초점이 맞춰져 있었지만, 현재는 boarder media capture and streams API 또는 짧게 MediaStream API로 규격화되어있다.
하지만 getUserMedia() 메서드는 여전히 로컬 입력 디바이스에 접근을 시작하기 위한 중요한(primary) 방법이다.

각 MediaStream 객체는 다른 입력 미디어를 가리키는 다양한 MediaStreamTrack 객체들을 가질 수 있다.
각 MediaStreamTrack은 여러 채널을 가질 수 있으며(왼쪽, 오른쪽 오디오 채널과 같이) 이 채널들은 MediaStream API에서 정의된 가장 최소 단위이다.

MediaStream 객체는 두 가지 방식으로 출력이 될 수 있다.

  1. <video><audio>와 같은 MediaElement에 출력을 보여주기(render) 사용될 수 있다.
  2. 외부 peer에게 이 media stream을 보낼 수 있는 RTCPeerConnection에 보내기 위해 사용될 수 있다.

MediaStreamTrack은 MediaSourceStates로 표현되는 객체로 많은 상태로 나타내질 수 있다.
또한 MediaStreamTrack은 capabilities() 메서드를 통해 다양한 capabilities를 제공한다.

RTCPeerConnection API

RTCPeerConnection API는 WebRTC가 가능한 브라우저와 peer 사이의 peer-to-peer 연결에서 가장 중요하다.
RTCPeerConnection 객체는 각 클라이언트에 따라(caller냐 callee냐에 따라) 약간 다른 방식으로 사용된다.

Caller의 흐름(flow)

RTCPeerConnection이 생성된 후 caller의 흐름은 아래와 같다.

  • onicecandidate handler 등록
    먼저 시그널링 채널들 중 하나를 사용하여 받은 ICE candidates를 다른 피어에게 보내기 위해 onicecandidate handler를 등록해야한다.

  • onaddstream handler 등록
    다음, 외부 피어로 부터 받은 video stream 화면에 보여주기 위해 onaddstream handler를 등록한다.

  • message handler 등록
    시그널링 채널은 다른 피어로부터 받은 메세지를 응답하기 위해 등록된 핸들러를 갖고 있어야한다.

  • 로컬 카메라에 접근하기 위해 getUserMedia 사용
    로컬 media stream를 설정하고 로컬 페이지에 표시하고 또, 이를 addStream() 메서드를 사용하여 RTCPeerConnection 객체에 추가하기 위해, getUserMedia()를 사용할 수 있다.

  • JSEP offer/answer 처리
    이제, createOffer() 메서드를 사용하고, RTCSessionDescription 객체를 받는 콜백 handler를 등록을 하여 협상을 시작할 준비가 되었다.
    그리고 드디어, RTCSessionDescription을 시그널링 채널을 통해 외부 피어로 보낸다.

Callee의 흐름(flow)

callee는 caller와 매우 비슷하지만, offer를 answer하는 부분이 다르다.

  • onicecandidate handler 등록
    caller와 같이 onicecandidate handler를 등록함으로서 시작한다.

  • onaddstream handler 등록
    caller와 같다.

  • meessage handler 등록
    caller와 같다.

  • 로컬 카메라에 접근하기 위해 getUserMedia 사용
    caller와 같다.

  • JSEP offer/answer 처리
    caller와 같지만, caller로 부터 offer를 받은 이후 callee의 흐름(flow)가 시작된다는 것이 중요하다.

RTCPeerConnection은 어디에 위치할까?

아래 다이어그램은 WebRTC 아키텍쳐이다.
이처럼 RTCPeerConnectionAPI 밑에 아래 처럼 복잡한 레이어들이 숨겨져있다.

RTCDataChannel API

WebRTC를 사용하여 피어들간 미디어 스트림을 보낼 때 뿐만 아니라,
임의의 데이터 스트림을 보내기 위해 DataChannel API를 사용하는 것도 가능하다.
많은 사람들이 주로 이를 RTCDataChanenel API라 언급하지만, 정확히는 WebRTC DataChannel API이다.
이는 send() 메서드와 onmessage 이벤트를 통해 웹소켓과 유사하도록 설계된 매우 유연하고 강력한 솔루션이다.

Share