안녕하세요, 주니어 개발자 Eon입니다.
오늘은 WebRTC에 대해 알아보겠습니다.
최근에 코로나 팬데믹으로 재택 근무가 자리 잡고, 학교는 비대면 수업을 진행하게 됐습니다.
그로 인해, 화상회의가 비대면 만남의 매개체가 돼 주고 있습니다.
화상회의는 어떻게 만들어졌는지, 어떤 기술인지 알아보겠습니다.
이후의 포스팅은 Janus Gateway를 구동 및 demo 페이지 연동을 통한 나만의 화상회의 구현 과정이 되겠습니다.
WebRTC (Web Real-Time Communication)은 브라우저 상에서 영상이나 오디오같은 미디어를 스트림하고 데이터 교환까지 할 수 있게 하는 기술입니다.
어쭙잖은 설명으로 원래의 정의나 기술에 대해 잘 전달하지 못하게 될 수 있으니 공식 문서 URL을 첨부하겠습니다.
MDN Web DOCs :: WebRTC_API
문서에서 설명하고 있듯이 WebRTC는 브라우저 상에서 이용되는 기술입니다.
브라우저에서 사용할 수 있으니 별도의 Application 설치가 필요 없고, 동시에 PC의 저장 공간을 차지하지 않는다는 장점이 있습니다.
그리고, WebRTC는 Peer-to-peer 방식을 사용하여 완전한 P2P를 지원합니다.
때문에 중간에 서버를 거치는 것이 아닌 이용자 간의 통신이 가능합니다.
NAT를 나가서 외부 통신을 하는 경우엔 다른 서버의 도움을 받아야 합니다.
(gif image from wowza blog :: what is webrtc)
위의 gif 이미지를 보면 WebRTC Cloud Server와 2개의 End-point가 서로 통신하는 모습을 볼 수 있습니다.
위의 WebRTC Server가 아닌, STUN / TURN 서버를 통해 시그널링을 하며 P2P로 연결할 수도 있습니다.
WebRTC Server를 통해 상대에 대한 정보(SDP, offer, answer)를 주고 받고 P2P 통신을 할 수 있게 됩니다.
(WebRTC에 대한 좀 더 개념적인 설명은 따로 포스팅해서 연결하겠습니다.)
WebRTC - samples
위의 샘플을 통해 WebRTC 예제를 실행, 테스트 및 학습할 수 있습니다.
위의 모든 것들을 좀 더 쉽게 개발하고 이용할 수 있게 해주는 것이 오픈소스 WebRTC Server입니다.
그리고 우리는 Janus Gateway를 사용하도록 하겠습니다.
Janus Gateway는 위에서 짧게 설명한 WebRTC를 사용할 수 있게 구현한 WebRTC Server입니다.
기본적인 WebRTC 기능을 포함하며, Meetecho 팀이 구현한 여러 종류의 플러그인이 제공됩니다.
브라우저에서는 제공된 플러그인의 여러 기능(echo tests, conference bridges, media recorders, SIP gateways 등)을 사용할 수 있습니다.
또한 Janus는 ICE, DTLS, SRTP 모두를 제공합니다. 따로 구성할 필요가 없습니다.
Janus Docs
Janus-Gateway Github
Janus는 ICE Server 역할을 포함합니다.
ICE Server 역할을 한다는 것은 P2P 연결의 중간자 역할을 한다는 것입니다.
어? 분명 완전한 P2P라고 하지 않았나?
Janus를 사용하지 않고 WebRTC를 구현할 때, NAT 외부의 사용자와 연결할 경우엔 꼭 STUN이나 TURN에 요청해, 상대방의 SDP 정보를 받은 후에 P2P 연결이 가능합니다.
Janus를 거치지 않을 경우, TURN 서버가 ICE Server의 역할을 할 수 있습니다.
하지만 우리는 Janus를 사용한 케이스만 보기로 합니다.
Janus가 ICE Server의 역할을 하며, 브라우저는 ICE Server를 통해 P2P 연결을 구성합니다.
ICE : Interactive Connectivity Establishment (상호 연결을 돕는 프레임워크)
그리하여 Janus가 P2P 연결의 중간자 역할을 담당합니다.
Janus 설치는 Github 링크를 참조바랍니다.
Janus Github repo 페이지를 보시면 설명이 아주 친절하게 되어 있습니다.
정말 설치 과정 하나는 따로 설명하지 않아도 될 정도입니다.
Dependencies
To install it, you'll need to satisfy the following dependencies:
Jansson
libconfig
libnice (at least v0.1.16 suggested, v0.1.18 recommended)
OpenSSL (at least v1.0.1e)
libsrtp (at least v2.x suggested)
usrsctp (only needed if you are interested in Data Channels)
libmicrohttpd (at least v0.9.59; only needed if you are interested in REST support for the Janus API)
libwebsockets (only needed if you are interested in WebSockets support for the Janus API)
cmake (only needed if you are interested in WebSockets and/or BoringSSL support, as they make use of it)
rabbitmq-c (only needed if you are interested in RabbitMQ support for the Janus API or events)
paho.mqtt.c (only needed if you are interested in MQTT support for the Janus API or events)
nanomsg (only needed if you are interested in Nanomsg support for the Janus API)
libcurl (only needed if you are interested in the TURN REST API support)
이하 라이브러리는 본인이 사용할 플러그인에 따라 설치하면 됩니다.
A couple of plugins depend on a few more libraries:
Sofia-SIP (only needed for the SIP plugin)
libopus (only needed for the AudioBridge plugin)
libogg (needed for the VoiceMail plugin and/or post-processor, and optionally AudioBridge and Streaming plugins)
libcurl (only needed if you are interested in RTSP support in the Streaming plugin or in the sample Event Handler plugin)
Lua (only needed for the Lua plugin)
아래 라이브러리 / 도구는 필요합니다.
Additionally, you'll need the following libraries and tools:
GLib
zlib
pkg-config
gengetopt
이상, 설치에 앞서 dependencies를 확인했습니다.
이하, 설치를 진행하도록 하겠습니다.
설치 과정은 Janus Gateway Github 페이지에 나온 순서대로 진행하시면 됩니다.
그럼 제가 설명할 것은 없습니다.
Janus 서버 빌드하는 과정에 많은 dependencies가 요구되어, 로컬 pc의 환경에 설치하는 게 부담이 될 수 있습니다.
그런 분들은 아래 Dockerfile을 참조하셔서 Image를 빌드한 후에 사용하시면 됩니다.
FROM ubuntu:bionic RUN echo ' \n\ APT::Periodic::Update-Package-Lists "0";\n\ APT::Periodic::Unattended-Upgrade "1";\n'\ > /etc/apt/apt.conf.d/20auto-upgrades RUN set -x \ && apt-get update && apt-get install -y build-essential snapd aptitude git wget golang \ python3 python3-pip python3-setuptools python3-wheel ninja-build \ libgstreamer1.0-dev libgirepository1.0-dev libunwind-dev apt-utils libsrtp-dev \ gdb \ && aptitude install -y libmicrohttpd-dev libjansson-dev libnice-dev \ libssl-dev libsofia-sip-ua-dev libglib2.0-dev libopus-dev libogg-dev \ libconfig-dev libavutil-dev libavcodec-dev libavformat-dev libnanomsg-dev \ libcurl4-openssl-dev liblua5.3-dev pkg-config gengetopt libtool automake curl jq httpie vim screen doxygen graphviz RUN set -x \ && wget https://cmake.org/files/v3.16/cmake-3.16.2.tar.gz \ && tar -xvzf cmake-3.16.2.tar.gz \ && cd cmake-3.16.2 \ && ./bootstrap --prefix=/usr/local \ && make && make install RUN set -x \ && python3 -m pip install meson \ && python3 -m pip install ninja RUN set -x \ && cd \ && wget https://github.com/cisco/libsrtp/archive/v2.2.0.tar.gz \ && tar xfv v2.2.0.tar.gz \ && cd libsrtp-2.2.0/ \ && ./configure --prefix=/usr --enable-openssl \ && make shared_library && make install RUN set -x \ && git clone https://boringssl.googlesource.com/boringssl \ && cd boringssl \ && sed -i s/" -Werror"//g CMakeLists.txt \ && mkdir -p build \ && cd build \ && cmake -DCMAKE_CXX_FLAGS="-lrt" .. \ && make \ && cd .. \ && mkdir -p /opt/boringssl \ && cp -R include /opt/boringssl/ \ && mkdir -p /opt/boringssl/lib \ && cp build/ssl/libssl.a /opt/boringssl/lib/ \ && cp build/crypto/libcrypto.a /opt/boringssl/lib/ RUN set -x \ && git clone https://github.com/sctplab/usrsctp \ && cd usrsctp \ && ./bootstrap \ && ./configure --prefix=/usr --disable-programs --disable-inet --disable-inet6 \ && make && make install RUN set -x \ && git clone https://github.com/warmcat/libwebsockets.git \ && cd libwebsockets \ && mkdir build \ && cd build \ && cmake -DLWS_MAX_SMP=1 -DLWS_WITHOUT_EXTENSIONS=0 -DCMAKE_INSTALL_PREFIX:PATH=/usr -DCMAKE_C_FLAGS="-fpic" .. \ && make && make install RUN set -x \ && git clone https://github.com/eclipse/paho.mqtt.c.git \ && cd paho.mqtt.c \ && make && make install RUN set -x \ && git clone https://github.com/alanxz/rabbitmq-c \ && cd rabbitmq-c \ && git submodule init \ && git submodule update \ && mkdir build && cd build \ && cmake -DCMAKE_INSTALL_PREFIX=/usr .. \ && make && make install RUN set -x \ && git clone https://gitlab.freedesktop.org/libnice/libnice \ && cd libnice \ && meson --prefix=/usr build && ninja -C build && ninja -C build install RUN export JANUS_WITH_POSTPROCESSING RUN set -x \ && git clone https://github.com/meetecho/janus-gateway.git \ && cd janus-gateway \ && sh autogen.sh \ && ./configure --prefix=/opt/janus \ && make \ && make install \ && make configs RUN set -x \ && rm -rf /libwebsockets \ && rm -rf /janus-gateway \ && rm -rf /boringssl RUN adduser --disabled-password --gecos '' janus USER janus RUN /opt/janus/bin/janus --v CMD ["/opt/janus/bin/janus"]
위의 순서로 진행하시면 되고, 아래 몇 개의 디렉터리를 제거한 이유는 단순히 image 크기를 줄이기 위함입니다.
맨 위의 update 관련한 내용은 OS 버전 업그레이드를 자동으로 수행하는 걸 방지합니다.
apt 패키지 설치하는 파트에서 시간이 꽤 많이 소요되며, 메모리를 많이 사용하게 됩니다.
빌드할 때 가급적 다른 프로세스를 추가 동작하지 않는 게 좋습니다.
한 번 빌드를 하면 각 스텝 별로 caching되기 떄문에 다시 빌드할 때에 큰 부담이 없습니다.
apt 패키지만 설치하는 image를 만들고 그 image를 사용해서 새로운 Dockerfile을 작성하셔도 됩니다.
이상으로 WebRTC가 무엇인지, WebRTC Server인 Janus Gateway 설치 과정을 포스팅했습니다.
이 다음은 Janus Gateway demo 페이지를 로컬 환경에 띄우고 직접 빌드한 Janus Gateway 서버를 연동하는 포스트를 준비하겠습니다.
감사합니다.👍
좋은 글 감사합니다! Docker 이미지 관련하여 한 가지 궁금한 점이 있는데, git clone해서 받은 library들은 checkout해서 특정 tag나 version으로 바꿔주어야 제대로 동작하는 것은 아닌가요?