본문 바로가기

백엔드 개발자(node.js)가 되는 과정

Node.js 기반 라이브 스트리밍 구현 흐름 살펴보기

728x90

현재 진행 중인 프로젝트를 통해 Nest.js 기반 API 서버와 라이브 스트리밍을 위한 서버, AWS 서비스로 라이브 스트리밍을 구현하였으며 대략적인 Work Flow는 위 그림과 같다.

어떤 방식으로 구현되었는지 단계별로 알아보고 보완이 필요한 부분을 살펴보자

1. 스튜디오 입장

BJ가 스트리밍을 시작하기에 앞서 준비 단계에 해당하는 페이지로 접속하며 이를 스튜디오로 칭했다.
해당 페이지에서는 스트리밍을 위한 신규 채널을 생성하고, 라이브 스트리밍을 진행할 수 있다.

2. 유저 정보 획득

입장한 유저의 신원을 조회한다. 이는 BJ가 스튜디오에 입장했을 때 종료되지 않은 스트리밍 채널 존재 여부를 확인하기 위함이다.
채널 존재 여부를 확인하는 이유는
첫째, BJ는 한 번에 여러 스트리밍 채널을 생성할 수 없도록 하기 위함이다.
둘째, BJ가 스튜디오 페이지를 빠져 나갔다 다시 복귀하더라도 기존에 생성한 채널 정보가 유지되도록 하기 위함이다.

3. 스튜디오 상태 체크

유저 정보를 기반으로 진행 중인 스트리밍 채널이 있다면 해당 정보를 보여주고, 진행 중인 채널이 없다면(채널 생성 이력이 없거나, 이미 종료된 채널만 보유했을 경우) 채널 신규 생성을 통해 일종의 '방'을 판다.

4. 신규 채널 생성

채널명, 해시태그 등 채널 정보를 입력하여 신규 채널을 생성하고, 스트림키를 획득한다. 여기서 스트림키는 OBS와 같은 스트리밍 소프트웨어로 RTMP 프로토콜 통신을 할 때 사용한다.

자세한 내용은 아래 링크 참조
https://issuebombom.tistory.com/106
https://issuebombom.tistory.com/105

또한 라이브 스트리밍이 시작될 경우 채팅 기능, 알림, 도네이션 기능이 활성화 되도록 하기 위해 소켓 이벤트를 세팅한다. 생성된 채널 ID를 대상으로 입장한 각 유저의 소켓이 join하도록 하여 ROOM 개념을 생성하여 채팅 기능이 같은 ROOM 안에 있는 소켓끼리 전달되도록 한다.

5. OBS와 RTMP 프로토콜 통신

OBS에는 RTMP 통신을 위한 설정이 존재한다. 먼저 RTMP가 구현된 서버의 IP와 스트림키를 설정하여 방송 시작 버튼을 클릭하면 스트리밍 서버와의 RTMP 통신을 진행하게 된다. 즉 OBS로 입력한 비디오, 오디오 데이터가 스트리밍 서버로 흘러들어가게 된다.

6. 스트리밍 서버 내부

스트리밍 서버 내부에서는 이를 인지하여 입력받은 데이터를 잘게 쪼개어 저장하는 HLS 로직이 적용되어 로컬에 저장한다. 그리고 각 파일들은 생성될 때 마다 이벤트로 감지하여 S3 bucket에 고스란히 업로드 한다.
이와 동시에 rtmp 통신이 연결되면 이를 감지하는 이벤트를 활용하여 웹 서버에 이를 알려주고, 프론트에서 스트리밍 플레이를 위한 hls 플레이어를 세팅한다.

📌 이슈 사항
로컬에 저장하지 않고 즉시 S3에 저장할 수 있다면 불필요한 로컬 저장 과정을 생략할 수 있게 된다.
라이브 스트리밍은 S3에 올라온 .m3u8 파일을 실행하기 때문에 이 문제를 해결한다면 스트리밍 시작 시간과 시청 가능 시간 간 딜레이를 감소할 수 있다. 이를 해결하기 위해서는 내부적으로 ffmpeg put method를 활용하여 직접적으로 S3에 저장하도록 하는 방법을 알아봐야 할 것 같다.

7. S3와 Cloudfront

Cloudfront는 클라이언트가 S3 Bucket에 직접 접근하는 것을 방지하며, 무엇보다 특정 데이터 요청이 들어올 경우 Cloudfront는 해당 데이터를 캐시에 저장한 뒤 캐시 데이터를 사용하도록 한다. 캐시에 접근하여 데이터를 획득한다는 것 자체가 S3에 직접 접근하는 것보다 시간 절약이 발생하므로 실시간 스트리밍에서는 필수불가결한 기능이라 할 수 있다.

📌 이슈 사항
Cloudfront의 기본 캐시 TTL은 24시간으로 설정되어 있다. 하지만 ts파일이 신규 생성될 때 마다 m3u8도 업데이트 되기 때문에 S3에 지속적으로 업데이트 되지만 파일명이 변경되지는 않으므로 Cloudfront는 최초에 캐시에 등록된 m3u8만 계속 제공하게 된다.
이를 해결하고자 m3u8 파일에 대해서는 캐시를 적용하지 않도록 캐시 정책을 반영했으며, 또한 캐시 정책 중 Elemental-Live 정책을 적용할 경우 ts 캐시 파일이 단시간 내 업데이트 되는 것을 확인할 수 있었다.

8. hls 플레이어 설정

프론트에서는 m3u8 파일을 실행할 수 있는 플레이어로서 hls 플레이어를 사용한다. 이는 지속적으로 Cloudfront와 통신하며 라이브 스트리밍을 제공한다.

9. 스트리밍 종료

OBS에서 방송을 중단하면 RTMP 통신이 끊어지는 이벤트가 발생하고 이를 캐치할 수 있다. 이를 통해 백엔드에 라이브 방송이 중단되었음을 알릴 수 있으며, 백엔드에서는 스트리밍 채널의 onAir 상태를 false로 만들면서 스트리밍 도중 발생한 도내이션의 정산 등을 처리하도록 구현할 수 있다.

728x90
728x90