study record

WebRTC에 대해 알아보자! 본문

기타

WebRTC에 대해 알아보자!

asong 2024. 4. 28. 19:52

Background

인스타 라이브, 유튜브 라이브는 RTMP 프로토콜을 사용한다고 한다.

  • RTMP란?
    • RTMP(Real Time Message Protocol)은 어도비 독점 프로토콜로 보통 비디오나 오디오 등을 인터넷 상에서 실시간으로 스트리밍 데이터를 전송해서 불특정 다수들이 받아 볼 수 있도록 하는 기술의 규격이다.
  • RTMP와 WebRTC의 차이점?
    • 인스타, 유튜브, 트위치 라이브는 RTMP를 사용하여 실시간 스트리밍을 한다. WebRTC는 더 낮은 Latency를 가지고 있고 Real Time과 비슷한 방송을 할 수 있다.

구글 밋, 디스코드, 게더 타운 등 어떠한 소프트웨어 설치도 없이 웹브라우저만 있으면 화상 회의를 가능하게 해주는 기술이 WebRTC 기술이다.

 

 

WebRTC 란?

WebRTC(Web Real-Time Communication)는

웹 또는 앱(Android, iOS)에서 별도의 소프트웨어, 플러그인 없이 음성, 영상, 텍스트 같은 데이터를 브라우저끼리 주고 받을 수 있게 해주는 기술이다.

  • 화상통화, 화상 공유 등을 구현할 수 있는 오픈 소스
  • 비디오, 음성, 일반 데이터가 P2P 방식으로 피어 간의 전송되도록 지원
  • JavaScript API로 제공
  • STUN/TURN 서버 필요. 피어 간의 통신을 하기 위해서사용자의 IP 주소를 알아야 한다. 대부분의 사용자는 방화벽을 사용하고 다른 네트워크 상에서 연결이 이루어지기 위해서는 STUN/TURN 서버가 꼭 필요하다.
  • 계속 이야기하는 피어 간의 통신이란, 하나의 컴퓨터와 다른 컴퓨터 하나가 데이터를 주고 받는 것이다. 동등 계층 간 클라이언트/서버의 개념 없이 동등한 노드들로 구성되어 데이터를 주고 받는 것이다.

 

NAT(Network Address Translation)란?

  • 네트워크 주소 변환
  • 각 기기에도 자신만의 이름이 있다. 그게 바로 IP(Internet Protocol)이다.그렇기 때문에 통상적인 네트워크에서 데이터를 주고 받기 위해서는 Public IP가 필요하다. 또한 IP 주소를 재기록하면서 라우터를 통해 네트워크 트래픽을 주고받는 메커니즘이다.

→ NAT는 WebRTC 통신에 많은 문제를 야기시킨다.

 

  • 이때에 STUN, TURN 서버를 통해 문제를 해결할 수 있다.
  • WebRTC 통신은 피어 간의 통신으로 서로 데이터를 주고 받아야 하므로 보내고 받는 피어의 정보(Public IP)를 알아야 한다. 그러나 Public IP는 요청을 보낼 때마다 private IP → Public IP로 NAT에 의해 바뀌기 때문에 동일한 Public IP로 통신할 수 없는 문제가 생긴다.
  • NAT는 Private IP를 Public IP로 1대1 대응시켜 변환하는 장치를 말한다.
  • IP는 고정IP, 유동IP로 나뉘어서 실제 고유의 값일 수도 아닐 수도 있다. 회사망/내부망(LAN)은 Private IP이기 때문에 다른 네트워크에서는 통용되지 않는다.

 

ICE (Interactive Connectivity Establishment)

ICE는 두 단말이 서로 통신할 수 있는 최적의 경로를 찾을 수 있도록 도와주는 프레임워크이다.

 

어떻게 최적의 경로를 찾는가?

→ TURN, STUN 서버를 사용하여 최적의 경로를 찾을 수 있다.

 

