Play-Dance-Live

da__ell·2023년 3월 17일
0

ETC

목록 보기
1/1
post-thumbnail

Play - Dance -Live 프로젝트에서 내가 담당했던 역할과 그 과정에서 했던 고민, 그리고 더 나아가 어떤 개선점이 있을 지 고민한 내용을 작성하였다.

목차

  • [왜 WEBRTC를 활용한 프로젝트를 만들었나?])
  • [왜 소켓 통신을 사용했나?]
    • [STOMP를 사용한 이유
  • [왜 Openvidu를 사용했나?]
    • [그렇지만 문제가 있었다]
  • [오디오와 영상의 싱크를 맞춰야 했다.]
    • [하지만 싱크가 맞더라도 네트워크 등의 문제로 방송 스트림 자체가 버벅거릴 때 어떻게 보정할 것인가?]
  • [왜 Java/Spring을 선택했나?]
    • [방송의 진행 로직을 어떻게 구성하였나?]
    • [투표, 랭킹 등 방송과 관련된 관리, 저장방식을 결정하고 구현(Redis, MySql)]
  • [프로젝트의 MVP 설정과, 개밥먹기의 중요성]

<수행한 역할>

  • 실시간으로 변동되는 투표, 랭킹 등 데이터들을 송수신하기 위해 STOMP를 활용한 소켓 통신 기능 구현
  • 2:N 스트리밍 서비스를 제공하기 위해 openvidu 프레임워크 결정 및 세션 관리
  • 오디오와 영상의 싱크를 맞추기 위해 Webaudio Api를 활용하여 MP3 파일을 오디오 소스로 변경
  • 방송의 진행 방식(현재 노래를 재생해야하는 플레이어, 라운드 종료 여부 등)을 결정하고 그와 관련된 로직을 Java, SpringBoot를 활용하여 구현
  • 투표, 랭킹 등 방송과 관련된 관리, 저장방식을 결정하고 구현(Redis, MySql)

왜 WEBRTC를 활용한 프로젝트를 만들었나?

기획 단계부터 시연 단계까지 모든 것을 팀에서 결정하여야 했다. 우리 팀에서 중요하게 생각한 것은, ‘흥미, 문제 해결’이었다. 먼저 서비스가 참신하고 참여하고 싶다는 생각이 들어야 하고, 이를 위해서 아이템도 트렌드에 맞춰서 선정하고 시연 때 임팩트를 줄 수 있어야 한다고 생각했다. 그리고 이와 동시에 어떠한 문제를 해결할 지에 대한 고민도 같이 해야 했다. 보다 새로운 문제에 대한 접근 방식으로, 최근 유튜브, 틱톡을 중심으로 쇼츠 컨텐츠에 대한 인기가 매우 높고, 춤은 이 쇼츠 컨텐츠와 매우 잘 맞는 장르였다. 그리고 인터넷 방송과 배틀적인 요소도 함께 추가해서 상호작용할 수 있는 요소를 추가하였다.
이를 통해 실시간 쇼츠 댄스 라이브 플랫폼 서비스라는 새로운 서비스를 만드는 것으로 결정하였고, 이를 구현하기 위해 화상통화 서비스를 쉽게 구현할 수 있는 Webrtc를 채택하였다.

왜 소켓 통신을 사용했나?

play-dance-live는 실시간으로 응원하는 플레이어에 대한 투표 데이터를 반영해야 했고 투표에 따라 랭킹의 변화 또한 반영하여야 했다. 또한 같은 방송을 시청하는 사람들끼리 채팅 메시지도 서로 송수신 할 수 있도록 하여야 했다.

시청자가 응원하는 플레이어에 대한 버튼을 누를 경우 모든 시청자들이 투표현황을 공유하여야 한다. 즉 시청자가 요청을 하지 않더라도, 서버에서 투표 현황에 대한 데이터를 방송의 모든 시청자에게 이를 공유하여야 한다는 것이다. 웹 소켓 통신을 구축함으로써 양방향통신을 구축함으로써 이를 해결하였다.

웹 소켓 연결을 통해 실시간으로 데이터를 전송하도록 하면 스트리밍, 폴링 방식보다 실시간에 가깝게 데이터를 처리할 수 있었고 트래픽이 줄어든다는 이점도 가진다.

STOMP를 사용한 이유

스프링에서 지원하는 STOMP를 사용하면 스프링 웹 소켓 어플리케이션은 STOMP Broker로 동작하게 된다. 우리는 Simple in-memory broker를 활용했다. 연결된 엔드 포인트로 클라이언트가 데이터를 전송하면 Spring은 그 데이터를 broker에 전달하고, broker는 websocket으로 연결된 클라이언트에게 메시지를 전달하는 구조가 된다. 이를 통해 실시간으로 데이터 전송이 가능해질 뿐만 아니라, 하나의 endpoint 연결만으로 같은 방에 있는 플레이어들 간의 데이터 송수신도 가능하게 되었다.

이를 통해 채팅, 투표, 랭킹 등 실시간으로 요청되는 데이터들을 같은 방에 있는 참여자 모두 동일하게 볼 수 있게 되었다.

왜 Openvidu를 선택했나?

다양한 이유가 있었다. 먼저 openvidu는 webrtc를 기반으로 하는 오픈소스 프로젝트였고 쉽고 빠르게 설치할 수 있다는 장점이 있었다. 이를 통해 미디어 서버를 구현하는데 소모되는 리소스를 절약해서 빠르게 실시간 통신을 구축할 수 있었다.

우리 서비스는 2:N 방식의 스트리밍을 제공하기 때문에 SFU 방식을 선택하는 것이 가장 적절했다. 서버와 클라이언트 간의 연결을 통해 모든 연결에서 클라이언트는 연결된 서버에만 자신의 영상데이터를 보내면 되고 서버는 이 영상 데이터를 연결된 모든 상대방에게 제공해준다. 그렇기 때문에 소규모 N:M인 우리 서비스에 적절한 방식이었다. openvidu는 이러한 중개 서버를 애플리케이션에 쉽게 추가할 수 있도록 기술 스택을 제공하는 플랫폼이었기 때문에 당시 빠른 서비스 제작을 위해 이를 선택했다.

그렇지만 문제가 있었다.

openvidu 프레임워크를 선택하여 더욱 편하게 미디어 서버를 구축하였지만 오히려 대부분의 설정을 자동으로 구성해주는 대신에 세세한 기능의 구현에서 제약이 따르는 것을 알게 되었다. 따라서 자체적인 TURN 서버를 구축하는 것이 더 좋은 문제 해결의 방법이 되었을 수도 있겠다고 생각하게 되었고, 적절한 기술을 선택하는 것의 중요성을 느끼게 되었다. 자세한 사항은 영상과 음악의 싱크에 대한 문제를 해결하는 과정에 기술하였다.

오디오와 영상의 싱크를 맞춰야 했다.

Play-Dance-Live는 온라인 댄스 배틀 플랫폼으로 춤과 음악의 싱크를 일치하는 것이 중요한 프로젝트였다. 당시 미디어 서버로 openvidu 프레임워크를 선택하였지만 openvidu의 기본 설정은 마이크 음성만 출력할 수 있게 되어 있었고, 음성 파일을 출력할 수 없었다.
처음 선택한 방식은 플레이어가 웹 소켓 신호를 보내면 서버에서 웹 소켓 브로커를 통해 시청자들에게 신호를 보내서 각자의 로컬 오디오를 동시에 재생하도록 하는 것이었다. 그렇게 되면 송출자가 춤을 추기 시작하면서 신호를 보내서 음악이 재생시킨다면 타이밍에 맞춰서 춤과 음악이 동시에 재생된다.
하지만 이는 다른 문제를 발생시켰다. 해당 방식은 노래를 재생시킬 때만 소켓 신호를 보내므로 중간에 들어오는 사람은 노래 시작 신호를 받지 못한다. 또한 로컬 오디오는 영상과 별도로 재생이 되고 있기 때문에 잠깐이라도 영상의 딜레이가 발생하면 영상과의 싱크가 맞지 않게 된다.
이를 위해 최종적으로 선택한 방식은 송출하는 쪽에서 MP3 음원을 오디오 소스로 사용하는 것이다. 앞서 언급한 대로 openvidu는 마이크와 같은 입력장치만 오디오 소스로 사용할 수 있기 때문에 MP3 파일을 송출할 수 없는 상황이었다. 이에 대한 대안으로 브라우저에서 지원하는 WebAudio API를 활용하였다. 기존에 마이크로 송출되던 오디오 소스를 MP3 파일로 대체하였고, 춤과 음악을 하나의 스트림으로 전송할 수 있게 되었다. 중간에 들어오는 시청자도 동일한 싱크로 영상을 감상할 수 있게 되었다.

하지만 싱크가 맞더라도 네트워크 등의 문제로 방송 스트림 자체가 버벅거릴 때 어떻게 보정할 것인가?

이 경우는 사실 생각조차 하지 못했다. 영상과 음원의 싱크를 맞추는데 공을 많이 들였지만, 싱크가 맞은 후에도 네트워크 자체의 지연으로 영상이 뚝 뚝 끊길 수 있었다. 이에 대한 보정 처리는 달리 고려하지 않았었는데 사실 질문을 듣고도 딱히 그럴듯한 해결 방안이 떠오르지 않았다. 추가적인 조사와 고민이 더 필요하다.

최대 몇 명까지 시청이 가능할지?

네트워크 상황만 잘 뒷받침 되어 준다면, 12명에서 15명 정도는 무리없이 시청할 수 있었다. 하지만 현재 구현 자체가 시연용에 최적화 되어있고, 춤을 추는 사람의 UI는 거의 개발자 용이나 다름 없어 시청자들의 의도하지 않은 조작이 서비스를 계속 다운시킬 수 있었다. 이는 완성도 측면에서 가장 먼저 보완해야 할 사항 중에 하나이다.

왜 Java/Spring을 선택했나?

처음 기획은 앞서 언급했던 대로 대규모 스트리밍 서비스였는데, 스프링 부트가 대규모 트래픽에 적합한 프레임워크라는 정보를 여러 채널을 통해 확인했었기에 무게가 실렸고, 좀 더 솔직하게는 이후에 취업을 위해 선택했던 스택이었다. 하지만 5주전으로 돌아간다면, node.js로 서버를 구축해 좀 더 짜임새 있는 코드를 빠르게 작성하고 여러 기능들을 더 고민해 볼 수 있는 시간을 많이 가졌을 것 같다.

방송의 진행 로직을 어떻게 구성하였나?

투표, 랭킹, 채팅 등과 같은 데이터들을 송수신하게 되면 모든 시청자들이 해당 데이터를 받을 수 있도록 웹소켓 통신을 구성하였다.
게임의 진행 방식에 대해서도 결정하고 이에 맞춰 구현을 했다.
먼저 참가자가 참가하기 버튼을 누르면 아래와 같이 다음 도전자에 들어가게 된다. 이후 본인의 차례가 됐을 때 본인의 화상통화 화면이 송출되게 구현하였다.

실시간으로 배틀을 진행할 때는 현재 챔피언과 도전자로 구분하여 챔피언이 먼저 춤을 추고 도전자가 이어서 춤을 추는 방식으로 라운드를 구성하였다.

각 참가자들은 노래에 맞춰 춤을 1번씩 추고 그동안 시청자들은 투표와 채팅을 통해 실시간으로 상호작용을 할 수 있도록 하였다.

이후 참가자의 노래가 끝나게되면 서버에서 현재 차례가 누구인지 (챔피언 혹은 도전자) 인지에 따라서 현재 투표 데이터에 따라 승자를 결정하고 승자 메세지를 출력하고 패배한 플레이어의 화상연결을 종료하고 대기자 중 첫 번째 플레이어와 화상연결을 하도록 하였다.

투표, 랭킹 등 방송과 관련된 관리, 저장방식을 결정하고 구현하였다(Redis, MySql)

당시 Redis를 처음 도입할 때 메인 DB의 캐시로만 사용하는 것으로 알고 있었다. 하지만 Redis의 특징인 ‘빠른 처리 속도’와 ‘in-memory’를 고려해 볼때 Redis를 인메모리 db로 사용할 수 있다는 것을 알게되었다. 따라서 실시간성이 중요하고 휘발성을 가진 데이터(투표, 대기열)를 Redis에 저장해서 빠른 처리를 보장하였다.
반면에 영속석이 보장되어야 하는 데이터(유저 연승전적, 랭킹)는 MySQL에 저장하여 사용하였다.
이를 통해 더 높은 성능과 안정성을 제공하였다.

프로젝트의 MVP 설정과, 개밥먹기의 중요성

프로젝트 기간은 4주에 달했지만 실제로 구현에 몰두한 기간은 2주에 불과했다. 그 이유는 우리가 MVP설정을 잘못했기 때문이다. 기획에 과도하게 몰두하다 보니 막상 기초적인 구현을 했을 때 프로젝트에서 아쉬운 부분이 많이 있었고 이는 프로젝트에서 많은 변경이 이뤄지게 만드는 원인이었다. 실제로 프로젝트에서 짜놨던 대부분의 백엔드 코드들은 4주간의 프로젝트 기간 중 1주 동안 구현한 코드였다. 기획이 바뀌면서 그것에 맞춰 서버의 코드도 변경되어야 했기 때문이다. 이러한 문제를 겪으면서 MVP설정을 빠르게 하고 실제 소규모의 프로젝트를 먼저 구현을 해보는 것의 중요성을 더욱 느끼게 되었다.

유사한 말로 개밥먹기 (dogfooding)라는 단어가 있어서 찾아보았다.

내가 개발하는 소프트웨어/서비스를 개발자/개발 회사의 직원이 직접 써 보고 실생활에 적용하는 것을 의미한다.

Eat your own dog food

닷컴 버블 시절 (1996 ~ 2000), 적당한 기능에 적당한 껍데기만 씌운 정말 프로그램들도 꽤 많이 나왔고 그에 대한 대응책으로서 개발자 사이에서 "개밥먹기", "dogfooding"이라는 말이 화제가 된 적이 있었다. 단순히 "해야 되니까", "하라니까" 프로젝트를 적당히 만드는 것이 아니라 직접 사용자가 되어서 직접 써 보면서 개발을 진행해나가는 것의 중요성을 느낄 수 있었다.

profile
daelkdev@gmail.com

0개의 댓글