WebRTC(Web Real-Time Communication)는 웹 브라우저 간에 플러그인 없이 서로 통신할 수 있도록 설계된 API입니다. 또한 WebRTC는 표준임과 동시에 표준을 구현한 오픈소스 프로젝트입니다. WebRTC에서 브라우저가 일반적인 피어(Peer)인데 이들이 서버가 없이 통신하기 위한 여러 문제들을 해결하기 위한 요소들이 필요합니다. 이때 실시간으로 통신할 때 단순한 텍스트만 보내는 것이 아니라 영상, 음성 등 다양한 포멧의 데이터를 송,수신 할 수 있습니다. WebRTC는 빠른 데이터 송신, 수신을 위해서 RTP, RTCP, SDTP 등의 UDP를 활용하는 프로토콜을 활용하고 있습니다. 브라우저에서는 WebRTC를 위한 JavaScript API를 제공하고 있습니다. 개발자가 특별한 라이브러리를 사용하지 않는다면 표준화된 이 API를 사용하여 구현합니다.
피어는 일종의 노드이며 클라이언트라고 생각하시면 됩니다. 다만 기존의 웹 구조에서는 클라이언트 - 서버로 데이터 전달과 서비스 제공이 이루어졌다면 WebRTC에서는 쌍방이 데이터 송수신을 할 수 있기 때문에 피어(Peer)라고 지칭합니다.
웹 서비스는 네트워크 연결의 어려움이 없었습니다. 프레임워크나 브라우저 레벨에서 TCP/IP 서비스를 잘 만들어놓았고 기존 개발자들이 네트워크에 대해서 잘 몰라도 클라이언트- 서버의 네트워크 연결이 거의 자동으로 진행되었습니다. 그저 클라이언트가 서버의 IP:port로 요청(request)를 보내면 3-handshake, 4-handshake를 통한 통신,통신 종료가 개발자들이 신경안쓰는 사이에 진행되었습니다.
그러나 P2P(Peer to Peer)는 이러한 일종의 자동화된 네트워크 연결이 어렵습니다. 후술하겠지만 Peer는 일반적인 IP를 쓰지 않기 때문입니다.
따라서 P2P 서비스는 일반적인 클라이언트 - 서버와는 다른 연결과정과 인프라 가 필요합니다.
WebRTC는 P2P를 위한 서비스이지만 아이러니하게도 그 연결을 위해서는 P2P의 통신을 중계해줄 시그널링 서버가 필요합니다.
WebRTC는 다양한 프로토콜을 통해서 피어 통신의 저지연성을 지원하고 있습니다. 이를 위해서 각 피어는 본인의 IP와 포트, 미디어 코덱 등의 통신 세션 정보를 교환해야합니다. Peer 통신을 하기 위해서는 나의 정보를 상대에게 보내야하는데 상대에게 내 정보를 보낼 방법이 없기 때문에 시그널링 서버라는 중계자가 필요합니다.(상대의 IP, port를 몰라서 보낼 수가 없습니다.) 따라서 시그널링 서버에게 내 정보를 보내면 시그널링 서버는 상대에게 나의 정보를 중계해주고 상대도 저에게 본인의 정보를 시그널링 서버를 통해서 보내게 됩니다.
시그널링 서버를 통해서 각자의 세션 정보를 교환하면 PeerConnection이 생깁니다. 이 PeerConnection을 통해서 필요한 데이터를 교환하게 됩니다.
이 부분은 피어가 연결을 맺는 중요한 부분인데 저는 여기서 곤혹스럽기도 하고 머리아픈 많은 디버깅을 처리했던 부분이기도 합니다. 나중에 코드와 함께 설명할 수 있도록 하겠습니다. 우선 축약한 개념과 순서를 설명하겠습니다.
추후 이 두 웹사이트에서 읽어보시면 좋을 것 같습니다.
WebRTC 정보
MDN WebRTC connectivity
1. 두 피어는 SDP(Session Description Protocol)를 교환하고 쌍방의 SDP를 저장합니다.
2. Ice Candidate를 교환하면서 최적의 네트워크 통신 경로를 탐색합니다.
3. ICE를 통해서 각자의 환경에 최적의 네트워크 통신을 확정합니다.
4. Negotiation이 끝나면 Peer Connection 생성되고 미디어를 송수신할 수 있습니다.
IP기반의 네트워크 통신에서는 IP가 디바이스마다 설정됩니다. 이 IP를 통해서 특정 피어를 식별하고 통신을 가능하게 합니다. 웹 서비스에서도 클라이언트는 DNS를 통해 서버의 IP를 알고 요청을 보낼 수 있습니다. 서버도 클라이언트의 IP를 식별해서 응답을 보낼 수 있습니다.
P2P에서도 이와 같이 상대의 IP를 알아야 네트워크 통신을 할 수 있다는 점은 동일하지만 웹 서비스와 다른 점은 개인은 NAT(Network Address Tranlation)로 야기되는 문제가 있다는 것입니다. 이를 통해서 Private Ip/Public Ip가 생깁니다.
내 Public IP 알아보기
위의 링크를 통해서 나오는 IP가 본인의 Public IP 입니다. 윈도우라면 CMD에 ipconfig, 맥이나 리눅스라면 ifconfig를 치면 나오는 네트워크 ip가 private IP입니다.
P2P 통신을 하기 위해서는 본인의 Private IP와 Public IP 둘 다 알고 상대에 전해줘야 합니다. 마치 본인 아파트 1층 비밀번호와 집 현관문 비밀번호를 알아야 집에 들어갈 수 있는 것과 같이 말입니다.
NAT 알아보기
Stun server는 개인의 Private,Public IP를 반환해주는 서버입니다. Peer는 Stun를 통해서 개인의 Network 정보를 알 수 있습니다. Stun을 통해 반환되어 P2P에 사용할 때는 경우 Server Reflexive라고 합니다.
Stun 서버를 통해서 본인의 정보를 알고 통신하는 것이 제일 좋습니다. 그러나 NAT의 보안 정책이 엄격하거나 기타 이유로 인해서 Stun으로는 통신이 어려운 경우 Turn 서버를 사용해야 합니다. Turn 서버는 공인IP를 가진 서버를 통해서 구현해야 합니다. Turn서버는 피어가 상대에게 직접 데이터를 보내지 못하기 때문에 그 데이터를 받아서 상대에게 전달해주는 릴레이 역할을 하는 서버입니다.
이 방법을 사용하면 직접 데이터를 보내는 것이 아니라 데이터를 릴레이하기 때문에 필연적으로 지연되고 엄밀히 말해 P2P통신이 아니기도 합니다. 따라서 Turn 서버를 사용하는 경우는 지양하게 됩니다.
SDP를 주고 받고 나서 각 피어는 ICE(Interactive Connectivity Establishment)를 실행합니다. ICE는 NAT를 우회하는 방법 Stun/Turn을 통해서 두 피어가 WebRTC 통신을 할 수 있도록 연결을 만드는 일종의 프레임워크입니다. Stun/Turn를 통해서 피어가 통신할 수 있는 후보군을 Ice Candidate라고 하는데 이 후보군들을 각 피어가 테스트해보면서 최적의 경로를 발견하면 이를 통해서 두 피어는 그 경로를 사용하기로 합의하면서 연결 상태를 유지합니다. 이 경로는 추후 데이터 연결 상태에 따라서 다시 수정될 수 있습니다. ICE는 개발자가 손대지 않고 표준에 따른 구현을 사용하며 개발자가 임의로 수정하지 않을 것을 권유합니다. 개발자는 ICE는 이해하지 못해도 Peer Connection 구현에는 문제가 없으며 단지 SDP 교환 이후에 Ice Candidate를 또한 교환하는 것까지 구현하기만 하면 됩니다.
WebRTC는 UDP를 사용합니다. 아무리 그래도 우리... 보안은 신경써야겠죠? HTTPS와 같이 Secure Layer를 추가합니다.
DTLS (Datagram Transport Layer Security) and SRTP (Secure Real-Time Transport Protocol)를 통해 기본적인 보안은 챙겨줍니다. 그러나 P2P에서 HTTPS와 같이 인증된 인증서를 쓰기는 어렵습니다. 따라서 시그널링 과정에서 사용한 HTTPS의 인증서를 재활용하여 DTLS를 사용하게 됩니다.
이제 ICE를 통해서 두 피어가 연결되었습니다. 그러면 데이터를 교환해야겠죠?
RTP (Real-time Transport Protocol), and SCTP (Stream Control Transmission Protocol)를 사용합니다. RTP는 실시간 스트리밍을 위해서 사용하며 SCTP는 안정적이고 순서가 보장된 메세지 전달을 위해서 사용합니다.
WebRTC는 P2P를 지원하기 위한 표준이지만 참여하는 사람들이 늘어날수록 각 피어의 네트워크 및 데이터 처리 리소스가 많이 사용되는 한계가 있습니다. 일반인들이 데스트탑으로 WebRTC 서비스를 사용하고 소수의 인원이 참여하는 것이 아니라 많은 인원이 이 서비스에 참여하려고 한다면 Media Server를 사용하는 것은 필수가 됩니다.
사실상 엄밀한 P2P가 아니지만 웹 환경에서 실시간 통신을 하기 위한 최선의 선택이라고 볼 수 있을 것 같습니다. 다만 필수는 아니고 이를 위한 피어 - Media server 시그널링 + Media Server 구현을 하기 위한 품이 더 들어갑니다.
https://tech.kakaoenterprise.com/121
[카카오엔터프라이즈 기술블로그 Tech&(테크앤):티스토리]
https://developer.mozilla.org/ko/docs/Web/API/WebRTC_API
https://webrtcforthecurious.com/
https://hyperconnect.github.io/2022/12/30/introduction-to-media-server.html