SW사관학교 정글 5기 Team Project (2022.12.22 ~ 2023.1.28)
PLAY DANCE LIVE! 는 실시간으로 1대 1 릴레이 댄스 배틀을 펼치고, 시청할 수 있는 플랫폼입니다.
랜덤으로 나오는 댄스 챌린지를 소화하고 챔피언의 자리를 차지해라!
AWS EC2 하나에 Frontend, Backend, Openvidu Deployment를 모두 올렸습니다.
서버 사양:
AWS EC2 t2.medium (2 vcpu, 4 GiB)
ubuntu 22.04 LTS (amd64)
22GiB storage
Openvidu v2.25.0:
Installation Mode: On Premises
Front-end:
React v17.0.1 created by create-react-app
Back-end:
Java SpringBoot v2.7.7 (Java 11)
기본적으로 openvidu 공식 문서의 Deployment on premises의 내용대로 진행한 후에 다음 내용을 참고합니다.
-
여러분이 공식문서를 잘 따라왔다면, 다음 항목들이 완료되었을 것입니다.
-
Openvidu를 EC2에 잘 설치했습니다.
-
/opt/openvidu/.env 파일을 올바르게 설정했습니다. (아래의 도메인과 SSL 환경설정 부분을 참고하세요)
-
-
그리고 여러분의 frontend 코드와 backend(application server) 코드를 약간 수정해주어야 합니다.
-
frontend/.env.production
REACT_APP_HOST=domain.com
domain.com
대신 여러분의 도메인 주소를 넣으세요. -
backend에서 openvidu 관련 설정과 서버 포트 설정이 있을 겁니다. 서버 포트는
5000
번으로 수정해주시고,OPENVIDU_URL
은 다음과 같이 설정해 주세요.OPENVIDU_URL: http://localhost:5443/
Note
여러분이 코드를 이해했다면, 서버 포트를
5000
번이 아닌 다른 포트로 매핑해도 상관없습니다.
-
-
그리고 이제 nginx 환경설정을
약간수정해야 합니다.-
Openvidu 공식 문서: Modify nginx configuration의 내용을 참고하며 진행했습니다.
-
./openvidu start
를 해서 openvidu와 nginx가 실행되고 있는 상태로 만듭니다. -
아래 코드를 실행하면
custom-nginx.conf
,nginx.conf
파일이/opt/openvidu
경로에 만들어집니다.sudo su cd /opt/openvidu docker-compose exec nginx cat /etc/nginx/conf.d/default.conf > custom-nginx.conf docker-compose exec nginx cat /etc/nginx/nginx.conf > nginx.conf
-
이제 vi로
custom-nginx.conf
를 수정해봅시다. (sudo 권한이 필요할 겁니다)많은 코드들이 있을텐데, yourapp과 관련된 설정만 수정해 보겠습니다.
# Your App upstream yourapp { server localhost:5442; } upstream openviduserver { server localhost:5443; } # ...생략 server { listen 443 ssl; listen [::]:443 ssl; server_name domain.com; # ...생략 # Your App location / { proxy_pass http://yourapp; #your app } # ...생략 }
기본적으로
location /
에 대해5442
포트로 proxy_pass 되어 있습니다.저희는 react의 빌드된 파일을 node 서버가 5442번 포트에서 듣도록 하고, springboot 백엔드 서버를 tomcat이 5000번 포트에서 듣도록 설정했습니다.
그리고 백엔드로의 요청은 모두
$host/api/…
형태가 되도록 작성했습니다.이에 맞게 파일을 수정해 보겠습니다.
# Your App upstream frontendserver { server localhost:5442; } upstream openviduserver { server localhost:5443; } upstream backendserver { server localhost:5000; } # ...생략 server { listen 443 ssl; listen [::]:443 ssl; server_name domain.com; # ...생략 # Your App location / { proxy_pass http://frontendserver; } location /api/ { proxy_pass http://backendserver; } # ...생략 }
-
이제
/opt/openvidu/docker-compose.yml
파일에 다음 라인들을 추가해주고 openvidu를 재시작하면 됩니다.nginx: ... volumes: ... - ./custom-nginx.conf:/custom-nginx/custom-nginx.conf - ./nginx.conf:/etc/nginx/nginx.conf
-
다음과 같이 구현하고 싶을 때 사용할 수 있는 방식입니다.
- 상업 서비스를 위해 openvidu를 사용하고 싶을 때 (물론 개발 목적으로도 가능)
- Fully Qualified Domain Name(FQDN)으로 사용하고 싶을 때
- 유효한 SSL 인증을 사용하고 싶을 때
구현을 위해서는 아래 내용에 따르세요.
-
서버의 Public IP를 가리키는 FQDN을 등록하기
- Type A 방식으로 public IP를 가리키는 DNS 등록을 하면 됩니다. (gabia 같은 곳에서 도메인 DNS 등록하는 것을 말함)
-
/opt/openvidu/.env
파일 수정하기- 파일을 다음 내용과 같이 수정하세요.
DOMAIN_OR_PUBLIC_IP=example.openvidu.io # 위에서 등록한 도메인을 적으면 됩니다. CERTIFICATE_TYPE=letsencrypt OPENVIDU_SECRET=YOUR_SECRET # 임의의 비밀번호. 튜토리얼에서는 MY_SECRET 이었습니다. LETSENCRYPT_EMAIL=youremail@youremail.com # let's encrypt를 활용하기 위해 이메일 주소를 적습니다.
location 사용법
NGINX의 proxy_pass 기능은 들어오는 요청을 받아서 특정 위치로 보내고, 다시 돌아오는 응답을 받아서 클라이언트에게 돌려주는 것까지 수행해줍니다. (정말 좋네요)
HTTP 서버에 요청을 전달하기 위해, location 블록 안에 proxy_pass를 지정해보세요.
location /some/path/ {
proxy_pass http://www.example.com/link/;
}
자세한 사용 방법은 nginx 공식 문서를 참고하세요.
문제점
- 음악이 시작하는 타이밍에만 signal이 전달되므로, 중간에 들어오는 시청자는 신호를 받지 못함
- 네트워크 지연으로 영상이 끊기게 되어도 음악은 계속 재생되기 때문에, 영상과 음악의 싱크가 어긋남
WebRTC 특성 상 mp3 파일을 직접 AudioSource로 사용할 수 없으나, WebAudio API를 이용하여 MediaStream을 생성하게 되면 가능해짐
영상과 음성이 한 스트림에 전송되므로 싱크 문제가 해결됨
- 중간에 진입하는 시청자도 중간부터 영상과 음성의 동시 수신 가능
- 영상이 끊겨도 음악과 싱크가 어긋나지 않음
Team Leader / 스트리밍, 진행 로직 설계
Backend / 채팅, 소켓, 방송 데이터 관리
Full Stack / 투표 시스템, 영상 레이아웃
Backend / DB, 인증 인가 시스템
-
두 명이 동시에 춤추기
- 현재 'PLAY DANCE LIVE!' 는 두 명의 참가자가 번갈아가며 춤을 추는 형식. 기획적으로는 두 사람이 동시에 춤 대결을 펼치는 것이 더 흥미로운 지점이 많았지만, 기술적으로는 많은 어려움이 예상되어 일단 번갈아 추는 것을 목표로 구현하고 각자의 춤과 노래의 싱크를 맞추는데 신경을 많이 썼음. 간단하게 생각해본 방안으로는, 춤을 추는 두 사람은 서로 P2P로 연결해 같은 타이밍에 맞춰 춤을 출 수 있게 하고, 중계 서버는 이 둘이 보내는 stream을 실제 음원에 해당하는 하나의 타이밍을 통해 mixing한 후 산출된 stream을 시청자들에게 송출하는 방법을 시도해 볼 수 있음. 다만 이 경우 춤추는 두 사람과 시청자들 간에는 서버의 연산시간 만큼의 지연이 발생하게 됨.
-
여러 개의 채널 중 골라서 입장하기
- 하나의 배틀을 온전히 진행할 수 있게 된 후, 음악 장르별 채널을 다양화해(e.g. K-pop, 1990s, ...) 각 채널에서 서로 다른 배틀이 이루어질 수 있게 추가 기획을 한 바 있음. 추가적인 구현이 필요함.
- 어뷰징 방지
- 투표 시스템을 악용해 반복문으로 투표 클릭 신호를 서버로 보내는 등의 어뷰징 행위를 방지해야 함. 버튼을 통한 api 요청에 '쿨타임' 같은 딜레이를 적용한다던지, 더 안전하게는 요청을 받는 서버가 같은 로그인 정보를 가진 요청에 대해 일정 시간내 최대 요청의 개수를 제한하는 방법이 있음.
- 배틀 시간 운영
- 시청자 대기열이 비어있는 상황을 피하고자 배틀 시간대를 지정하여 운영함. (e.g. 오후반은 1시에 시작. 저녁반은 21시에 시작.)
MIT License. 2023. codeEATERS. All rights reserved.