왜 ICE를 사용해야 하는가?

→ 모든 단말은 각자의 환경이(학교 내부망, 회사 내부망, 집의 네트워크) 다양하기 때문에 피어 간의 연결이 단순하게 이루어지지 않는다. 방화벽이 존재하면 방화벽도 통과해야 하고, Public IP가 없다면 유일한 주소값을 할당해야 하고, 라우터가 직접 피어 간의 연결을 허용하지 않으면 데이터를 릴레이 해야 한다.

 

ICE 프로세스를 사용하면 NAT가 통신을 위해 필요한 모든 포트를 열어두고, 두 개의 엔드 포인트를 연결 할 수 있는 IP주소, 포트에 대한 완전한 정보를 가지게 된다.

결국 요청하는 클라이언트와 미디어 서버 사이의 연결을 통해 미디어(비디오, 음성)을 주고 받을 수 있다.

ICE는 혼자 동작하지 않으며 STUN, TURN 서버를 사용해야 한다.

 

STUN (Session Traversal Utilities for NAT)

공개 주소를 발견하거나 피어 간의 직접 연결을 막는 등 라우터의 제한을 결정하며 ICE를 보완하는 프로토콜이다.

간단하게 STUN 서버는 해당 피어의 Public IP 주소를 보내는 역할이다.

종단 간의 연결을 확인하고 NAT 바인딩을 유지하기 위한 연결 유지 프로토콜로도 사용할 수 있다.

다만, 두 단말이 같은 NAT 환경에 있거나 NAT의 보안 정책이 엄격하는 등의 이유에 따라 완벽한 해결책이 되진 않는다.

 

[방법]

STUN(Session Traversal Uilities for NAT)는 위에서 말했듯 NAT환경에서 Private IP를 별도로 가지고 있기 때문에 Peer to Peer(이하 P2P) 통신이 불가능하다. 따라서 클라이언트는 자신의 Public IP를 확인하기 위해 STUN 서버로 요청을 보내고 서버로 부터 자신의 Public IP를 받는다. 그래서 이때부터 클라이언트는 자신이 받은 Public IP를 이용하여 시그널링을 할때 받은 그 정보를 이용해서 시그널링을 하게 한다.

 

다만 이 STUN으로 모든걸 해결할 수는 없는데 바로 두 명의 Client가 같은 네트워크에 존재하고 있을때는 이것으로는 해결이 되지 않는다. 또한, NAT 환경에서 Symmetirc NAT의 경우는 어플리케이션이 달라지면 NAT의 매핑테이블이 바뀔 수 있기 때문이다.

 

TURN (Traversal Using Relays around NAT)

STUN의 확장으로 NAT 환경에서 릴레이하여 통신을 하게 된다.

NAT 보안 정책이 너무 엄격하거나 NAT 순회를 하기 위해 필요한 NAT 바인딩을 성공적으로 생성할 수 없는 경우에 TURN을 사용한다.

 

TURN 서버는 인터넷망에 위치하고 각 피어들이 사설망 안에서 통신한다. 각 피어들이 직접 통신하는 것이 아니라 릴레이역할을 하는 TURN 서버를 사용하여 경유한다.

TURN은 이러한 릴레이로부터 IP주소와 포트를 클라이언트가 취득할 수 있는 릴레이 주소를 할당한다.

 

단점 또한 존재한다. 클라이언트와의 연결을 거의 항상 제공하지만 STUN에 비해 리소스 낭비가 심하다. 그렇기 때문에 ICE Candidate 과정에서 Local IP로 연결할 수 있는지, Public IP로 연결할 수 있는지를 알아낸 후 최후의 수단으로 사용해야 한다.

 

