WebRTC

2022. 10. 6. 16:11코딩

WebRTC (Web Real Time Communication) 은 웹 애플리에키션과 사이트가 중간자 없이 브라우저 간에 오디오나 영상 미디어를 잡고 마음대로 스트림할 뿐 아니라,
임의의 데이터도 교환할 수 있도록 하는 기술입니다.
별도의 플러그인이나 소프트웨어 설치 없이 브라우저에서 지원하는 기술들을 사용해서 데이터 공유와 화상 회의를 가능하게 만듭니다.
구글에서 공유한 웹 기반 커뮤니케이션 라이브러리 라고 생각하면 쉽습니다.

P2P (peer to peer) 란 무엇인가?

보통의 웹사이트나 여러가지 서비스는 인터넷을 통해 중앙서버에 접속하여 데이터를 받는 방식인데, P2P는 상대방의 컴퓨터가 서버의 역할을 대신 해준다~ 라고 생각하시면 편할 것 같습니다.
그래서 개인 컴퓨터들이 네트워크로 연결되어 서로 정보와 자료를 공유하는 것을 말합니다.

그래서 이것이 왜 등장했는가?

WebRTC 이전에는 Server가 중간자 역할을 했는데, 사용자 간 통신의 모든 부하를 서버가 떠맡는 구조이기 때문에 확장과 유지하기가 비쌉니다.

그래서 다른 방법으로 중간자 역할이 없이 사용자 대 사용자로 연결을 하여 좀 더 비용을 싸게 먹히게 하는 구조로 만들게 되었습니다.

데이터를 공유한다고 하니 이제 생각 나는 것이 하나 있을텐데.. 아마도 WebSocket 이라고 생각합니다.

WebSocket도 알아보면 영상을 주고 받을 수 있는데 왜 Web RTC를 사용하나 싶을 수 있습니당..

3가지 특징으로 얘기를 할 수 있는데

  • 첫 번째, web rtc는 영상, 오디오, 임의의 데이터 통신이 high performance, high quality이도록 설계되어 있습니다.
  • 두 번째, webrtc는 브라우저 간 직접 통신이여서 웹소켓에 비해 훨씬 빠릅니다,
  • 세 번째, webrtc의 지연시간이 훨씬 짧습니다.

그러면 webrtc는 websocket을 사용을 안하는가 라는 의문을 가질 수 있는데.. 사용합니다! webrtc가 p2p 연결을 통해 직접 통신하지만 심각한 부하를 받을 수 있기 때문에 websocket 혹은 socket.io를 사용하여 Signaling 서버가 필요합니다.

WebSocket 통신방식

sequenceDiagram
    participant ClientA
    participant Server
    participant ClientB
    Note right of ClientA : Server에게 메시지 전달
    ClientA->>Server: Hi
    Note right of Server : ClientB에게 메시지 전달
    Server->>ClientB: Hi

WebRtc 통신방식

sequenceDiagram
    participant Server
    participant ClientA
    participant ClientB
    ClientA->>ClientB: Hi
    Note left of Server : 문제 발생 시에만 서버 연결

이걸 어디서 사용하지 ?

현재 이 내용을 발표하고 있는 Google Meet, Zoom 에서도 이 Web RTC를 이용하여 화상회의 기능을 구현하였습니다.

그리고 이 기술에 대해 좀 더 알아야 하는 점이 있는데, 아래에 정리해보도록 하겠습니다.

Signaling

누가 누군가를 부를 때, 그걸 중재하는 서버가 Signaling Server라고 하며, 통신할 때 어떤 종류의 통신을 원하는지 의 정보를 같이 전송합니다.
서로 통신에 OK 사인을 보내게 되면, Signaling Server를 통해서 자신의 IP 주소를 교환하는 방식으로 이루어져 있습니다.

쉽게 설명하면 약속 잡기

Stun

보통 public IP인 공유기에는 여러 private IP 주소가 내부적으로 라우팅 되어 있습니다. 예를 들어 한 공유기에 연결된 핸드폰과 노트북은 서로 다른 private IP를 사용하고 있습니다.
여기서, private IP를 할당 받은 상태에서는 자신의 public IP주소를 모르는데, 이 상태에서 다른 사람과 통신하려면 디바이스에서 자체적으로 자신의 public IP주소를 알고 있어야 합니다.
이걸 가능하게 만들어주는 친구가 Stun Server 입니다.

