작년 캡스톤 디자인, 하계 오픈소스 해커톤에서 개발하였던 화상채팅을 개발하며 배운 내용과 그 과정을 설명하겠습니다.
줌, 구글 미트와 같은 화상채팅 플랫폼처럼 다양한 기술을 종합하지는 않았지만 기본적인 화상채팅을 구현하는 과정에 대한 설명을 여러 포스트를 통해 살펴보겠습니다.
화상채팅은 무엇으로 개발할까요?
화상채팅은 WebRTC라는 기술로 개발할 수 있습니다.
WebRTC란
Web real-time communications의 약자로 웹 어플리케이션 및 사이트들이 별도의 소프트웨어 없이 음성, 영상, 미디어 혹은 텍스트, 파일 같은 데이터를 브라우저끼리 주고 받을 수 있게 만든 기술입니다.
https://developer.mozilla.org/ko/docs/Web/API/WebRTC_API
WebRTC의 장점
WebRTC의 장점으로는 Laytency가 짧아 Real-Time과 비슷한 스트리밍이 가능하고,
별다른 소프트웨어 없이 실시간 커뮤니티가 가능하다는 점이 있습니다.
WebRTC의 단점
WebRTC에도 단점이 존재합니다.
- 먼저 크로스 브라우징 이슈가 존재합니다.
WebRTC의 구현이 계속 진화하고 있으며 각 브라우저마다 다른 코덱 및 기타 미디어 기능에 대한 지원 수준이 다르기 때문에, 코드 작성을 시작하기 전에 Google에서 제공하는 Adapter.js 라이브러리를 사용하는 것을 강력하게 고려해보아야합니다.
MDN에서는 위와 같이 설명하고 있습니다. 필자는 아직 Adapter.js를 사용하지는 않았지만 Adapter.js를 분석하는것도 WebRTC를 구현하는데 큰 도움이 될 것이라 판단됩니다.
- **STUN/TURN서버가 꼭 필요합니다. **
p2p,즉 peer to peer 통신을 하기 위해서는 상대방의 ip주소를 얻어야 합니다.
대부분의 사용자는 방화벽을 사용하기 때문에 다른 네트워크 상에서 연결을 지원하기 위해 두 서버가 필요합니다.
WebRTC 통신 원리
다음으로는 WebRTC의 통신 원리에 대해서 살펴보겠습니다.

