Earn this, Earn it.
Agora SDK로 WebRTC 구현하기 - 이론편 본문
프로젝트에 대해선 Github Link 에서 확인해볼 수 있습니다. :)
이번 프로젝트에서는 WebRTC라는 최근 핫한 기술을 적용해봄으로써 기술적 도전을 해보기로 했습니다.
제일 처음으로 WebRTC API와 바닐라 JS만을 이용해 구현해봤는데, 서버측 인프라가 충분치 않은 환경에서 Mesh구조로 구현할 수 밖에 없었고, 이와 같은 Mesh 구조는 다중 사용자가 이용하는 저희 프로젝트에서는 적합하지 않다고 판단했습니다.
그래서 저희는 Agora SDK를 이용하기로 하였는데 리액트 관련 예제가 없어서 어려움을 겪었기 때문에 제가 공식문서를 공부하면서 정리한 튜토리얼을 공유해볼까 합니다.😁
최대한 많은 블로그와 공식문서를 참고했으나 요약하는 과정에서 잘못 해석된 내용이 있을 수 있습니다. 잘못된 점이 있으면 언제든지 지적 환영합니다 ( _ _ )
일단 이번 글에서는 WebRTC이론과 Agora로 어떤 이점을 얻을 수 있는지 알아보고
"왜 우리가 Agora를 사용했는지" 말씀드리겠습니다...!
일단 WebRTC란 무엇일까요?
WebRTC(Web Real-Time Communication)는 브라우저 내 RTC를 위해 Google에서 개척한 오픈 소스 프로토콜입니다. 추후 W3C(World Wide Web Consortium)에서 브라우저 사양의 일부로 표준화하였습니다.
더 자세히 살펴보면, WebRTC(Web Real-Time Communication)이란 말그대로 실시간 커뮤니케이션을 위한 기술로서 텍스트, 파일 뿐만 아니라 음성 및 영상 미디어 데이터를 중간 서버를 거치지 않고 브라우저끼리 주고 받을 수 있는 기술입니다. 별도의 플러그인 등이 없이 P2P(peer-to-peer network)로 연결하여 화상회의 및 데이터 공유를 합니다.
WebSocket ? WebRTC?
WebSocket이란 말도 들어보셨을 겁니다. 이 둘의 차이는 무엇일까요?
WebSocket은 TCP 프로토콜을 통해 클라이언트와 서버 사이의 양방향 통신을 위한 기술이고,
WebRTC는 UDP를 이용해 클라이언트 간에 직접 데이터를 주고받는 기술입니다.
또한 WebRTC는 모든 브라우저에서 지원하는 것은 아니니 기술을 적용함에 있어 주의해야 할 것입니다.
WebRTC를 본격적으로 알아보기에 앞서
이를 위한 두 가지 서버에 대해 알아보겠습니다.
1. Signaling Server(필수, 상대방의 정보를 얻기 위해)
2. Media Server(선택, 데이터 전송 방식이 P2P 방식이 아닌 중간 서버를 통하는 것)입니다.
그럼 WebRTC를 구현하는 방법은 두 가지를 생각해볼 수 있겠네요
1. Signaling Sever + P2P (직접 데이터 교환)
2. Signaling Server + Media Server (중간 서버를 거쳐서 데이터 교환)
1. Signaling Server
클라이언트가 다른 클라이언트와 통신을 하기 위해서는 상대방이 누구인지를 먼저 파악해야 합니다. 이를 위해 필요한 것이 시그널링 서버입니다. 상대방의 메타정보를 어딘가로부터 전달 받아야 하는데, 이런 이유로 인해 시그널링 서버를 별도로 구축해야 하며, 이 서버는 상대방 주소를 전달받는 역할 외에 다양한 기능을 수행하게 됩니다. 상대방의 접속 정보 또는 영상 코덱 정보 등을 실시간으로 전달해야 하고 접속이 끊겼다는 것도 알려줘야 합니다. 그래서 대부분의 경우 클라이언트와 시그널링 서버의 통신은 WebSocket으로 구축하는 경우가 많습니다.
시그널링 서버에서 정보 교환해야 할 것들
- 통신을 열고 닫기 위한 세션 컨트롤 메세지들 ( Session Control Messages )
- 에러 메세지들 ( Error Messages )
- 코덱 (Codecs)
- 대역폭 (Bandwidth)
- 미디어 유형 (Media Types)
- IP 주소 (Ip Addresses)
- 보안 키
- etc...
시그널링 서버의 동작 원리
1. SDP 교환
SDP란 (Session Description Protocol) WebRTC에서 스트리밍 미디어의 해상도나 형식, 코덱 등의 멀티미디어 컨텐츠의 초기 인수를 설명하기 위한 프로토콜입니다.
SDP는 응답 모델(Offer/ Answer)을 갖고 있어서
(1) 어떤 피어(Client 1)가 미디어 스트림을 교환할 것이라고 다른 피어(Client 2)에게 제안을 하면,
(2) 상대방으로부터 응답이 오기를 기다립니다.
(3) 그 후 응답을 받게 되면 이 과정이 끝나게 됩니다.
(왠지 전 TCP 프로토콜의 3-way handshake가 생각나네요 ㅎㅎ 물론 다른 겁니다!)
2. ICE candidate
이후 Client 1과 Client 2는 서로의 주소 값을 알아내기 위해 ICE Candidate(ICE 후보)를 교환하게 됩니다.
ICE란 peer끼리 P2P 연결을 가능하게 하도록 최적 경로를 찾아주는 프레임워크이고,
여기서 Candidate는 IP 주소와 포트 넘버의 조합으로 표시된 주소를 말합니다.
SDP를 통한 제안 및 응답이 끝나게 되면, 각자의 peer가 수집한 ICE 후보 중에서 최적의 경로를 결정하고 협상하는 프로세스가 발생합니다.
(1) 각 Peer는 ICE 후보들을 수집하고
(2) 이 ICE 후보들에게 패킷을 보내 가장 지연 시간이 적고 안정적인 경로를 찾게 됩니다.
(3) 이렇게 최적의 ICE 후보가 선택되면, 이 과정이 끝나게 되고 기본적으로 필요한 모든 메타 데이터와 IP 주소 및 포트, 미디어 정보가 피어 간 합의가 완료됩니다.
이후 P2P 연결이 완전히 설정되고 활성화되며 로컬 데이터 스트림의 양방향 통신이 가능하게 됩니다.
여기서 중간 다리 역할을 해주는 것이 바로 시그널링 서버입니다.
그렇다면 위의 그림에서 STUN 서버는 무엇일까요?
STUN서버? TURN서버?
아래와 같은 상황을 예로 들어봅시다!
(1) ICE가 UDP를 통해 Client1과 Client2의 직접 연결을 시도합니다.
- ✅(연결 성공!) 이제 미디어 데이터 교환 단계로 넘어갑니다! (끝)
- ❓ (연결 실패..) NAT 혹은 Firewall 뒤에 있는 것 같습니다!
NAT(Network Address Translation) 은 기기에 공인 IP를 부여하는 기술입니다. 보통 라우터에 설정하는데, 라우터는 공인 IP 를 갖고, 라우터에 연결된 모든 기기는 사설 IP(Private IP) 를 갖습니다. 기기가 요청할 것이 생기면, 라우터의 고유한 포트를 사용해서 사설 IP 에서 공인 IP 로 변환합니다(translation). 어떤 라우터는 접근할 수 있는 노드를 제한 할 수도 있습니다.
(2) NAT? 그럼 STUN 서버가 이를 해결해줄테니 STUN서버를 이용해봅시다!
Client 1은 STUN 서버에 요청을 보낸 후 다른 기기와 직접 연결을 시도합니다.
- ✅(연결 성공!) 미디어 데이터 교환 단계로 넘어갑니다!
- ❓ (연결 실패..) TURN 서버가 필요합니다...!
STUN (Session Traversal Utilities for NAT) 는 기기의 공인 IP를 알려주고 기기의 NAT가 직접 연결을 허용하는지 아닌지 파악하는 역할도 합니다
(3) TURN 서버가 Client 1과 Client 2과 연결을 맺고 모든 교환 과정을 중개합니다.
클라이언트는 이 TURN 서버를 이용해 패킷을 주고 받습니다.
TURN (Traversal Using Relays around NAT) 는 Symmetric NAT 의 제약조건을 우회하기 위해서 만들어졌습니다. TURN 서버와 연결을 맺고, 이 서버가 모든 교환 과정을 중개해줍니다. 모든 기기는 TURN 서버로 패킷을 보내고, 서버가 이를 포워딩하므로 당연히, 오버헤드가 있고 다른 대안이 없을 때만 사용하는 것이 좋습니다.
WebRTC의 연결은 기본적으로 UDP를 통한 연결으로 이루어져 있지만 위와 같이 TURN서버를 이용하게 되면 TCP를 통해 수행되며 위에서 말한 대로 네트워크 트래픽을 릴레이하여 통신합니다.
2. Media Server
이제 드디어 미디어 데이터를 교환하는 단계로 왔습니다!
미디어 서버 개념은 위에서 설명한 시그널링 서버와는 궤가 다릅니다.
WebRTC는 기본적으로 P2P 방식으로 동작합니다. 그래서 만약 N:M이나 1:N을 구현하기 위해서는 Mesh 구조를 가져가야 합니다.
이는 모든 피어간 연결이 필요하기 때문에 네트워크 리소스를 매우 많이 잡아먹고 각 클라이언트에 부담을 굉장히 많이 주게 되므로 중간에 중계를 해주는 서버가 하나 필요한데 이것이 바로 Media 서버입니다.
미디어서버를 통한 WebRTC의 두가지 종류
위에서 말한것 처럼 다자간에 대한 WebRTC 통신은 많은 제약사항을 가지고 있기 때문에 중간에 미디어서버를 통해 통신을 하게 되는데 두가지로 나뉩니다.
SFU (Selective Forwarding Unit) 방식
SFU 방식은 단순히 받은 데이터를 연결된 Peer들에게 뿌려주는 것을 말합니다. 중간 처리를 하지 않고 그대로 보내주기 때문에 서버에 부하가 상대적으로 적은 방식입니다. 서버는 각 Peer 간 연결 할당과 암호화 및 복호화 하는 역할을 담당하며 1:N 스트리밍 구조에 적합합니다.
MCU (Multi-Point Control Unit) 방식
MCU 방식은 중앙에서 비디오를 인코딩 등과 같은 전처리를 하여 피어에게 다시 전달 해 주는 역할을 합니다. 즉, 중간에서 믹싱을 해주며 인코딩을 통해서 압축률을 좋게 하여 각 피어들에게 던져주면 네트워크 리소스 비용에서는 유리하나 중앙에서 처리해주는 서버의 CPU리소스를 많이 잡아먹는다는 단점이 있습니다. 다만 서버의 운용 비용이 높아 WebRTC와 같은 실시간 보장이 우선인 서비스의 경우 장점이 상쇄될 우려가 있습니다.
3가지 방식에 대한 비교 그림
그렇다면 Agora가 제공하는 솔루션은 어떤 것일까?
1. 데이터 중계(Media Server) 및 TURN/STUN(Signaling Server) 서버 유지 관리
기존 WebRTC는 데이터를 중계하고(SFU인지 MCU인지는 모르겠네요) IP 주소를 얻기 위해 각각 TURN/STUN 서버를 유지 관리합니다. Agora의 WebRTC는 이 모든 작업을 추상화하여 수행해주며 따라서 관리해야 할 하드웨어 오버헤드가 줄어들고 프로세스가 간단해집니다. 이를 통해 구현 비용이 줄어들고 복잡성도 크게 줄어드는 장점이 있습니다.
2. 네트워크 제공
데이터 처리 전용 데이터 센터가 전 세계에 200개 이상 분산되어 있어서 부드럽고 빠른 데이터 전송을 보장하며 오디오 및 비디오용 독점 고성능 SOLO 및 NOVA 코덱을 실행하여 밀리초의 대기 시간을 보장하고 패킷 손실에 대한 극도의 복원력을 나타내는 지능형 동적 라우팅을 제공합니다. 이는 실시간 통신을 위해 특별히 설계된 가상 및 UDP(사용자 데이터그램 프로토콜) 기반 네트워크 아키텍처입니다.
3. 확장성
기존 WebRTC에 대해 Mesh 연결 아키텍처가 아닌 모든 피어가 서로에 대한 데이터를 얻는 채널 기반 아키텍처를 활용해 중복 연결을 방지합니다.
결론.
저희는 말씀드린 대로 P2P방식과 미디어 서버를 이용하는 방식 중에 고민하였는데요.
미디어 서버를 이용할 때에도 SFU를 택해서 직접 미디어 서버를 구현할 것인지
MCU방식을 제공해주는 플랫폼을 이용할 것인지 고민했습니다.
결국에 저희는 다중 사용자를 위한 서비스이기 때문에 P2P의 한계로 미디어 서버를 이용해야 했고, 6주 동안 미디어 서버를 구현하는 것은 무리라고 판단하여 클럽하우스에서도 사용하고 있는 Agora.io의 SDK를 이용하였습니다.
그림에서 보시는대로 아고라는 주로 MCU방식으로 데이터를 중계하고 IP 주소를 얻기 위한 TURN/STUN 서버를 각각 유지 관리하여 제공해줍니다. 또한 추상화가 굉장히 잘 되어 있다는 장점이 있었고 다양한 기능을 제공하는 SDK이다 보니 확장성에도 유리할 것이라 판단하였습니다.
다음 포스팅에서는 본격적으로 React와 Typescript를 적용하여 단계별로 WebRTC를 구축해보겠습니다!
출처
https://withseungryu.tistory.com/130?category=917456
[WebRTC] Signaling Server ( 시그널링 서버 )
WebRTC에 대해서 이야기를 해봤는데 WebRTC를 유기적으로 잘 사용하기 위해서는 아래와 같은 서버가 필요하다. Signaling - Always needed NAT Traversal - need for production Media - depends on the app 이번..
withseungryu.tistory.com
https://brunch.co.kr/@springboot/640
2. 화상 회의 서비스를 위한, WebRTC 소개
Overview 작년 코로나 이후로, 필자는 계속 재택근무를 하고 있는데, 거의 매일 화상 회의를 하고 있다. 코로나가 당장 없어지지 않는다면 집에서 화상 회의로 팀원들과 온라인으로 대화하는 삶
brunch.co.kr
https://devji.tistory.com/entry/WebRTC-%EB%9E%80-%EC%86%8C%EA%B0%9C-%EA%B0%9C%EC%9A%94
WebRTC 란? (소개, 개요)
WebRTC (Web Real-Time Communication) WebRTC는 웹 브라우저, Andoird, iOS 등에서 사용 가능한 P2P 음성, 비디오, 데이터 교환 솔루션이라고 볼 수 있습니다. 구글이 개발하여 오픈 소스화 하였고 그 뒤로 IETF(..
devji.tistory.com
https://www.agora.io/en/blog/past-present-future-of-webrtc/
The Past, Present, and Future of WebRTC
Agora presents a deeper look into WebRTC technology, where it originated, current use cases and future applications, plus a demo tutorial on how to build your own WebRTC app.
www.agora.io
https://developer.mozilla.org/ko/docs/Web/API/WebRTC_API/Protocols
WebRTC 프로토콜 소개 - Web API | MDN
이 글은 WebRTC API에 대한 프로토콜을 소개하기 위해 작성 되었습니다.
developer.mozilla.org
https://andonekwon.tistory.com/71?category=447798
WebRTC란? (시그널링 과정 feat. Kurento Media Server) (3)(작성중)
이전 글 복습 NAT 환경 같은 경우에는 자신은 Private IP를 가지고 있어서 시그널링을 할 때 Peer to Peer로 통신을 할 수 있는 방법이 없다. 따라서 자신의 퍼블릭 IP를 알아내기 위해 STUN서버를 통해서
andonekwon.tistory.com
210307 개발일지(90일차) - 정글 나만의 무기 프로젝트 - WebRTC란 무엇인가?(2) : ICE, SDP, Signalling
위의 STUN, TURN 등으로 찾아낸 연결 가능한 네트워크 주소들을 Candidate(후보)라고 할 수 있다.ICE라는 프레임워크에서 Finding Candidate(후보 찾기)를 한다. 보통 3종류의 후보들을 갖게되는데, 그 종류
velog.io
https://brunch.co.kr/@linecard/156#comment
30장. ICE의 이해
1. ICE의 개요 ICE는 Interactive Connectivity Establishment의 약어로 RFC 5245 A protocol for Network Address Translator (NAT) Traversal for Off/Answer Protocols에 정의되었습니다. ICE는 두 단말이 서로 통신할 수 있는 최적
brunch.co.kr
https://juneyr.dev/webrtc-basics
실시간 통화 어떻게 하는 거지 : WebRTC 기초
WebRTC 를 공부하기로한다. WebRTC가 뭔데 - 이름 그리고 비전 webRTC는 plugin-free web - Real Time Communication 이다. 그러니까 별도의 플러그인 설치없이 실시간 소통(비디오, 오디오) 이 가능하도록 만들어
juneyr.dev
'[개발 공부]' 카테고리의 다른 글
TIL - defer/async 와 ssr/csr (0) | 2021.11.17 |
---|---|
TIL - [OSI 7계층] IP 주소에 대해서 (네트워크 계층) (0) | 2021.11.13 |
TIL - 데이터베이스와 인덱스 (0) | 2021.10.30 |
TIL - React 함수형과 훅(hooks)에 대해서 (0) | 2021.10.11 |
TIL - 식별관계와 비식별관계 (0) | 2021.09.28 |