클라이언트는 자신의 Private IP가 포함된 TURN 메세지를 TURN서버로 보낸다. 그러면 TURN 서버는 메세지에 포함된 Network Layer IP 주소와 Transport Layer의 UDP 포트 넘버와의 차이를 확인하고 클라이언트의 Public IP로 응답하게 된다. 이때 NAT는 NAT 매핑테이블에 기록되어 있는 정보에 따라서 내부 네트워크에 있는 클라이언트의 Private IP 로 메세지를 전송한다.

 

 

ICE Candidate Gathering

Local Address, Server Reflexive Address, Relayed Address 등 통신 가능한 주소들을 모두 가져온다.

이 주소들 중 가장 최적의 경로를 찾아서 연결시켜준다.

 

ICE는 Client가 모든 통신 가능한 주소를 식별하는 것을 의미하는데 클라이언트는 STUN 메세지를 TURN 서버로 요청 및 응답과정에서 다음 3가지의 주소를 확인 하게 된다.

 

◾Relayed Address : TURN 서버가 패킷 릴레이를 위해 할당하는 주소

◾Server Reflexive Address : NAT 가 매핑한 클라이언트의 공인망(Public IP, Port)

◾Local Address : 클라이언트의 사설주소(Private IP, Port)

 

따라서, STUN 서버는 Server Reflexive Address 만을 응답하지만 TURN 서버는 Relayed Address와 Server Reflexive Address 를 모두 응답한다.

 

Candidate라는 개념이 추가로 존재하는데 이것은 IP와 포트의 조합으로 표시된 주소이며 이제 이 확보된것을 통해서 연결을 해야한다.

◾Direct Connection : Host 간의 직접적인 미디어 송수신

◾Server Reflexive Connection : Server Reflexive Candidate를 이용한 미디어 송수신

◾TURN Relay Connection : Relay Candidate를 이용한 미디어 송수신

 

이제 이렇게 확보된 3개의 주소들의 우선순위를 정하여 SDP내에 포함시켜 전송한다. Connection을 체크한 후 Connection이 완료되면 RTP 및 RTCP 패킷을 전송하여 통화가 가능하게 된다.

 

STUN 서버랑 TURN서버의 차이

TURN서버는 STUN서버의 개념을 포함하고 있는 Super Set이며 STUN서버 처럼 단순히 라우팅 테이블을 통해서 Private IP를 Public IP를 연결하는데에 그치지 않는다.

WebRTC를 예로 들면 미디어 데이터를 1:1로 보내준다고 했을때 그 모든 데이터는 TURN 서버를 Relay 서버로 하여 데이터를 원하는 Peer에게 전달해주게 된다.

 

하지만, 만약 1:N 통신으로 스트리밍하는 서비스에서 중간에 Media 서버를 두어 중계하지 않으면 모든 Peer가 매쉬 구조로 연결되게 되어 각 Peer에 엄청난 부담을 주게 되고 네트워크 자원도 너무 많이 사용하게 된다.

 

따라서, 이것을 해결하는 MCU방식과 SFU방식이 있다.

결론적으로 Client와 Media 서버가 서로 Peer관계를 맺어 단순 송신 혹은 수신을 하게 된다. 그래서 TURN서버를 Relay 서버로 거칠 이유가 없기 때문에 이런 서비스에서는 TURN 서버는 단순히 STUN서버의 역할을 할 가능성이 크다고 한다.

 

 

WebRTC Sample API

  • RTCPeerConnection
    • 두 Peer 간의 안정적이고 효율적인 통신을 설정하고 관리한다.
    • 신뢰할 수 없는 네트워크에서도 실시간 통신을 가능하게 한다.
  • RTCDataChannel
    • Peer 간의 연결을 통해 데이터를 보낸다.
    • 텍스트, 파일, 데이터 등을 전송할 수 있다.
  • Select sources & outputs : 사용 가능한 오디오, 비디오 등이 여러 개일 때 선택할 수 있게 한다.
  • Stream capture: 재생하고 있는 비디오를 캡쳐할 수 있다.

 

