webrtc 란?

Matthew Woo·2022년 1월 15일
2

My Review

목록 보기
4/11
post-thumbnail

데모영상
https://github.com/Team-ICON

위 프로젝트를 개발하면서 Websocket을 이용한 서버통신 방식으로 구현할 것이냐, Webrtc를 이용한 peer-to-peer 방식을 사용할 것이냐를 두고 꽤나 고민을 했었었다. 결국 Webrtc로 구현하긴했으나 처음 접했을 때는 생소한 개념들도 나왔고 선 공부 후 프로젝트 착수가 아니라 사실상 프로젝트 개발을 하며 부분적으로 키워드를 기준으로 찔끔찔끔씩 공부했었다 보다보니 흐름을 한번 정리할 필요가 있다고 느꼈다. 그래서 webrtc 관한 부분을 흐름에 포커스를 두고 좀 정리해보고자 한다.


webrtc 란?

WebRTC (Web Real-Time Communication) is a technology that enables Web applications and sites to capture and optionally stream audio and/or video media, as well as to exchange arbitrary data between browsers without requiring an intermediary. The set of standards that comprise WebRTC makes it possible to share data and perform teleconferencing peer-to-peer, without requiring that the user install plug-ins or any other third-party software. -MDN

Webrtc 는 비디오, 음성 스트리밍을 비롯해 브라우저간에 데이터를 주고 받을 수 있게하는 기술입니다. 중간의 third-party software 나 특정 플러그인 설치 없이도 peer-to-peer간 통신 방식으로 데이터를 주고 받을 수 있습니다.

peer끼리 연결하기 (peer connection)

두 peer간 connection을 위해서는, STUN 또는 TURN 서버를 이용하여 ICE candidates 를 수립하는데 ICE candidatesSignaling 의 범주에 들어갑니다. peer to peer 통신인데 STUN, TURN 과 같은 서버는 왜 필요하며, ICE candidate, Signaling 과 같은 모르는 것들이 튀어나와서 필자도 처음에는 당황스러웠으나 하나씩 알아보자.

Signaling은 두 peer 들 간에 서로 데이터를 주고받고 통신하게 하기 위한 과정이다. 이를 위해 크게 두가지로 과정이 필요하다. 첫 번째는 sdp를 주고 받아야하고, 두 번째는 peer간 연결을 위한 과정이 있다.

> sdp 는 뭐고, 두 번째는 또 뭔가요..!!

sdp는 peer간 연결이 된 이후, 어떤 데이터를 어떻게 주고 받을지를 정하는 과정이다. 엄밀히 얘기하면 SDP (Session Description Protocol), 멀티미디어 데이터를 주고 받기 위해 데이터에 대한 포맷을 기술하는 protocol이다. SDP를 통해 데이터를 전달 받는 쪽은 전달 받는 데이터의 메타 정보를 알 수 있다. 그 과정을 보면,

  • 나는 이러이러한 peer 이고, 어떤 media 와 format이 있어(나의 offer를 상대에게 전송)
  • 너는 어떠한어떠한 peer이고, 어떤 media와 format이 가능하구나? (상대의 offer 받음)
  • 그럼 너와 나의 상황 보니.. 우리 앞으로 이런 format, media를 주고 받을 수 있겠구나. 우리 앞으로 잘해보자!(answer 를 상대에게 전송)
  • 이후 상대에게서도 answer를 받은 후 나에게도 적용함


서로 SDP offer or answer를 주고 받는데, 이 sdp를 어떻게 주고 받을지는 자율이다. sdp는 peer 간에 메일로 주고 받건, 종이로 써주건 상관이 없다고 합니다. 실제 sdp 를 보면 콘솔에 찍어보시면 위와 같은 데이터가 나오는데 종이로 써줄만한건 절대 아니며.. 이걸 왜 메일로 주고받나!! 그만큼 어떻게 주고 받을지 정해진 가이드도 없고 저렇게 생긴 녀석을 주고받기만 하면 되기에 이 sdp를 주고 받게 하는 시그널링 서버는 가이드도 없고 프로그래머의 자율이다.

async function makeCall() {
    const configuration = {'iceServers': [{'urls': 'stun:stun.l.google.com:19302'}]} // 0. 이건 좀 이따 살펴볼 것임
    const peerConnection = new RTCPeerConnection(configuration);
    signalingChannel.addEventListener('message', async message => { // 3. 반대로 나와 연결되는 peer도 똑같이 1~2번 과정으로 offer를 생성하였을 것이고 나에게 보낼텐데 이 코드가 각각 offer 보낸 것을 받는 부분
        
      	if (message.offer) { // 3. 각자 offer를 보내니 각자 offer를 받는 부분
          peerConnection.setRemoteDescription(new RTCSessionDescription(message.offer));
          const answer = await peerConnection.createAnswer(); // 4. offer를 받아서 answer을 생성
          await peerConnection.setLocalDescription(answer);
          signalingChannel.send({'answer': answer}); // 5. answer를 peer에게 전송
    	}
      
        if (message.answer) { // 6. 피어들 간에 각자 생성하고 전송한 answer를 받는 부분
              const remoteDesc = new RTCSessionDescription(message.answer); 	
              await peerConnection.setRemoteDescription(remoteDesc); // 각각 상대에게 받은 answer를 등록함
         }
      
      
    });
    const offer = await peerConnection.createOffer(); // 1. 이건 나, local 컴퓨터의 offer를 생성
    await peerConnection.setLocalDescription(offer); 
    signalingChannel.send({'offer': offer}); // 2. 나의 offer 를 연결하는 peer에게 보냄!!
}