쉽게 설명하면 어디서 만날까 정하기

Turn

public ip간 연결을 테스트 해보고 연결이 가능하면 클라이언트들은 P2P 연결이 된 것인데, 만약 연결이 실패한다면 인터넷 상의 중계 서버를 사용해야 합니다.
이때 사용하는 서버가 TURN 서버 입니다.

쉽게 설명하면 특정 약속 장소 잡기

WebRTC를 구성하는 프로토콜

자 이제 이 WebRTC를 구성하는 프로토콜에 대해 알아보겠습니다.

크게 4가지 단계를 거쳐서 동작하게 되는데, 각각의 단계마다 사용하는 프로토콜이 다릅니다.

  1. Signaling
    • SDP (Session Description Protocol)
  2. Connecting
    • ICE (Interactive Connectivity Establishment)
  3. Securing
    • DTLS (Datagram Transport Layer Security)
    • SRTP (Secure Real-time Transport Protocol)
  4. Communicationing
    • RTP (Real-time transport Protocol)
    • SCTP (Stream Control Transmission Protocol)
    • RTCP (Real-time Transport Control Protocol)

Signaling

SDP - Session Description Protocol

이름 그대로, Session 의 Description을 담당하는 프로토콜 입니다.

  • 생성할 세션의 타입 정보를 전송합니다.

처음에 A가 B에게 통신 요청을 하는 걸 offer, B가 응답하는 걸 Answer라고 합니다.

  • offer 에는 통신 종류가 video / audio인지, 인코딩에는 어떤 방식을 사용할 것인지, ip주소값 등의 정보가 들어 있습니다.
  • 이 정보를 서로 교환해야만 통신이 가능합니다.

일반적으로 Web에서는 Json 을 사용해 통신하지만, SDP는 key=value 형태로 데이터를 전송하며 아래의 7가지 key 값만 사용할 수 있습니다.

  • v : Version
  • o : Origin
  • s : Session Name
  • t : Timing
  • m : Media Description
  • a : Attribute
  • c : Connection Data

Session Description Protocol

sequenceDiagram
    participant ClientA
    participant ClientB
    Note left of ClientA : create offer
    Note left of ClientA : register offer to LocalDescription
    ClientA->>ClientB: send offer to CB
    Note right of ClientB : register offer to RemoteDescrption
    Note right of ClientB : create answer
    Note right of ClientB : register answer to LocalDescription
    ClientB-->>ClientA: send answer to CA
    Note left of ClientA : register answer to RemoteDescription
    ClientA->>ClientB: exchange ice candidate
    ClientB-->>ClientA:

Connecting

ICE - Interactive Connectivity Establishment

peer connection을 담당하는 프레임워크 입니다. 일반적으로 peer connection이 필요한 경우는 크게 세 가지 입니다.

  1. 동일한 라우터를 공유하는 경우 : 그냥 connection 가능
  2. 서로 다른 라우터를 가지고 있는 경우 :
    • 자신의 public ip를 알기 위해 stun server를 사용
    • 자신의 public ip를 토대로 상대방과 통신
  3. 어떤 이유에서건 p2p 통신이 불가능한 경우 : turn server를 사용해서 통신

이렇게 세 가지의 통신을 지원하는 프레임워크가 ICE 라고 보면 됩니다.

Communicationing

RTP - Real time transport Protocol / RTCP - Real time Transport Control Protocol

a가 audio call을 요청하는 상황에 a의 audio stream 값이 상대방에게 전송되는데
이 전송되는 데이터의 format을 RTP라고 보면 됩니다.
voice call이 진행중인 상황에서 상대방이 말하고 있으면, 나는 침묵하게 되는데 이 침묵이 담긴 데이터 패킷을 굳이 상대방에게 전송할 필요가 없겠죠 ?
이 때 RTCP가 active call 인지 체크해서 대역폭을 낭비하지 않도록 조절하는 것, RTP의 통계값을 의미한다고 보면 됩니다.