알아야 할 용어

  • Data Streams
    • 연결 지향 통신에서 연속적으로 끊임없이 생성되고 흘러나오는 데이터들의 흐름
  • NAT(Network Address Translation)
    • 네트워크 주소 변환으로 IP 패킷의 TCP/UDP 포트 숫자와 소스 및 목적지의 IP 주소 등을 재기록하면서 네트워크 트래픽을 주고 받는 기술이다.
  • Signaling 시그널링
    • 시그널링은 P2P 통신이 일어나기 전 (즉, 데이터가 전송되기 전)에 세션 제어 메세지, 네트워크 구성, 미디어 기능 등의 정보를 교환하는 데 사용합니다.
      • 세션 제어 메세지 : 통신을 초기화하거나 닫고 오류를 보고
      • 네트워크 구성 : 외부 세계에 컴퓨터의 IP 주소와 포트는 무엇인지 파악
      • 미디어 기능 : 브라우저와 통신하려는 브라우저에서 처리할 수 있는 코덱과 해상도 파악
    • 시그널링은 P2P 스트리밍을 시작하기 전에 성공적으로 완료되어야 한다.
  • SDP (Session Description Protocol)
  • JSEP (JavaScript Session Establishment Protocol)

 

SFU (Selective Forwarding Unit)

P2P와 달리 서버에서 미디어 트래픽을 중계해준다.

이전에는 클라이언트(Peer) - 클라이언트(Peer) 간의 연결을 진행했다면 이번에는 서버(Peer) - 클라이언트(Peer) 간의 연결을 진행하게 된다.

그에 따라, N:M 상황에서 여러 명과의 링크를 유지해야하는 상황에서 서버와의 링크를 유지하면서 서버와 미디어 정보를 송수신하면 된다.

위의 그림에서처럼 자신의 미디어 정보를 송신할 링크(Uplink) 1개와 미디어 정보를 수신할 링크(Downlink) N개를 가지게 된다.

이전 Mesh 구조에 비해 Connection을 덜 유지하게 된다.

 

장점

  • 서버가 미디어 트래픽을 중계해주기 때문에 모든 Connection에 대해 클라이언트가 직접 관리할 필요가 줄어들기 때문에 클라이언트의 부하가 줄어들지만 서버의 부하가 증가한다.
  • P2P보다는 실시간성이 떨어질순 있지만 P2P에 걸맞는 실시간 송수신이 보장된다.

단점

  • 클라이언트의 부하가 줄어들긴하지만 단순 정보 중계를 위해 사용하던 P2P 서버와는 달리 미디어 트래픽을 중계해야하기 때문에 서버의 부하가 증가한다.
  • P2P에 비해 N:M 연결에서 부하가 줄어들긴 했지만 각각의 수신 링크(Downlink)를 개별적으로 유지해야하기 때문에 클라이언트의 부하는 여전히 높다.

 

MCU (Multi-point Control Unit)

SFU와 비슷하게 서버가 중간에서 미디어 트래픽을 중계해준다.

그렇기 때문에 마찬가지로 서버와 클라이언트 간의 연결을 진행하게된다.

SFU는 각각의 클라이언트에서 오는 미디어 정보들을 그대로 포워딩해준 반면 MCU에서는 각각의 클라이언트에서 오는 미디어 정보들을 혼합하고 가공해서 수신측으로 전송해준다.

그렇기 때문에 미디어 정보를 수신할 링크(Downlink)를 N개를 가질 필요 없이 혼합된 데이터를 받을 링크(Downlink) 1개만을 가지고 있으면 된다.

즉, 미디어 정보를 송신할 링크(Uplink) 1개와 미디어 정보를 수신할 링크(Downlink) 1개 총 2개의 링크만을 유지하면 되기에 네트워크에 최적화된 방식이라고 볼 수 있다.

하지만 위에서 언급했듯이, 연결되어있는 모든 클라이언트들의 미디어 정보들을 수신하고 이를 혼합 및 가공해야하기 때문에 서버의 부하가 기하급수적으로 높아진다.

 

