webRTC 공부 (P2P 연결)

민순기·2023년 1월 3일
1

webRTC란?

WebRTC(Web Real-Time Communication)은 웹 애플리케이션과 사이트가 중간자 없이 브라우저 간에 오디오나 영상 미디어를 포착하고 마음대로 스트림할 뿐 아니라, 임의의 데이터도 교환할 수 있도록 하는 기술입니다. WebRTC를 구성하는 일련의 표준들은 플러그인이나 제 3자 소프트웨어 설치 없이 종단 간 데이터 공유와 화상 회의를 가능하게 합니다.

이를 위하여 WebRTC는 상호 연관된 API와 프로토콜로 구성되어 함께 작동합니다. 이 문서에서는 WebRTC의 기본을 이해하고, 설정하며, 데이터와 미디어 연결을 위해 사용할 수 있게 도와줄 것입니다.

- MDN


P2P connection

Singaling

webRTC 연결을 성사시키기 위해서는 먼저 누구와 연결할지 어떤 데이터를 보낼지 알고 있어야 한다. 이걸 가능하게 하는것이 바로 시그널링이다.
시그널링은 단순한 텍스트일뿐 webRTC는 어떤 방식으로 보내는지 전혀 상관하지 않지만 일반적으로 webSocket을 사용하여 시그널링 프로세스를 진행한다.

시그널링은 offeranswer 메시지 를 주고받는 과정이다. 해당 메시지에는 SDP라는 정보가 담겨있다.

A와 B가 시그널링 프로세스를 한다면 과정은 다음과 같을것이다.
1. A가 SDP offer를 생성하여 시그널링 서버로 보낸다.
2. 시그널링 서버가 A의 SDP offer를 받아 B에게 포워딩한다.
3. A의 SDP offer를 받은 B는 시그널링 서버에 SDP answer를 전송한다.
4. 시그널링 서버가 B의 SDP answer를 받아 A에게 포워딩한다.

SDP

위 사진에서처럼 SDP에는 IP주소, 미디어 정보, 코덱등의 정보가 담겨있다.

Connection

피어간에 정보를 주고 받기 위해서는 두 피어가 네트워크 연결이 되어있어야 한다.
만약 두 피어가 다른 사설 IP를 사용하고 있다면 두 피어는 커뮤니케이션 할 수 없다.


STUN

이 네트워크 주소를 찾는데 사용하는 프로토콜이 STUN이다.

STUN은 사설망에 있는 클라이언트가 자신에게 접근할 수 있는 공인 IP와 PORT, NAT type(이하 mapped address)을 알기 위한 프로토콜이다.

클라이언트가 STUN 서버에 STUN Binding Request를 날리면 STUN 서버는 STUN Binding Response를 응답으로 전달해준다. STUN Binding Response에는 IP, PORT, NAT type등이 포함되어 있는데 이들을 Mapped Address라고 한다.

STUN은 대부분의 NAT type에서 잘 동작하지만, Symmetric NAT에서는 동작하지 않는다.
STUN은 일관적인 NAT 연결에서 동작하도록 설계되었지만, Symmetric NAT은 목적지가 변경 될 때마다 NAT Mapping이 달라지는 개념이다.

Symmetric NAT에서 STUN이 동작하지 않는 이유

Symmetric NAT는 각 내부 IP:포트 조합에 고유한 외부 IP:포트 조합을 할당하는 NAT 유형입니다.

이로 인해 NAT 장치가 외부 IP:포트 조합과 내부 IP:포트 조합의 매핑을 유지하지 않기 때문에 대칭 NAT 뒤의 피어가 들어오는 연결을 수신하기 어렵습니다.

이 문제를 해결하기 위해 일부 NAT 장치는 피어가 연결을 시작하는 데 사용하는 동일한 외부 IP:포트 조합에서 들어오는 연결을 수신할 수 있도록 하는 "헤어피닝"이라는 기능을 지원합니다.
이 경우 STUN을 사용하여 피어와 연결을 설정할 수 있습니다.

그러나 모든 NAT 장치가 헤어핀을 지원하는 것은 아니며 이러한 경우 STUN을 사용하여 대칭 NAT 뒤에 있는 피어와 연결을 설정할 수 없습니다.

이러한 경우 피어 간에 미디어 스트림을 전달하기 위해 TURN 서버를 릴레이로 사용할 수 있습니다.

- ChatGPT


TURN

만약 두 클라이언트가 같은 NAT 환경에 있고 NAT type이 Symmetric NAT이라면 사용할 수 없다.

위 경우에 사용하는 것이 TURN 이다.

할당

할당이란 TURN 서버가 할당 요청을 보낸 클라이언트에게 relay 주소를 보내는 과정을 의미한다.

클라이언트가 서버에 TURN Message 로 할당 요청(Allocate Request)을 보낼때 생성되고 할당 수명이 만료되거나 클라이언트가 할당을 해제할 때 종료된다.

할당 요청

클라이언트: 공인 IP와 PORT를 통해 중계를 받고 싶습니다. relay주소를 할당해주세요.

응답

TURN 서버: relay 주소는 XX.XX.X.X:XXXXX입니다.

권한 요청 및 승인

할당 받은 relay 주소를 통해 피어끼리 통신을 하기 위한 다음 단계.
signaling 단계에서 주고받은 SDP 내부의 IP가 relay주소로 보내는 요청을 승인하는 것이다. 승인되지 않은 연결은 모두 차단된다. (사전에 통신하기 위한 IP정보를 알고 있어야 한다.)

