🤔 WebRTC?
Published: 2021-04-05 14:32:58

> 📝 궁금한 모든 것을 기록합니다.
> 😎 기록에서 멈추지 않고 나의 것으로 만듭니다.
> 🙈 잘못된 정보가 있다면 언제든지 댓글에 남겨주세요 :D

# 🤔 WebRTC?
Web Real-Time Communication의 약자로 실시간으로 웹 어플리케이션(또한 android, ios도 지원)에서 데이터를 교환할 수 있는 기술이다. 여기서 중요한 점은 별도의 소프트웨어의 도움 없이(드라이버, 플러그인 없이) 실시간으로 통신을(p2p) 가능하게 해준다는 것이다. 영상, 음성 및 데이터 통신을 하는 자바스크립트 API라고 할 수 있다.(대부분의 브라우저에서 지원해주고 있다.=>IE는 지원되지 않는다..., 크로스 브라우징이슈를 해결하기 위한 [라이브러리 adapter.js](https://github.com/webrtcHacks/adapter)) WebRTC를 통해 음성통화, 비디오채팅 및 파일 공유를 위한 웹-앱 어플리케이션을 만들 수 있다.

## 😄 WebRTC에 대한 또다른 정보!
- 구글에서 음성/영상 코덱 및 에코 캔슬링 기술을 가진 2개의 회사를 인수한 후, 투자와 개발을 거처 2011년도에 WebRTC를 오픈소스화하여 API 형태로 공개했다.
- WebRTC가 있기 전에는 웹에서 화상 통신을 하기 위해선 사용자가 별도의 플러그인을 설치해야하는 번거러움 있었다. 그러나 WebRTC로 인해 이런 문제를 해결되었다. 
- W3C에서 WebRTC의 표준과 API 정의를 위해 노력하고, IETF(국제 인터넷 표준화 기구)에서 프로토콜의 표준화 작업을 시작했다. 
- WebRTC는 구글뿐 아니라, Mozilla, Opera 등과 같은 웹브라우저 주요 기업들의 전적인 지원을 받는다. 

## 😍 WebRTC를 이해하려면 필요한 지식!
- **NAT(Network Address Translation)**
NAT은 해당 기기의 공인(public) IP를 부여하는데, 라우터가 공인 IP를 가지고 있고, 여기에 연결된 기기는 사설(private) IP 주소를 갖게된다. 공인IP는 유일한 IP며, 사설IP는 특정 네트워크 안에서만 유효하다. 
여기서 공인IP는 실제 주소와 같고 외부에 공개되어 있다. 그렇기에 다른 컴퓨터에서 검색, 접근이 가능하다. 그렇기 때문에 공인IP를 사용하려면 보안 방화벽이 반드시 필요하다. 
사설IP는 외부에 공개되지 않아 검색, 접근이 불가능하다. 주로 인터넷을 사용할 때, 라우터에 공인IP를 두고 그 라우터에 여러대의 디바이스들이 사설IP를 가지고서 접속하게 된다.
다시 NAT에 대해 설명하게 되면, 통상적으로 네트워크에서 데이터를 주고 받기위해선 공인 IP가 필요하다. NAT은 사설IP를 공인IP로 1대1 대응시켜 변환하는 장치이다. 
여기서 WebRTC는 P2P 방식으로 서로의 정보(공인IP)를 알아야한다.

- **Signaling**
RTCPeerConnection이 생성되기 전에 서로 다른 네트워크의 기기끼리 서로의 위치 확인과 미디어 포멧에 대한 협의를 하는 프로세스를 시그널링이라 부른다. 

- **Signaling Server**
P2P 통신을 위해 서로를 연결해주는 역활을 한다. 
1. 브라우저가 사용자의 장치에 접근한다. 
2. Signaling 서버를 통해 상대방의 정보를 얻는다. 
3. Peer to Peer connection을 통해 통신한다. 
즉, 각 Peer가 연결되기 위해선 Signaling 서버에 먼저 접근하여 상대방의 정보를 알아낸 후 P2P Connection을 한다. Caller가 상대 사용자에게 Signaling서버를 통해 자신의 정보들을 제공하고, Callee는 그 정보들에 대해 자신의 정보를 담아 답장한다. 
Signaling 서버에서 교환해야 할 정보들은 세션 제어 메세지(통신을 초기화하거나 닫고 오류를 보고한다), IP주소/포트, 보안키, 코덱/해상도, 에러메세지, 미디어 유형, 등이 있다. 
Signaling 서버는 직접 구축해도 되고([WebSocket](https://developer.mozilla.org/ko/docs/Web/API/WebSocket), SPI, XMPP/Jingle, Netty), cloud message platform(Pusher, Kaazing, PubNub), [아마존의 Kinesis Video Stream ](https://github.com/awslabs/amazon-kinesis-video-streams-webrtc-sdk-js), [구글의 AppRTC에서는 Google App Engine으로 구현된 시그널링 서버](https://github.com/webrtc/apprtc)을 사용해도 된다. 
	* [다양한 시그널링 서버의 구현 방법](https://github.com/muaz-khan/WebRTC-Experiment/blob/master/Signaling.md)

- **SDP (Session Description Protocol)**
SDP는 P2P로 서로 주고받는 데이터를 이해하는데 사용된다. 
데이터의 해상도, 형식, 코덱, 암호화 방법 등을 기술하는 표준(프로토콜)이며, 메타데이터를 나타낸다. 

- **JSEP (JavaScript Session Establishment Protocol)**

- **ICE (Interactive Connectivity Establishment)**
ICE는 P2P간 통신을 위한 기술로 서로의 기기가 통신하기 위한 최적의 경로(통신 가능한 모든 주소들을 가져온다)를 찾을 수 있도록 도와주는 프레임워크이다. ICE는 최적의 경로를 찾기위해 STUN과 TURN을 사용하는 프레임워크로 SDP 제안 및 수락 모델에 적용할 수 있다. NAT환경에서 자신의 공인IP를 파악하고 상대방에게 데이터를 전송하기 위한 응답 프로토콜이라고 할 수 있다.

- **ICE Candidate**
ICE를 통해 얻게된 후보를 Candidate라 부른다. SDP를 결정한 후에는 ICE Candidate을 서로 교환하며 여러 경로중 최적의 ICE를 결정하게 한다. 이 과정에서 이미 스트리밍이 시작되어도 연결초반에 영상 저품질 현상이 일어날 수 있다. 이렇게 후보를 수집하면 일반적으로 3개의 주소를 얻게된다: 자신의 사설IP와 포트넘버 / 자신의 공인IP와 포트넘버 (STUN, TURN 서버로 부터 받는다) / TURN서버의 IP와 포트넘버 (TURN 서버로 부터 받는다.)

- **STUN 서버 (Session Traversal Utilities for NAT)**
STUN 서버는 기기의 공인 IP를 찾고 P2P 연결을 방해하는 요소가 라우터에 있는지 알아내는 프로토콜이다. 즉, 해당 Peer의 공인IP 주소를 보내는 역활은 담당한다. 또한 두 엔드포인트 간의 연결을 확인하고 둘의 연결을 유지하기 위해서도 사용할 수 있다. 그러나 항상 효과적으로 일을 처리하지 못한다. NAT의 보안 정책 등이 엄격하면 연결하지 못할 수도 있다.

- **TURN 서버 (Traversal Using Relays around NAT)**
TURN은 STUN 서버에서 연결이 실패했을 경우 오디오, 비디오 등을 릴레이 해주는 역활을 한다. TURN 서버는 인터넷망에 위치하고 각 Peer들이 사설IP안에서 통신한다. 여기서 각 Peer들이 직접적으로 통신하는 것이 아닌 릴레이 역활을 하는 TURN 서버를 사용하여 경유한다. 그렇기에 엄밀히 말하면 P2P 통신이아닌 중간에 서버(TURN)를 거치게 되며, 그 구조상 지연이 필연적으로 발생한다. 
TURN를 통해 모든 정보를 중계하고, STUN에 비해 리소스낭비가 심하기 때문에, ICE Candidate과정에서 모든 후보군을 찾은 후, 대안이 없는 경우에만 사용한다. 

## P2P 동작 과정
1. 각 브라우저가(디바이스) P2P 연결에 동의한다.
2. 서로의 주소를 공유한다. 
3. 보안사항 및 방화벽을 우회, 통과한다. 
4. 다양한 데이터를 실시간으로 교환한다. 

### 추가 설명
각 개인의 디바이스(컴퓨터)에는 공인IP가 할당되어 있지 않다. 그 이유는 보안문제(방화벽), NAT 등이 있다. 단순히 공인IP를 알아냈다고, 특정 사용자를 찾을 수 없다. 해당 네트워크(공인IP)에 연결되어 있는 사설IP(고유의) 주소까지 알아내야 특정 사용자를 지정할 수 있게 된다. 일반적으로 라우터가 NAT 역활(공인IP와 포트번호를 확인 후, 현재 네트워크에 연결된 사설IP를 연결해준다)을 담당하기 때문에 P2P 연결을 위해선 각 Peer가 연결된 라우터의 공인IP 주소와 포트를 먼저 알아야한다. 그러나 어떤 라우터는 특정 주소나 포트의 연결을 차단하는 방화벽이 설정되어 있을 수 있다. 이렇게 라우터를 통과해서 연결할 방법을 찾는 것을 NAT traversal 이라 하고, 이 작업을 STUN 서버에 의해 이루어진다. 
STUN 서버의 역활은 위에서 설명했듯이, 각 Peer가 자신의 공인 IP 주소와 포트를 확인하는 과정에 대한 프로토콜이다. 즉, 상대방과 대화를 시작하기 전에 자신의 고유 주소를 조회해서 알아내는 것이다. 그러나 다양한 방화벽 정책으로 인해 STUN 서버에서 항상 자신의 정보를 알아올 수 있는 것이 아니다. 이로인해 STUN 서버로 자신의 주소를 가지고 오지 못할 경우의 대안으로 TURN 서버를 이용할 수 있다. 
이렇게 STUN, TURN 서버를 이용해 알게된 IP주소와 포트의 조합으로 구성된 연결가능한 네트워크 주소를 Candidate라 부르고 이 Candidate를 모두 찾아내어 주소를 찾아낸다. 이 모든 과정은 ICE라는 프레임워크에서 이루어진다. 

## 😳 WebRTC의 흐름
1. Session description을 교환한다. 
- Signaling 프로세스는 call을 요청하는 유저가 offer를 만들면서 시작한다. 
- 이 offer는 session 정보를 SDP 포멧으로 가지고 있으며, callee에게 전달된다. 
- Callee는 caller에게 SDP 정보를 포함한 answer 메세지를 보낸다.
- 위의 과정을 통해 A와 B는 어떤 코덱과 어떤 video parameter들이 사용될지 알게된다. 
2. ICE candidate를 교환한다. 
- SDP 교환 이후 ICE candidate 교환이 시작된다. 
- 각 ICE candidate는 caller 입장에서 통신할 수 있는 방법을 설명한다. 
- 각 Peer는 검색되는 순서대로 candidate를 내보내고, 이미 스트리밍이 시작되어도 모든 가능한 candidate를 전송한다. 
- 각 Peer가 서로 호환되는 candidate를 제안했다면, 미디어 통신을 시작한다. 
- 추후 더 나은 방법이 있다면, 스트림의 포맷이 변경된다.
3. 미디어 전송 시작

## 😲 WebRTC의 중요 API
-  **getUserMedia()**
사용자가 자신의 디바이스를 스트림 할 수 있도록 허가를 받는 API이다. 
클라이언트 사용자 컴퓨터의 카메라와 마이크 접근을 담당한다.

- **RTCPeerConnection**
Peer간의 연결을 생성하여 오디오와 비디오 통신에 사용 하게 한다. STUN 서버가 필요한 부분이다. 이 객체는 RTCConfiguration을 인자로 받는데 연결설정 방법과 ICE에 대한 정보를 포함시켜야한다.

- **RTCDataChannel**
Peer간의 데이터를 주고 받을 수 있는 Tunnel API 이다. RTCPeerConnection을 통해 데이터를 전송시키기 위한 API이고, 이 객체에서 createDataChannel()을 호출하여 얻을 수 있다. 

- **Select sources & outputs**

- **Stream capture**

## 👀 References
- [[WebRTC] STUN 과 TURN 에 대하여 #1 - 개요](https://alnova2.tistory.com/1110)
- [Build the backend services needed for a WebRTC app](https://www.html5rocks.com/ko/tutorials/webrtc/infrastructure/)
- [WebRTC는 어떻게 실시간으로 데이터를 교환할 수 있을까?](https://wormwlrm.github.io/2021/01/24/Introducing-WebRTC.html)
- [[WebRTC] WebRTC란?](https://www.html5rocks.com/ko/tutorials/webrtc/infrastructure/)
- [[WebRTC] 웹브라우저로 화상 채팅을 만들 수 있다고?](https://velog.io/@ehdrms2034/WebRTC-%EC%9B%B9%EB%B8%8C%EB%9D%BC%EC%9A%B0%EC%A0%80%EB%A1%9C-%ED%99%94%EC%83%81-%EC%B1%84%ED%8C%85%EC%9D%84-%EB%A7%8C%EB%93%A4-%EC%88%98-%EC%9E%88%EB%8B%A4%EA%B3%A0) 


# 🤔 WebSocket?
WebSockect은 서버와 클라이언트 간에 socket connection을 유지해서 언제든 양방향 통신 또는 데이터 전송이 가능하도록 하는 기술이다. 주로 WebRTC 구현을 위해 많이 사용된다. WebSocket를 사용하는 이유는 데이터의 빠른 업데이트, 실시간 업데이트가 필요한 어플리케이션에서 매우 중요한 기술이기 때문인데, webSocket은 Stateful protocol이기 때문에 클라이언트와 한번 연결되면 계속 같은 라인을 사용해서 통신할 수 있다.(기존 웹어플리케이션에서 서버와 클라이언트는 대부분 HTTP를 통해 이루어져있고, stateless하기 때문에 클라이언트의 한 request에 한 response만 서버에서 전달되는 구조다.) 그렇기 때문에 HTTP 사용시 필요없이 발생되는  HTTP와 TCP 연결 트래픽을 피할 수 있다. 

## 😁 SocketIO?
SocketIO는 웹서버의 종류와 브라우저 버전을 파악해서 가장 적합한 기술을 사용해 WebSocket을 이용할 수 있도록 해준다. 즉, WebSocket을 지원하지 않는 구버전의 브라우저에서(IE9) socketIO로 구현된 서비스를 사용할시 polling flow로 webSocket을 따라하듯이 구현해준다.