장점

클라이언트는 단순 링크 2개(Uplink, Downlink 각각 1개)만을 유지하면 되기에 클라이언트의 부하가 상당히 줄어든다. N:M 연결에서 효율적인 모습을 보여줄 수 있다.

단점

모든 클라이언트들의 정보를 수집하고 한번에 혼합 및 가공을 진행하기에 실시간 송수신 보장이 어려울 수 있다.서버가 모든 미디어 정보를 중계하고 이를 혼합 및 가공하는 과정까지 거쳐야하기 때문에 서버의 부하가 상당히 심해진다.

 

 

 

ICE (Interactive Connectivity Establishment)

  • 두 Peer간 데이터 송수신시 최적의 경로를 찾아주는 프레임워크
  • 두 Peer간 연결 테스트를 위해 SDP를 이용해 미디어 패킷을 보내 연결 가능한지 확인

 

ICE Candidate

  • STUN, TURN 서버를 이용해 얻어낸 IP주소, 프로토콜, 포트의 조합으로 구성된 네트워크 주소들
    • private IP , 포트번호
    • public IP, 포트번호 (STUN, TURN 서버에서 구해옴)
    • TURN 서버의 IP, 포트번호 (TURN 서버에서 구해옴)

ICE를 이용해 P2P 통신할수 있는 주소 후보(ICE Candidate)들을 찾고, 정보들을 주고받게 해줘야 하는데 이때 사용하는게 SDP

 

SDP(Session Description Protocol)

해상도, 형식, 코덱, 암호화 등 멀티미디어 컨텐츠 연결을 설명하기 위한 표준.

두 peer간 다른 한쪽이 데이터가 전송되고 있다는걸 알게 해줌.

구조

SDP는 한줄 이상의 UTF-8 텍스트로 구성 되어있음.

등호기호(”=”) 를 기준으로,

좌측: letter-lines

우측: 포맷에 맞게 값이나 설명이 적혀있음.

 

 

 

 

시그널링 Signaling

서로 다른 네트워크에 있는 2개의 디바이스들을 통신하기 위해서는, 각 디바이스들의 위치(IP) 발견 및 미디어 포맷협의가 필요하다. 이 프로세스를 시그널링 signaling 이라 부르고 각 디바이스들을 상호간에 동의된 서버(socket.io 혹은 websocket을 이용한 서버)에 연결시킨다.

 

⭐시그널링 과정 ⭐

A가 offer 라는 세션 정보를 만든다. 이 offer는 세션 정보를 SDP 포맷으로 가지고 있으며, 커넥션이 이어지기를 원하는 B에게 전달되어야 한다.

B는 offer를 전해 받고 이 offer에 SDP description을 포함하는 answer 메세지를 보내야 한다.

이 과정이 끝나면 A와 B는 서로 어떤 코덱들과 어떤 video parameter들이 사용될지 알 수 있다. 하지만, 그들은 아직 미디어 데이터 전송하는 방법을 모른다. 이때 ICE가 사용된다.

 

[offer message]

 

자, 이제 SDP를 교환했으니 ICE를 교환해야 한다. 각 ICE candidate는 발신 피어 입장에서 통신을 할 수 있는 방법을 설명한다.

각 피어는 검색되는 순서대로 candidate를 보내고 미디어가 이미 스트리밍을 시작 했더라도 모든 가능한 candidate가 전송 완료될 때까지 계속 보낸다. 두 피어가 서로 호환되는 candidate를 제안했다면, 미디어는 통신을 시작한다.

 

[candidate]

 

 

Signaling transaction flow ⭐

시그널링 정보를 교환하는 기초적인 과정

민수는 민지에게 영상통화를 걸었다.

1. 민수 - Web App

