Mediasoup 초기 시작 세팅하기
지금 졸작에서 진행하고 있는 프로젝트에서 화면 공유 기능이 필요해서 WebRTC 를 사용해야했습니다!
WebRTC 를 사용하기 위해서 백엔드에서는 미디어 서버라는 것을 구축해야하는데요.
저는 미디어 서버들 중에서도 MediaSoup 이라는 것을 사용하기로 했습니다.
먼저, WebRTC 가 무엇인지부터 설명하겠습니다.
WebRTC 는 뭐야?
WebRTC(Web Real-Time Communication)는 브라우저 간에 실시간 통신을 가능하게 하는 오픈 소스 기술입니다.
이 기술은 사용자들이 별도의 플러그인이나 소프트웨어 설치 없이 웹 브라우저 또는 모바일 앱에서 직접 음성, 비디오 및 데이터 스트림을 주고받을 수 있게 해줍니다. WebRTC는 주로 화상 통화, 화면 공유, 파일 전송 등의 실시간 통신 기능을 구현하는 데 사용됩니다.
WebRTC의 주요 장점은 P2P(Peer-to-Peer) 연결을 통해 클라이언트 간 직접적인 데이터 교환을 가능하게 한다는 점입니다.
이는 서버 부하를 줄이고, 데이터 전송 지연을 최소화하여 더 빠르고 효율적인 통신을 구현할 수 있게 합니다.
WebRTC는 다음과 같은 주요 API를 통해 이 기능을 제공합니다:
- MediaStream: 카메라, 마이크 등 장치에서 데이터 스트림에 접근할 수 있게 해줍니다.
- RTCPeerConnection: 두 클라이언트 간의 음성 및 비디오 데이터를 안전하게 교환할 수 있도록 암호화 및 대역폭 관리를 제공합니다.
- RTCDataChannel: 일반적인 데이터의 P2P 통신을 지원합니다.
이들 API는 P2P 통신을 가능하게 하며, 연결 과정에서 시그널링(Signaling)이라는 절차를 통해 서로 데이터를 교환하고 연결을 설정합니다.
방화벽과 NAT 그리고 STUN/TURN 서버
WebRTC는 P2P 통신을 기반으로 하지만, 실제로 클라이언트 간의 직접 연결이 항상 가능한 것은 아닙니다.
방화벽(Firewall)과 NAT(Network Address Translation) 가 보안 및 네트워크 관리 목적으로 직접적인 연결을 차단합니다.
이 문제를 해결하기 위해 WebRTC는 STUN(Session Traversal Utilities for NAT)과 TURN(Traversal Using Relays around NAT) 서버를 활용합니다.
- STUN 서버: 클라이언트가 공인 IP 주소와 포트를 확인하도록 도와줍니다. 이 정보를 사용해 클라이언트는 NAT 뒤에서 P2P 연결을 시도할 수 있습니다.
- TURN 서버: STUN을 사용해도 연결이 실패할 경우, TURN 서버가 중계 서버 역할을 하여 클라이언트 간의 데이터를 전송합니다. 이는 P2P 연결이 불가능할 때 사용됩니다.
이렇게 STUN/TURN 서버를 이용해서 막혀있는 방화벽을 우회하여 클라이언트 간에도 안정적인 통신을 보장할 수 있도록 하고 있습니다.
WebRTC 미디어 서버의 종류
WebRTC 에는 클라이언트 간 미디어 데이터(오디오, 비디오, 텍스트 등)를 처리하고 전달하는 미디어 서버가 있습니다.
주요 미디어 서버에는 SFU 와 MCU 가 있습니다.
SFU(Selective Forwarding Unit) 는 클라이언트로부터 받은 미디어 스트림을 그대로 전달합니다. 그에 반해 MCU(Multipoint Control Unit) 은 여러 클라이언트의 스트림을 서버에서 혼합하여 단일 스트림으로 전달합니다.
여기까지가 아주 간단한 WebRTC 에 대한 소개입니다! 사실 저도 처음 접하는 부분이라 이렇게 설명함에도 불구하고 아직도 익숙치않고 어색합니다..! 더 자세하고 실용적인 내용은 후에 개발을 진행하면서 생기는대로 공유하도록 하겠습니다!
대표적인 미디어 서버에는 Kurento, Mediasoup 등이 있는데요, 저는 여기서 Mediasoup 을 사용하기로 마음 먹었습니다.
왜 Mediasoup 이어야 하지??
졸작에서 구현하고 있는 서비스는 실시간 커뮤니케이션 플랫폼입니다. 주요 요구 사항은 높은 성능, 낮은 지연, 확장성, 그리고 많은 수의 동시 사용자를 처리할 수 있는 능력입니다. 이러한 요소들을 고려했을 때, Mediasoup 이 적합하다고 생각했습니다.
1. 낮은 지연
: Mediasoup는 SFU 기반으로 작동하여, 클라이언트 간의 미디어 스트림을 직접 전달합니다. 서버에서 추가적인 미디어 처리 없이 스트림을 그대로 전달하므로 지연이 매우 낮다고 합니다.
그에 비해 Kurento는 미디어 스트림을 처리하고 변환하기 때문에 이로 인해 지연이 발생할 수 있다고 합니다. 특별한 미디어 처리 기능이 요구되지 않는다면 오히려 kurento 가 무거울 수도 있다고 합니다..!
2. 확장성
: Mediasoup 은 Node.js 를 기반으로 하고 있습니다. 다수의 동시 사용자를 처리하는 데에는 Kurento 에 비해 Mediasoup 이 더 경량적이라 시스템 자원 소모가 덜 할 수 있다고 합니다.
3. 불필요한 미디어 처리
: 제가 구현할 서비스는 단순한 PC 화면 공유가 목적입니다. 스트림에 필터를 적용한다거나 실시간 트랜스 코딩과 같은 고급 미디어 처리가 필요하다면 Kurento 가 더 좋은 선택일 수 있지만, 일반적이고 평범한 음성 및 영상통화 구현에서는 오히려 Kurento 가 과도한 기능일 수 있습니다. Mediasoup 은 복잡한 미디어 처리 없이 실시간 음성 및 화상 전달에 더 중점을 두었다고 합니다.
4. 사용하는 언어..
: Mediasoup 은 Node 기반이고, Kurento 는 Java 기반입니다. 저는 스프링으로 개발을 하고 있는 Java 가 더 익숙한 개발자이고, 사실 Node 에 익숙하지 않아서 Mediasoup 을 잘 사용할 수 있을지는 모르겠지만, 한번 구현을 해보려고 합니다..
5. SFU 방식
: Mesh 방식은 모든 클라이언트에게 미디어를 전송해야하지만, SFU 방식을 사용하게 되면 서버에 한번만 보내면 서버가 알아서 다른 클라이언트들에게 전송할 수 있어서 MCU 는 서버의 부하가 크기 때문에 SFU 방식을 선택하였습니다.
자, 이제 초기 세팅을 어떻게 해야하는지에 대해 말씀드리겠습니다!!
저는 VScode 를 사용해서 시작했습니다. 저는 기존에 사용하고 있던 API Server 레포지토리가 아닌 새로운 레포지토리를 생성해주었습니다! 새로운 폴더를 만들고 그리고 그 레포지토리와 제 VScode 를 연결해주었습니다~!
`npm init` 을 해주고 그냥 다 enter 를 쳐줍니다.
그 다음 `npm install express --save` 이걸 해줍니다.
express js 는 node 의 프레임워크라고 합니다.. node 는 첨이라..
여기까지 하면 package.json 에 맨 밑에 express 의존성이 추가된 걸 확인할 수 있습니다!
//index.js
const express = require('express') //③번 단계에서 다운받았던 express 모듈을 가져온다.
const app = express() //가져온 express 모듈의 function을 이용해서 새로운 express 앱을 만든다. 🔥
const port = 5000 //포트는 4000번 해도되고, 5000번 해도 된다. -> 이번엔 5000번 포트를 백 서버로 두겠다.
app.get('/', (req, res) => { //express 앱(app)을 넣고, root directory에 오면,
res.send('Hello World!') //"Hello World!" 를 출력되게 해준다.
})
app.listen(port, () => {
console.log(`Example app listening at http://localhost:${port}`)
}) //포트 5000번에서 이 앱을 실행한다.
index.js 라는 파일을 만들어 위의 코드를 붙여넣어주고,
다시 package.json 파일로 돌아가서 scripts 에 `"start" : "node index.js"` 를 작성해줍니다.
모든걸 저장하고 터미널 창으로 돌아가서 `npm run start` 를 해주면 로컬 서버가 열립니다!!
여기까지가 node 프로젝트를 생성하는 초기단계였습니다..! 이제부터 mediasoup 을 구축하는 방법에 대해 알아보겠습니다.