WebRTC ㅎㅇ!
RemoteCraft는 나만의 작은 플랫폼이지만... 가장 Universal하게 쓸 수 있는 플랫폼에 정착하고 싶었다. 그때 찾은 것이 바로 WebRTC..! WebRTC란 plugin-free web - Real Time Communication의 준말이다.
별도의 소프트웨어 및 플러그인이 설치되어 있지 않아도 비디오, 오디오, 데이터의 실시간 양방향 소통을 가능하도록 만들어주는 기술이다. 설명만 들어서는 그저 완벽한 도구가 될 수 있을 것 같다. 디스코드 영상채팅도 이 WebRTC 기술을 쓰는 것으로 알고 있다.!
매뉴얼이... 생각보다 복잡하다.... 어떻게 하는거지?
기본적으로는 peer-to-peer, 두 클라이언트(caller 와 callee)가 중계하는 서버를 거치지 않고 다이렉트하게 1:1 통신을 하게 되어있다.
필요한 과정은...
- 스트리밍 오디오 / 비디오 / 데이터를 가져올 수 있을 것
- 소통하고자 하는 IP 주소와 포트 등 네트워크 데이터가 필요하다
- 에러의 보고, 세션 핸들링을 위해 신호 통신을 관리해야한다
- 서로의 각자의 클라이언트가 지원하는 해상도, 코덱 등 capability 정보를 서로 교환해야한다
- 연결 완료!
- 양방향 스트리밍 시작!
WebRTC 연결의 전체 흐름은 크게 두 덩이의 프로세스로 나누어서 개발 할 수 있다.
- Signaling을 통해 통신할 peer 간 정보를 교환한다. 네트워크 정보, media capability 정보, 세션 수립
- WebRTC를 사용해 연결을 맺고, peer 의 기기에서 미디어를 가져와 교환한다
WebRTC는 양방향 스트리밍을 위해 다음과 같은 클라이언트 API를 제공한다.
- MediaStream : 영상 소리 등 input 데이터 스트림에 접근한다.
- RTCPeerConnection: 암호화 / 대역폭관리 기능. 오디오 / 비디오 연결을 한다.
- RTCDataChannel: 일반적인 데이터 통신 채널
여기까지가 반이고... 2~4번 과정에 있는 자잘한 일들은 모두 Signaling이라는 과정을 통해서 실행된다.
WebRTC 연결에서 개발자가 직접 구축해야하는 것 Signaling Server
- Session control messages: 통신의 상태 관리, 그리고 에러 리포트
- Network configuration : 외부에서 보는 나의 IP 및 포트를 어떻게 찾지?
- Media capabilites : 내 클라이언트와 상대 클라이언트가 사용 가능한 코덱, 그리고 해상도는 뭐지?
다음 작업들은 peer가 서로 스트리밍을 하기 전에 완료되어야 하는 작업들이다.
- Network configuration
- ICE(Interactive Connectivity Establishment) 프로토콜을 사용해서 서로의 퍼블릭 IP 와 포트를 찾고
- 발견된 ICE candidate 에 서로에게 추가
- Media Capabilities
- 미디어 정보 교환은 offer 와 answer 방식으로 교환
- 형식은 SDP(Session Description Protocol)
NAT(Network Address Translation) 은 기기에 공인 IP를 부여하는 기술이다. 라우터에 설정하는데, 라우터는 공인 IP 를 갖고, 라우터에 연결된 모든 기기는 사설 IP 를 갖는다. 기기가 요청할 것이 생기면, 라우터의 고유한 포트를 사용해서 사설 IP 에서 공인 IP 로 변환한다(translation). 어떤 라우터는 접근할 수 있는 노드를 제한 할 수 있다.
- ICE는 UDP 를 통해 기기들을 서로 직접 연결시도한다.
- 바로! 연결이 되었습니다. 이제 미디어를 교환합시다. (거의... 사설망에서만 가능.. 진짜 안됨..)
- 상대 기기가 NAT 혹은 방화벽 뒤에 있다!
- 기기가 NAT 뒤에 있다. STUN 서버가 이를 해결해 줄 수 있겠다.
- STUN (Session Traversal Utilities for NAT) 는 기기의 공인 IP 를 알려준다. 기기의 NAT가 직접 연결을 허용하는지, 아닌지 파악하는 역할도 한다.
- 클라이언트는 STUN 서버에 요청을 보낸다. STUN 서버는 클라이언트의 공인 주소와, 클라이언트가 NAT 뒤에서 접근이 되는지 알려준다.
- 그 이후에 직접 다른 기기와 통신한다. <- 요 통신 또한 시그널링 서버의 담당이다!
- 이제 연결이 되었습니다. 이제 미디어를 교환합시다.
- 실패..! 이럴때는 이제 TURN 서버가 필요한 때이다.
- TURN아... 도와줘..
- TURN ( Traversal Using Relays around NAT)서버는 Symmetric NAT 의 제약조건을 우회하기 위해서 만들어졌다. TURN 서버와 연결을 맺고, 이 서버가 모든 스트리밍 과정을 중개해준다. 모든 기기는 TURN 서버로 패킷을 보내고, 서버가 이를 상대에게 포워딩 해주는 방식이며 당연히 오버헤드가 생기고 비용이 매우 많이 들것으로 예상된다... 트래픽 비용이 와르르르..
- Google에서도 STUN서버는 오픈으로 지원해주지만 TURN서버는 지원해주지 않는다!
Session Traversal Utilities for NAT (STUN) – RFC 5389
Session Traversal Utilities for NAT (STUN)은 P2P 통신을 위해 호스트가 NAT의 존재 유무 및 NAT의 종류를 식별하고 또한 NAT에 의해 변경되는 퍼블릭 IP 주소 및 Port 값을 발견하기 위한 네트워크 프로토콜이다.
STUN은 클라이언트-서버, 응답-요청 프로토콜이다. STUN 클라이언트는 본인의 공용 IP 및 포트를 발견하기 위해 STUN 서버에 요청을 보내고 STUN 서버는 그 정보를 응답한다. 요청에는 일반적으로 UDP를 통해 전송되는 Binding Request와 TCP or TLS를 통해 전송되는 Shared Secret Request 이다.
그외....
여기까지가 간략한 1:1 또는 소규모 통신을 위해 알아야 할 것들이고 때에 따라서 대규모 방송 서비스를 구축하거나 컨텐츠 가공이 필요할 경우에는 중앙 미디어 서버를 구축할 필요성이 생긴다. 이런 경우 목적에 따라 두가지 아키텍처를 고려해볼 수 있다고 하지만 내게 현실적으로 필요한 문제가 아니기에 가뿐히 넘어가 준다.. ㅠㅠ 다자간의 스트리밍이나 브로드캐스팅 아키텍처에 대해 궁금하신 분들은 MCU (Multipoint Control Unit), SFU(Selective Forwarding Unit)에 대해 읽어보시면 될 것 같습니다..
그래서 내가 해야할 것은 뭔가..?
- 시그널링 서버 + Session control message 교환을 위한 Websocket 클라이언트
- WebRTC에서 지원하는 비디오 오디오 인코더
- Server-to-Peer 클라이언트 작성!
27/07/2021... WebRTC ICE Candidate에 대하여
배포 후 여러 브라우저와 네트워크 환경에서 테스트를 하면서 찾은 정보와 문제점들에 대해 적는다. 보통 가정집에 설치된 LG, SKT, KT 인터넷 + LTE연결에는 문제 없이 연결 되는 것을 확인했다. 몇몇 커피샵에서 제공하는 Wifi는 연결이 안되는 곳도 있었고, 사내에서 쓰는 네트워크는 (내가 테스트 할 수 있는 한도 내에서...) STUN을 통한 P2P 연결에 실패했다. 아마도 사내 NAT의 보안정책에 따라서 udp를 차단 할 수도 있고 ICE 와 관련된 패킷을 드랍할 수도 있다고 한다.. 현재 기기가 속해 있는 네트워크 환경에 대한 정보는 https://test.webrtc.org/ 또는 크롬의 내부 로깅 툴 chrome://webrtc-internals 에서 확인 할 수 있다.
ICE Candidate - RFC 5245
브라우저와 워커 모두 네트워크 연결에 대한 정보를 교환해야 한다. 이를 ICE candidate라고 하며 (직접적으로 또는 TURN 서버를 통해 경유하여) 사용 가능한 방법을 알아보자.
예를 들어 연락처를 교환할때 보통은 휴대폰 번호만을 주고받는것이 일반적이지만, 필요에 따라 집 또는 직장 번호를 교환하기도 합니다. 이 처럼 통화 가능한 연락처의 목록을 ICE candidates (ip, port, transport) 라고 부르며, 통신을 할 두 대상이 '능동'적으로 이 정보를 교환한다.
일반적으로 각각의 피어는 가장 좋은 후보에서 나쁜 후보 순서로 제안하고 연결을 위해 나아가게 됩니다. UDP (더 빠르고, 미디어 스트림이 TCP에 비해 비교적 쉽게 인터럽트로부터 회복할 수 있기 때문에) candidate이 이상적이지만, ICE 프로토콜의 표준은 TCP candidate 역시 허용한다.
LTE 네트워크에서의 브라우저에서는 RTCPeerConnection 객체에서 ICE Candidate을 수집할때 console log를 찍어보았다.
현재 네트워크에서는 2개의 ICE candidate을 볼 수 가 있다.
srflx 타입 ICE Candidate
{"candidate":"candidate:842163049 1 udp 1677729535 222.106.177.9 3678 typ srflx raddr 0.0.0.0 rport 0 generation 5 ufrag DZAW network-cost 999","sdpMid":"0","sdpMLineIndex":0}
host 타입 ICE Candidate
user candidate: {"candidate":"candidate:2184699491 1 udp 2113937151 a7d99160-ffd0-450c-9970-6bbea2c7f024.local 58212 typ host generation 6 ufrag 4tuu network-cost 999","sdpMid":"0","sdpMLineIndex":0}
ICE Candidate은 총 4가지의 타입 host, srflx, prflx, relay가 있다.
- Host 타입: 호스트 후보는 호스트의 인터페이스(VPN 인터페이스를 포함하여 물리적 또는 가상)에 연결된 실제 IP 주소
- srflx 타입: server reflexive candidate는 STUN / TURN 서버에 의해 식별된 IP 주소로, 클라이언트의 공인 IP 주소
- prflx 타입: peer reflexive candidate는 각 피어에 의해 식별된 IP 주소, 각 피어간 STUN Check를 통하여 식별된 IP 주소
- relay 타입: relay candidate는 server reflexive candidate( “srflx”)처럼 생성되지만 STUN 대신 TURN을 사용 함
TODO
개발 중에 호스트 타입과 srflx타입의 candidate은 네트워크 환경에 관계없이 매번 볼 수 있었고, prflx타입의 candidate은 나오지 않았으며, relay는 아마 TURN서버를 운용하고 RTCPeerConnection 객체를 생성할때 설정으로 iceServers 객체를 파라미터로 넘길때 추가를 해주어야 candidate으로 나오는 것 같다. srflx타입의 candidate을 STUN이 발견하여 알려줬다면, 외부에서 연결할 수 있는 candidate이라는 건데... 사내 혹은 건물의 NAT에서 P2P연결을 어떤 방식으로 막는지 알아봐야 할 것 같다. 알아야 우회를 하던... 또 다른 해결방법을 찾을 수 있을텐데..
출처 및 참고자료:
https://webrtcforthecurious.com/
https://www.html5rocks.com/en/tutorials/webrtc/basics/
https://www.cloudbees.com/blog/webrtc-issues-and-how-to-debug-them
'remote-craft' 카테고리의 다른 글
RemoteCraft 07 - Websocket (feat. Lobby) (0) | 2021.07.25 |
---|---|
RemoteCraft 05 - WebRTC Pion! (0) | 2021.07.23 |
RemoteCraft 03 - 계획 01 + 비디오 파이프라인 이야기... (0) | 2021.07.19 |
RemoteCraft 02 - Libretro 00 (0) | 2021.07.19 |
RemoteCraft 01 - 계획 00 (0) | 2021.07.13 |