invite()

  1. RTCPeerConnection을 생성한다.
  2. **getUserMedia()**를 통해 웹캠과 마이크의 권한을 허용받는다.
  3. RTCPeerConnection에 stream을 추가하기 위해 myPeerConnection.addStream() 함수를 실행한다.

2. 웹 브라우저

영상통화가 준비되었는지 민수에게 물어본다

3. 민수 - Web App

handleNegotiationNeededEvent()

  1. SDP offer를 생성하기위해 RTCPeerConnection.createOffer() 함수를 실행한다.
  2. 생성된 offer 정보를 전달하기위해 RTCPeerConnection.setLocalDescription() 함수를 실행한다.
  3. video-offer”타입의 메세지로 시그널링 서버의 민지에게 제안을 보낸다.

4. 웹 브라우저

ICE layer는 candidates를 민지에게 보낸다.

5. 시그널링 서버

on.message()

“video-offer”타입의 메세지를 받아 민지에게 전송한다.

6. 민지 - Web App

handleVideoOfferMsg()

  1. RTCPeerConnection을 생성한다.
  2. 수신된 SDP offer를 사용하여 RTCSessionDescription 를 생성한다.
  3. 민수의 WebRTC 구성에 알려주기 위해 RTCPeerConnection.setRemoteDescription() 를 생성한다.
  4. getUserMedia()를 통해 웹캠과 마이크의 권한을 허용받는다.
  5. local steam을 추가하기 위해 RTCPeerConnection.addStream() 를 실행한다.
  6. 민수에게 보낼 SDP answer를 생성하기 위해 RTCPeerConnection.createAnswer() 를 실행한다.
  7. 민지의 커넥션을 끝내기 위해 RTCPeerConnection.setLocalDescription()를 호출하여 연결한다.
  8. 시그널링 서버를 통해 SDP answer를 "video-answer" 타입으로 전송한다.

7. 웹 브라우저

ICE layer는 candidates를 민수에게 보낸드.

8. 시그널링 서버

on.message()

video-answer”타입의 메세지를 받아 민수에게 전송한다.

9. 민수 - Web App

handleVideoAnswerMsg()

  1. SDP answer을 받기위해 RTCSessionDescription를 생성한다.
  2. 세션 설명을 **RTCPeerConnection.setRemoteDescription()**에 전달하여 민지의 연결 끝이 어떻게 구성되어 있는지 알 수 있도록 민수의 WebRTC 계층을 구성한다.

 

ICE candidate exchange process ⭐

ICE layer에서 candidate들을 보내기 시작할 때, 다음과 같은 교환이 일어난다.

Web Browser

SDP 문자열로 표현되는 ICE 후보 생성

 

1. 민수 - Web App

handleICECandidateEvent()

1.candidate를 받고 시그널링 서버를 통해 민지에게 "new-ice-candidate”메세지를 전송한다.

2. 시그널링 서버

on.message()

"new-ice-candidate”메세지를 받아 민지에게 전송한다.

3. 민지 - Web App

handleNewIceCandidateMsg()

  1. candidate에 제공된 SDP를 사용하기위해 RTCIceCandidate를 생성한다.
  2. candidate를 RTCPeerConnection.addIceCandidate()에 사용하여 민지의 ICE 레이어로 전달한다.

4. Web Browser

SDP 문자열로 표현되는 ICE 후보 생성

5. 민지 - Web App

handleICECandidateEvent()

candidate를 받고 시그널링 서버를 통해 민수에게 "new-ice-candidate”메세지를 전송한다.

6. 시그널링 서버

on.message()

"new-ice-candidate”메세지를 받아 민수에게 전송한다.

7. 민수 - Web App

handleNewIceCandidateMsg()

  1. candidate에 제공된 SDP를 사용하기위해 RTCIceCandidate를 생성한다.
  2. candidate를 RTCPeerConnection.addIceCandidate()에 사용하여 민수의 ICE 레이어로 전달한다.

 

 

📌 Reference