물론 video의 경우도 비슷한데, stream 을 전송하려면 RTP로 실제 패킷을 담고, RTCP로 통계값을 사용합니다.
RTCP로는 packet loss 등의 정보를 담고 있으며, 불필요한 대역폭 낭비를 줄이는 역할도 합니다.

SCTP - Stream Control Transmission Protocol

RTP / RTCP 와 같은 Communication Protocol 분류에 들어갑니다.
RTP와 RTCP는 미디어, 오디오, screen sharing할 때만 적용이 가능한 프로토콜이라 이외의 경우에는 사용이 불가능합니다.
그래서 사용하는게 SCTP 입니다. 파일공유, 채팅, 게임 관련 등 비디오나 오디오를 제외한 나머지 데이터를 통신에 활용할 때 사용합니다.

Securing

DTLS - Datagram Transport Layer Security

SRTP - Secure Real-time Transport Protocol

둘 다 Security Protocol로 p2p 로 전송되는 데이터는 개인의 웹캠이나 목소리 등의 개인적인 정보일 가능성이 큽니다.
그래서 해커가 중간에서 데이터를 접근하지 못하게 할 방법이 필요합니다.

그러니까.. 기본적인 로직으로는

  1. Signaling 과정에서 하나의 certificate를 생성하고, 서로 교환합니다.
  2. 그러면 서로 교환한 certificate로 데이터를 복호화 해서 데이터를 확인할 수 있게 됩니다.
  3. 그러니까... 중간에 누가 데이터를 훔쳐가도 복호화 불가능하게 만들어버리기~

SRTP : RTP 데이터를 암호화 하는 프로토콜 (물론 위에서 말한 세가지 경우에만 사용)
DTLS : RTP 제외한 나머지 데이터 통신 과정에서 사용


사용 예제

먼저 구글의 WebRTC 예제에 따라 기초부터 하나씩 기능을 추가하면서 진행해보도록 하겠습니다.

  • 구글 예제 : https://github.com/googlecodelabs/webrtc-web

  • 1단계 : 카메라에서 비디오를 추출하기

  • 2단계 : RTCPeerConnection 을 이용하여 대상에게 비디오를 제공하기

  • 3단계 : RTCDataChannel 을 이용하여 데이터를 주고 받기

  • 4단계 : 서버를 이용하여 메시지를 주고 받기

  • 5단계 : 네트워크 상에서 비디오를 주고 받기

  • 6단계 : 이미지를 공유하기

로 이루어져 있으며, 간단하게 몇몇 중요한 부분들을 설명하고, 개인적으로 WebRTC 라이브러리를 사용해서 프로젝트를 진행해보도록 하겠습니다.

1단계 : 카메라에서 비디오를 추출하기

// 비디오 만을 허용
const mediaStreamConstraints = {
  video: true,
};

// 이 스크립트를 사용하게될 화면에 있는 비디오 태그 가져오기
const localVideo = document.querySelector('video');

// 비디오 태그에서 재생될 로컬 스트림
let localStream;

// 위에서 가져온 비디오 태그 요소에 미디어 스트림을 추가하여 성공으로 처리
function gotLocalMediaStream(mediaStream) {
  localStream = mediaStream;
  localVideo.srcObject = mediaStream;
}

// 만약에 문제 발생시 에러 출력
function handleLocalMediaStreamError(error) {
  console.log('navigator.getUserMedia error: ', error);
}

// navigator.mediaDevices에서 getUserMedia를 통해 비디오를 가져온 다음 가져온 미디어 스트림을 위에 작성한 메서드로 넘김
navigator.mediaDevices.getUserMedia(mediaStreamConstraints)
  .then(gotLocalMediaStream).catch(handleLocalMediaStreamError);
test

위 코드를 실행하게 되면 위와 같은 화면을 확인할 수 있게 됩니다. 사실 여기까지는 WebRTC는 사용하지도 않았으니... 차근차근 넘어가도록 하겠습니다.

2단계 : RTCPeerConnection 을 사용하여 비디오 제공하기

챕터 2 보러가기