첫 줄에 turn 서버를 설정하는 부분은 turn 서버를 얘기하면서 다시보기로하고 구글에서 제공하는 코드를 좀 살펴보자.

RTCPeerConnection는 peer 간 연결을 위해 사용되는 interface로 peer 간 연결을 유지하고 관리하는데 사용되는 함수들을 제공한다. 보통 데이터를 주고 받는 서버 - 클라이언트 간 관계에서는 보내는 쪽, 받는 쪽 코드가 따로 존재하지만 본 케이스는 peer to peer 연결방식이기에 보내는 쪽이나, 받는 쪽이 같은 브라우저에서 보내는 코드(주석에서 1, 2, 6)와 받는 코드 (주석 3, 4,5)가 함께 존재한다.

주석을 좀 달아놓긴했지만 설명을 해보자면 peer간에 각자 offer를 생성하고, 생성한 offer를 전달 한 다음, 전달 받은 offer를 answer하는 과정을 거친다. 서로 주고 받는 과정을 통해 session descriptions를 생성하게 되면 offer와 answer를 주고 받은 peer가 연결이 된 후에는 어떤 데이터 format이나 어떤 데이터를 주고 받을 수 있는지를 파악하게 된다.

오 그럼 이제 각 피어가 서로 sdp를 주고 받았으니 본격적으로 peer 간 연결을 해준 뒤 주고받았던 sdp로 데이터를 서로 주고받으면 된다!!

그럼 peer간 연결을 어떻게 할 수 있는지 살펴보자.

이 과정을 ICE(Interactive Connectivity Establishment) 라고 한다. 직역하면 상호 연결을 수립하는 것. STUN or a TURN server를 이용하게 된다.

STUN (Session Traversal Utilities for NAT)

보통 개인 PC나 기기들에는 public IP가 할당되어 있지 않고 private IP만 할당되어 있다.
보통 라우터에 public IP가 할당되어 있고 이 라우터에 연결된 각 기기에 priviate IP가 할당 된다. 각 peer가 STUN 서버에 요청하여 peer가 연결된 라우터의 public IP를 조회하고 라우터의 public IP뒤에 포트번호를 붙여 peer기기와 매핑 후 public IP로 통신할 수 있는지 확인한다. 방화벽이나 라우터에 의해 ip주소를 특정하지 못한다면 TURN 서버를 이용하여야 한다.

TURN (Traversal Using Relays around NAT)
symmetric NAT을 방식을 이용하는 라우터는 포트번호를 특정할 수 없다. symmetric NAT 방식의 라우터는 통신하는 목적지에 따라 다른 포트를 이용하기 때문에 라우터의 포트를 특정할 수 없고 peer간의 직접 연결이 불가능하다. 따라서 이 라우터를 우회하는 방식을 TURN이라한다. 서로 데이터를 주고 받을 때 TURN 서버로 보내고 TURN 서버가 이 데이터들을 중개해주는 것이다.

따라서 아까 이 코드를 보자면,

  const configuration = {'iceServers': [{'urls': 'stun:stun.l.google.com:19302'}]} 

STUN 서버로 피어간 연결을 할 수 있는 상황인지, 방화벽이나 라우터의 문제로 피어간 연결이 불가능하다면 이 해당 TURN 서버로 데이터를 주고 받겠다라는 의미이다. TURN 서버는 구글에서 제공하는 서버인데 오픈소스로 개발된 TURN 서버도 있다. turn server

webrtc 를 사용하면 안되는 경우, 주의점

  • peer to peer 간 통신 방식이기에 클라이언트가 증가 함에 따라 각 클라이언트가 전송 및 수신을 감당할 수 있는 한계가 있음. 본 필자가 진행한 livememo의 경우 모든 클라이언트가 노트북으로 접속할 때는 약 30명까지 감당가능하지만 모바일 환경에서는 직접 동기생들을 모아 테스트해본 결과 15명이 넘어가면 클라이언트가 감당하지 못하고 연결이 잘 안되는 현상이 발생하였음.

  • 브라우저에서 지원하는 버전 확인을 잘 해야하고 주고 받는 데이터도 각 브라우저에서 서로 주고 받을 수 있게 지원되는 형식인지 확인이 필요하다.


https://en.wikipedia.org/wiki/WebRTC
https://developer.mozilla.org/en-US/docs/Web/API/WebRTC_API/Protocols
https://bloggeek.me/webrtc-turn/
https://bloggeek.me/google-free-turn-server/
https://www.html5rocks.com/en/tutorials/webrtc/infrastructure/

profile
지속가능하고 안정적인 시스템을 만들고자 합니다.

0개의 댓글