권한 요청

 피어: OO.O.O.O에서 XX.XX.X.X:XXXXX로 오는 요청을 허가해주세요.

접근 권한은 300s 이후 만료되는데, 이를 방지하기 위해 권한을 요청했던 피어가 다시 TURN 서버에게 권한 요청을 해야 한다.

Indication/ChannelBinding

권한 요청까지 마치고 난 후 TURN 서버와 클라이언트가 메시지를 주고받기 위한 두 가지 방법이 있다.

Indication
1. Server 가 인증을 하라고 Response 를 보냄
2. Client 는 인증정보를 담아서 다시 요청을 보냄
3. TURN Server 는 릴레이 할 주소(XX.XX.X.X:XXXXX)와 피어 A 와 연결 통신 할 수 있는 권한 할당이 되었다고 응답을 보냄
4. 이후 두 단말은 릴레이 정보를 통해 서로 데이터를 주고 받는다.

⇒ 클라이언트 에서 피어 B 로 데이터를 보낼 데이터가 Server 로 오거나 피어 B 에서 Server 로 데이터가 들어오면 누락을 시킨다.

Channel Binding
1. Client가 피어 A 의 전송정보와 채널번호를 지정해서 Server 에 Channel Bind 요청을 보냄
2. Server 는 Bind 이후 응답을 보내줌
3. 이후 Client 는 Channel 정보를 담아서 데이터를 전송, TURN Server 는 채널 정보를 제거 후 데이터만 피어 A 에게 전송
4. 피어 A 에서 들어온 데이터는 TURN Server 에서 Channel 정보를 포함시켜서 Client 에 전송

Indication은 그 자체가 작은 메시지이기 때문에 대용량의 데이터를 다루거나 큰 대역폭이 필요한 서비스에는 적합하지 않다. 만약 백만개의 데이터를 주고받는다면 백만개의 indication이 오가야 하기 때문이다.

이 경우에는 Channel binding 방식을 사용하는것이 좋다.


ICE

ICE는 WebRTC를 사용하여 두 피어를 연결하는데 사용되는 프로토콜이다. STUNTURN을 통해 SDP를 교환했으니 이제 ICE candidate를 교환해야 한다. ICE Candidate란 두 단말을 연결하기 위한 IP주소와 포트의 조합을 의미한다.

ICE의 흐름

  1. 두 피어가 다른 피어와 통신하는데 사용할 수 있는 ICE Candidate를 수집한다.
    이를 ICE Candidate Gathering이라고 한다.
  2. 각 피어는 수집한 candidate들을 다른 피어에게 보낸다.
  3. 두 피어는 받은 candidate를 사용하여 Candidate Pair (이하 쌍) 를 생성한다.
  4. 위 과정이 끝나면 각 피어는 만들어진 쌍들 중 어떤 것이 데이터를 성공적으로 교환 할 수 있는지 연결성 체크를 시작한다.
  5. 모든 쌍들에 대한 연결성 체크를 마치면 가장 연결성이 좋은 쌍을 사용할 연결로 선택한다.
  6. 선택된 연결 통로를 통해 데이터를 교환한다.

Candidate Pair 예시

Candidate 종류

  • Host
    클라이언트의 사설 주소.

  • mDNS
    Host candidate와 유사하지만 IP주소를 사용하지 않고 UUID를 사용한다. IP주소가 드러난 Host candidate의 경우 상대방이 webRTC를 통해 내 로컬 IP주소를 알 수 있지만, mDNS candidate는 랜덤한 값의 UUID밖에 알 수 없다.

  • Server Reflexive
    Server Reflexive CandidateSTUN Binding Request를 STUN 서버에 보낼때 생성된다.
    STUN Binding ResponseXOR-MAPPED-ADDRESSServer Reflexive Candidate이다.

  • Peer Reflexive
    Server Reflexive Candidate와 마찬가지로 STUN Binding Request를 보낼때 생성된다.
    차이는 STUN Binding Request를 STUN 서버로 보내지 않고 상대방 단말로 직접 보낸다는 것이다.
    아마 두 단말이 같은 네트워크 상에 있을때 사용하는것 같다.

  • Relay
    Relay Candidate는 TURN 서버에서 할당해준 relay 주소를 의미한다.


ICE 연결 이후

ICE 연결 이후에는 현재 연결 상태를 계속 체크하고, STUN/TURN으로 연결되어있으면 상태를 주기적으로 refresh한다.
만약 현재 연결중인 Candidate Pair의 연결이 끊기면 다른 Candidate Pair로 연결을 바꾼다.
SDP를 주고받은 후 양 단말이 연결 되면 양 단말 간 실제 비디오 / 오디오 데이터들을 주고 받는다.


참고 레퍼런스
https://webrtcforthecurious.com/
https://snack.planetarium.dev/kor/2019/06/nat_traversal_2/
https://chat.openai.com/
https://velog.io/@kkj53051000/WebRTC%EC%99%80-%EC%8B%9C%EA%B7%B8%EB%84%90%EB%A7%81%EC%9D%B4%EB%9E%80-%EC%8B%9C%EA%B7%B8%EB%84%90%EB%A7%81-Mozilla-%EB%B6%84%EC%84%9D#4-stun--turn

profile
2년차 FE 개발자 민순기입니다.

0개의 댓글