그림을 간략히 단계별로 설명하자면 다음과 같습니다.
- 각 브라우저가 P2P커뮤니케이션에 동의합니다.
- 서로의 주소를 공유합니다.
- 보안 사항 및 방화벽을 우회합니다.
- 멀티미디어 데이터를 실시간으로 교환합니다.
2,3번 단계는 웹 개발의 접근 방법으로 해결하기 어려운점이 존재합니다.
브라우저는 웹서버가 아니기 때문에 외부에서 접근할 수 있는 주소가 필요합니다.
이를 위해 p2p 기반이지만 설정 초기 단계에서 중재자 역할이 필요합니다.
상대방의 IP를 알아내는 방법, NAT 트래버셜
IP는 각 기기의 이름과도 같습니다.
IP는 고정, 유동으로 나뉘어서 실제 고유값일 수도, 아닐 수 도 있습니다. 더 나아가 회사망, 내부망은 Private IP이기 때문에 다른 네트워크에서는 통용되지 않습니다.
그래서 우리는 통상적인 네트워크에서 데이터를 주고 받기 위해서는 Public IP가 필요합니다.
** public ip?란**
통신사isp로 부터 회선을 구매하여 할당 받은 이터넷 주소로, 전 세계적으로 유일한 값입니다.
private ip와의 차이점은 private ip는 사설 아이피로 로컬 아이피, 가상 아이피라고도 합니다.
IPv4의 주소가 부족함에따라 따로 서브넷팅한 ip이기 때문에 라우터에 의해 로컬 네트워크 상의 pc나 장치에 할당됩니다.
하지만 일반적으로 컴퓨터에는 public ip가 할당되지 않습니다.
그 이유로는
- 방화벽
- 여러대의 컴퓨터가 하나의 공인 ip를 공유하는 NAT
- 유휴 상태의 ip를 일시적으로 임대받는 DHCP 때문입니다.
DHCP는 호스트에게 ip와 각종 tcp/ip 프로토콜을 기본적으로 자동으로 세팅해주는 프로토콜입니다.
공인 ip 뿐만아니라 해당 네트워크에 연결된 사설 IP주소까지 알아내야 특정한 사용자를 지정할 수 있게됩니다.
일반적으로는 라우터가 NAT의 역할을 수행하여 외부에서 접근하는 공인 IP와 포트번호를 확인해 현재 네트워크 내의 사설 IP들을 적절히 매핑시켜줍니다.
따라서 브라우저 두 개가 서로 직접적인 통신을 하기 위해서는 각자 연결된 라우터의 공인 IP주소와 포트를 먼저 알아내야 합니다.
하지만 어떤 라우터들은 특정 주소나 포트와의 연결을 차단하는 방화벽 설정이 있을 수 있습니다.
이처럼 라우터를 통과하여 연결할 방법을 찾는 과정을 바로 NAT트래버셜이라고 합니다.
STUN/TURN
NAT트래버셜 작업은 STUN(Session Traversal Utilities for NAT) 서버에 의해 이루어집니다.
STUN 방식은 단말이 아닌 자신의 Public IP 주소와 포트를 확인하는 과정에 대한 프로토콜입니다.
즉 STUN 서버는 인터넷의 복잡한 주소들 속에서 유일하게 자기 자신을 식별할 수 있는 정보를 반환해줍니다.
WebRTC 연결을 시작하기 전에 STUN서버에 요청을 보내면, STUN서버는 NAT뒤에 있는 피어들이 서로 연결할 수 있도록 Public IP와 포트를 찾아줍니다.
STUN방식이 항상 효과적이지는 않습니다. 구 기기가 같은 NAT환경에 있을경우, 또는 NAT의 방화벽 정책이 다른 경우, 이전에 연결된 적이 있는 네트워크만 연결되게 제한하는 경우도 있습니다.
따라서 STUN서버를 통해 자기 자신의 주소를 찾지 못했을 경우 TURN서버를 대안으로 이용하게 됩니다.
TURN은 STUN의 확장으로 NAT환경에서 릴레이하여 통신을 하게 됩니다.
NAT보안 정책이 너무 엄격하거나 NAT순회를 하기 위해 필요한 NAT바인딩을 성공적으로 생겅할 수 없는 경우에 TURN을 사용합니다.
TURN서버는 인터넷 망에 위치하고 각 피어들이 사설망 안에서 통신합니다. 각 피어들이 직접 통신하는 것이 아니라 릴레이 역할을 하는 TURN서버를 사용하여 경우합니다.
이 경우 중간에 서버를 한 번 거치기 때문에 엄밀히 말하자면 p2p 통신이 아니게 되며, 또한 구조상 어느정도의 지연이 발생합니다.
하지만 보안 정책이 엄격한 개인 NAT내부에 위치한 브라우저와 p2p 통신을 할 수 있는 유일한 방법이기 때문에 TURN방식은 최후의 수단으로 선택되어야 합니다.
ICE Candidate
STUN,TURN서버를 이용해 얻은 IP주소와 프로토콜, 포트의 조합으로 구성된 연결 가능한 네트워크 주소들을 바로 후보, Candidate라고 부릅니다.
그리고 이 과정을 후보 찾기, Finding Candidate라고 합니다.
위 과정으로 후보들을 수집하면 일반적으로 3개의 주소를 얻게됩니다.
- 자신의 사설ip, 포트넘버
- 자신의 공인ip, 포트넘버
- TURN서버의 ip와 포트넘버
이 모든 과정은 ICE(Interactive Connectivity Establishment)라는 프레임워크 위에서 이루어집니다.
ICE는 두 개의 단말이 p2p 연결을 가능하게 하도록 최적의 경로를 찾아주는 프레임워크입니다.
이제 두 브라우저가 p2p통신을 할 수 있는 주소를 얻었습니다.
남은 과정으로는 미디어와 관련된 정보를 교환하는 것입니다.
SDP
Session Description Protocol은 WebRTC에서 스트리밍 미디어의 해상도나 형식, 코덱 등의 멀티미디어 컨텐츠의 초기 인수를 설명하기 위해 채택한 프로토콜입니다.
미디어와 관련된 초기 세팅 정보를 기술하는 SDP는 발행 구독 모델과 유사한 제안 응답 모델을 갖고있습니다.
특정 피어가 아닌 미디어 스트림을 교환할 것이라고 제안을 하면, 상대방으로 부터 응답이 오기를 기다린다는 의미입니다.
그렇게 응답을 받으면, 각자의 피어가 수집한 ICE후보(네트워크 주소들의 구성)중에서 최적의 경로를 결정하고 협상하는 프로세스가 진행됩니다.
수집한 후보들로 패킷을 보내 가장 지연시간이 적고 안정적인 경로를 찾아 최적의 후보를 선택합니다.
이를 통해 기본적으로 필요한 모든 메타 데이터와 IP주소 및 포트, 미디어 정보, 피어 간 합의가 완료됩니다.
위 과정을 통해 피어간 p2p연결이 완전히 설정되고 활성화됩니다.
그 후 각 피어에 의해 로컬데이터 스트림의 엔드포인트가 생성되며, 이 데이터는 양방향 통신기술을 사용해 서로에게 전송됩니다.
ICE 후보들을 모으고 교환하고... 이걸 다 기다릴까?
일반적으로 각 피어는 ICE후보를 수집하고 목록을 완성시킨 후, 한꺼번에 교환을 합니다.
하지만 이런 방식은 SDP의 제안 응답 모델과 맞물리면서 단점으로 작용합니다.
후보를 모으는데 시간이 걸리고 그 과정에서 또 네트워크 환경에 따라 지연이 걸릴수 있습니다.
또한 한쪽 피어의 후보수집이 완료되어야만 다른 피어가 후보를 모을 수 있기 때문에 비효율적입니다.
이러한 비효율적인 후보교환 작업을 병렬 프로세스로 수행할 수 있게 만드는것이 바로 Tricle ICE입니다.
Tricle옵션이 활성화된 ICE프레임워크는 각 피어에서 ICE후보를 찾아내는 즉시 교환을 시작합니다.
그래서 상호간 연결가능한 ICE를 보다 빠르게 찾아내어 시간을 최적화합니다.
위의 모든 과정, Signaling
앞에서 이야기한 모든 과정을 일컬어 시그널링이라고 부릅니다.
즉, RTCPeerConnetion통신에 사용할 프로토콜, 채널, 미디어코덱 및 형식, 데이터 전송 방법, 라우팅 정보와 NAT통과 방법을 포함한 통신 규격을 교환하기 위해 두 장치의 제어 정보를 교환하는 과정을 의미합니다.
시그널링은 WebRTC 자체에서 지원하는 기능이 아닙니다. WebRTC 연결 전 미리 준비해야하는 과정입니다. WebRTC 자체의 스펙도 아니므로, 한 가지로 정해진 방법이 있지 않습니다.
직접 시그널링 서버를 구축한다면 보통 웹 소켓을 이용한 방법을 선택합니다.
WebRTC에 대한 전반적인 내용을 간략히 설명했습니다.
해당 기술을 직접 구현하는 과정을 통해 학부 수업에서 배우는 여러 개념들을 다뤄볼 수 있다는 점에서 굉장히 매력있는 프로젝트가 될것이라 생각합니다 :)
다음 포스트에서는 어떻게 구현하는지에 대한 설명을 하겠습니다.
많은 도움을 받은 블로그
https://kbs77.tistory.com/102
https://kbs77.tistory.com/94