이번 2022년 1학기 캡스톤 디자인 프로젝트로 팀원들과 온라인 면접에 특화된 온라인 미팅 서비스를 기획했다.
전반적인 컨셉은 Zoom, WebEx와 같은 온라인 미팅 서비스와 비슷하고 그 위에 면접에 도움을 줄 수 있는 기능과 컨셉을 얹은 프로젝트이다.
어찌어찌 하여 나는 프론트 엔드를 담당하게 됐고, 비디오와 오디오 통신하는 Group Video Call
기능 개발에 있어서 풀 스택 개발을 담당하겠다고 팀원들에게 당당하게 선언했다.
당당하게 선언할 수 있었던 이유는 잠깐 찾아보니까 WebRTC
라는 API
를 이용해서 손 쉽게(그땐 그래보였다 ^ㅡ^) 개발 가능해 보였고, 예시 코드도 많아 보여서 얼른 끝내버려야겠다는 마음이 컸던 것 같다.. 뭐 아무쪼록 잘못된 생각이었음을 느끼는데는 시간이 오래 걸리지는 않았다.
WebRTC를 활용하여 프로젝트 개발 할 때 사용한 기술 스택은 아래와 같다.
Frontend
사이드는 Vue.js
를 활용하고,
Backend
사이드는 Spring boot
를 활용했다.
둘다 특별한 이유가 있었던 건 아니고,,
Vue.js
는 그저 한번 써보고 싶어서였고, Spring
은 앞으로 쭉 다뤄야할 프레임워크이기 때문에 한번더 숙련도를 쌓을 겸 사용하기로 했다.
사실 어려움은 여기서 발생한다.. 그룹 화상 통화 기능 개발을 위한 WebRTC
를 다루기 위해서, 처음에는 "예시 코드 보면서 빠르게 무지성 복붙해보자~" 라고 생각하며 웹에 있는 코드를 참고하며 끄적끄적 복붙하기를 시도했으나..
웹에 있던 코드들은 대부분 React.js
+ Node js
+ Socket.io
기반 코드들이었다.
"예시 코드 무지성 복붙으로 사용"에 실패한 이유는 다음과 같다.
(1) WebRTC 작동 Flow
에 대한 정확한 이해도 없을 뿐더러,
(2) Node js
와 Socket io
도 제대로 다뤄본적도 없어서 코드 해석하기도 쉽지 않았다. 그리고,
(3) Spring
기반 소켓 통신과 Node js
기반 소켓 통신의 코드는 분명 차이가 있었고,,,
(4) 심지어 Vue.js
는 처음 다뤄보는 상황이었기 때문에
가이드 코드를 내 프로젝트에 맞게 유연하게 변환하는것은 정말로 어려웠다.
깃헙 레파지토리에서 관련 Spring Java 코드들도 많이 찾아보았으나,, 이해하고 적용하기 정말 어려웠고.. 어느정도 시도해보다가 가이드 코드를 그대로 쓰기는 포기했다..
이번 글에서는 내가 WebRTC
를 SpringBoot
와 Vue.js
환경에서 구현한 과정을 적어보겠다.
코드를 짜기 위해서 가장 절실했던 것은, WebRTC 동작 Flow를 명확히 이해하는 것이었다. 사실 이러한 이해는 단순히 글을 읽는다고 해서 100% 이해되는 부분은 아니라고 생각한다..
나 또한 개념을 몇번이나 반복해서 읽었지만 결국 어느 정도 이해된 시점은 가이드 코드를 다 뜯어보고, 내 코드로 만들어본 시점이었던 것 같다.
하지만 결국 남의 가이드 코드를 이해하기 위해서, 가장 빠르게 그 코드를 해석해서 내 코드로 바꾸기 위해서는 WebRTC
에 관한 이해가 선행돼야 한다. 아래로는 WebRTC
에 관한 내용을 기재해보았다.
WebRTC(Web Real-Time Communication)
는 별도의 플러그인 설치 없이 실시간으로 미디어(오디오, 비디오, 텍스트, 파일 등)를 최대한 서버를 거치지 않고 Peer간 전송할 수 있는 오픈 소스 웹 기반 기술이다.
위의 그림을 보면 엄청 어려워보인다ㅠㅡㅠ.. 서버만 Signaling Server
, TUN Server
, STUN Server
3개를 구축해야하는지에 대한 막연함도 생기고,,
WebRTC
가 분명 Peer간에 다양한 미디어들이 다이렉트하게 전송될 수 있다고 했는데 결국 서버를 거쳐서 동작하는 건가하는 의문도 들었다. 정확한 동작 Flow를 이해하기 위해서 각각의 서버가 무슨 역할을 하는지 이해해 보자.
Signaling Server
는 WebRTC에서 가장 기본이 되는 서버라고 할 수 있다.
서로 다른 네트워크에 있는 Peer들을 연결시키기위해서는 Session Control Messages
, Error Messages
, Codec
, Bandwith
등 다양한 정보가 필요하다.
결국 WebRTC
기술을 활용해서 Peer끼리 연결하기 위해서는 위의 정보들이 먼저 각각의 Peer들에게 전달돼야 한다는 것이며 이 프로세스를 Signaling
이라고 한다.
이러한 정보들을 중계해주는 역할을 하는 서버가 바로 Signaling Server
이다.
또한 위의 정보들은 SDP(Session Description Protocol)을 사용한다.
WebRTC와는 별개로 Signaling Server
는 직접 구축해야하며,
많은 가이드에서 일반적으로 클라이언트 사이드와 WebSocket
을 사용하여 통신한다.
Signaling Server
를 중심으로 WebRTC의 동작 과정을 설명해보자면 다음과 같다.
!!! Client와 Server 사이 통신은
WebSocket
을 사용한다. !!!
① Client Side의 A Client(Peer)에서Signaling Server
로 연결에 필요한 A Clinet의 데이터를 보낸다.
=>Signaling Offer
② Server Side에서,Signaling Server
에 연결된 모든 세션들에게 A Client의 데이터를 전달한다.
③ Client Side의 B Client(Peer)에서 A Client의 데이터를 활용해서 연결에 필요한 일련의 작업을 한 후, B Client의 데이터를Signaling Server
로 보낸다.
=>Signaling Answer
④ Server Side에서, A Client의 세션에게 B Client의 데이터를 전달한다.
⑤ 각각의 데이터를 활용하여 WebRTC가 A Client와 B Client가 연결한다.
위의 Signaling Server
을 이용해서 우리는 Peer간의 통신이 가능하다!
하지만 통신 중간에 방화벽, NAT 환경에 놓여 있는 Peer에 대해서는 직접적인 Signaling
이 불가능하다. 이때 이어 설명할 STUN Server
와 TURN Server
가 필요하다.
STUN Server
는 클라이언트 자신의 공인 IP(Public Address)를 알려주는 서버이다.
Client에서 STUN Server
로 요청을 보내서 자신의 공인 IP를 확인한 후, 해당 IP를 활용하여 Signaling
하게 된다.
이러한 STUN Server
는 직접 구현할 필요없다.
짧게 생각해봐도 클라이언트 자신의 공인 IP를 알아내는 서버??
내가 직접 만들 필요가 있을까..?
이미 스마트하신분들이 만들어 놓은 오픈 소스, Google 등에서 운영하는 STUN Server
를 사용해도 된다!
STUN Server
같은 경우는 단순히 정보 제공을 위한 서버라 트래픽 발생이 현저히 낮기 때문에 웬만하면 무료 STUN Server
를 사용해도 문제가 크게는 없다고 한다.
앞서 말한 STUN Server
를 활용하면 대략 80% 정도는 Signaling
을 통한 연결이 가능하다고 한다. 하지만, 그렇지 못한 20%의 경우가 존재하는데, 보호정책이 강한 NAT나 라우터, 보통Symmetric NAT 환경
에서 나타난다고 한다.
TURN Server
는 Symmetric NAT
제한을 우회할 수 있게끔 해주는 기능을 한다.
결국 TURN Server
가 Peer간의 통신 채널을 중계해주는 역할을 하며, WebRTC의 가장 큰 특징인 P2P 방식에서 벗어나게 된다.
때문에 Peer간 모든 트래픽을 중계해주기 때문에 상당한 부하를 감당해야하며, 비용 또한 크게 발생할 것이다.
즉, Local IP와 Public IP 둘다로도 연결할 수 없는 경우 TURN Server
을 최후의 수단으로 사용하게 된다.
STUN Server
처럼 구글에서 무료 제공하는 TURN Server
가 있다고 하지만,, 앞서 말한 단점 때문에 현재는 사용을 못한다고 하고,
안정적인 서비스를 위해서는 TURN 서버를 직접 운영하는 것이 필요할 것이다.
구글링을 해보니,
COTURN이라는 오픈 소스를 활용해 TURN 서버를 구축하는 것을 강력 추천했다.
사실 이번 프로젝트에는 TURN Server
까지는 활용하지 않고, STUR Server
만 활용할 예정이다 ㅎㅎ..(하다가 문제가 커지면 그때 추가하지않을까)
WebRTC
의 구현 방식에는 크게 3가지로 Mesh
, SFU
, MCU
방식이 있다.
사실 우리가 지금까지 위에서 말한 방식은 Mesh
방식으로 서버의 자원이 적게들지만 Peer 수가 늘어날 수록 Client 사이드의 과부하가 급격하게 증가하는 방식이다. 때문에 소규모 연결에 적합할 것이다. 이에 대한 설명은 바로 밑 단락에서 하기로 하고,,
Mesh
방식에서는 Media Server
가 필요하지 않다.
Media Server
는 SFU
, MCU
방식의 WebRTC
에서 필요한 서버로,
각각의 Peer들은 Media Server
에게 미디어 스트림들을 쏴주고 Media Server
에서 미디어 트래픽을 관리하여 각각의 Peer에게 다시 배포해주는 멀티미디어 미들웨어이다.
즉, WebRTC
의 특징은 P2P 통신이 아닌게 되는 것은 TURN Server
와 유사하다고 할 수 있고, 클라이언트에 부하가 현저히 줄어드는 대신 서버의 부하가 커지며 구현의 난도가 상당히 높다.
Media Server
가 언제, 왜 필요할지에 대해서 제대로 이해하기 위해서 아래 WebRTC 구현 방식에 대해서 살펴보는 것이 좋겠다.
위에서 언급 했듯, WebRTC
의 구현 방식에는 크게 3가지로 Mesh
, SFU
, MCU
방식이 있다.
구현 방식에 있어서 당연히 장점과 단점이 존재한다. 어떤 방식을 택할지는 정답은 없다.
자신이 현재 하는 프로젝트 스펙에 맞게 정하면 선택하면 된다!
아래로는 간단하게 각각의 방식의 특징과 장단점을 살펴 보겠다. 위 그림을 보면서 글을 읽으면 이해하기 쉽다.
이 블로그에 정말 깔끔하게 정리돼있다!
아래도 위 블로그를 참고하여 작성했다.
특징
Signaling Server
, STUN Server
, TURN Server
를 사용하는 전형적인 P2P WebRTC
구현 방식이다.장점
Signaling
과정만 서버가 중계하기 때문에 서버의 부하가 적다.단점
특징
Media Server
에서 혼합(muxing) 또는 가공(transcoding)하여 수신측으로 전달하는 방식.Media Server
의 매우 높은 컴퓨팅 파워가 요구된다.장점
단점
특징
Media Server
를 두는 방식.장점
Mesh
방식보다 느린 것은 어쩔수 없다. 하지만 비슷한 수준의 실시간성을 유지할 수 있다.Mesh
방식보다는 Client의 부하가 줄어든다.단점
Mesh
방식보다는 서버의 부하가 늘어난다.사실 포스팅 하나로 끝내려고 했는데,,,
생각보다 짚고 넘어가고 싶은 부분이 많아서 와다다다 이론적인 내용들을 적게 됐다...
WebRTC
는 생각보다 쉽지 않은 기술임은 확실하다..
실제로 여러가지로 멘토님께 조언을 구해보니 상용할정도로 개발하려면,
정말로 어려운 기술이다. 신경쓸게 한두가지가 아니다..
다음 포스팅에서는 간단하게 로컬에서 WebRTC
를
Spring boot
& Vue.js
& Simple Peer
을 활용해서 맛 봐도록 할 것이다.
확실한 것은 위의 내용을 한번이라도 훑고 가면 코드를 이해하기에,,
자신의 코드로 만들기에 훨씬 더 쉬울 것 같다!!
뭐 간단하게 "응 난 집에서만, 집 네트워크에서만 돌릴정도로만 만들어보게~" 라고 한다면 무지성 복붙이 가능하겠지만.. 어느정도 배포까지 해야하고 화상 회의로서 기능을 하게끔 해야 하는 상황이라면 위의 기본적인 정보들을 숙지하는 것은 필수일 것 같다.
https://velog.io/@jsw4215/%EB%A6%AC%EC%95%A1%ED%8A%B8-webRTC-recypumx
https://millo-l.github.io/WebRTC-%EC%9D%B4%EB%A1%A0-%EC%A0%95%EB%A6%AC%ED%95%98%EA%B8%B0/
재밌게 잘 봤습니다 :-)
혹시 같은 네트워크의 2개의 client가 STUN 서버를 이용하면 이슈가 없을까요? ( 같은 공인 IP인 경우)
있다면 어떤식으로 해결할까요?