포스트

통합 플랫폼(치지직 CHZZK, SOOP 등) 투표 추첨기 개발 및 기획

치지직, SOOP 등 다양한 스트리밍 플랫폼을 지원하는 통합 투표 추첨기를 Nuxt.js와 Vue로 개발한 과정을 기록한 개발일지

통합 플랫폼(치지직 CHZZK, SOOP 등) 투표 추첨기 개발 및 기획
통합 플랫폼 투표 추첨기
  • 개발 기간 : 2024. 02. 28 ~ 2024. 7. 1
  • 개발자 : lcmykr(기획, 서브 개발), 기우(메인 개발), 박설명(TTS 작업 도움)
  • 기술 스택 : Nuxt.js, Vue, Tailwind CSS, CHZZK unofficial API, Figma
  • 주요 기능 : 실시간 채팅 연동, 간편 추첨, 숫자 투표, 슬롯머신 애니메이션, TTS
  • 운영 상태 : 중단 (당시 홍보 부족 및 개인 사정 등)

서론

2023년 12월, 트위치가 서비스 종료 소식이 떨어지면서 스트리머들의 이주에 대해 위기에 놓였다. 후발주자인 2024년 2월 쯤, 네이버에서 개발한 치지직으로 런칭되었고, 많은 스트리머들이 이주하면서 당시에 많은 스트리머들이 사용하던 확장프로그램 트위치 투표 추첨기를 치지직에서도 사용할 수 있도록 (당시) 비공식 API 를 사용하여 치지직 투표 추첨기 뿐만 아니라 2024년 2월 트위치가 한국 서비스를 종료하게 되면서 동시송출을 하던 스트리머들을 위해 옆동네인 (구)아프리카TV, SOOP 과 동시에 투표하여 사용할 수 있도록 만들 계획이였다.

계획 과정

2024년 2월 말, 지인 개발자과 함께 통합 플랫폼 투표 추첨기 프로젝트를 협업하여 개발 및 기획하기로 결정하여 진행했다.

당시 프로토타입은 다음과 같았다. 기존에 있었던 확장프로그램 트위치 투표 추첨기를 기반으로 UI나 투표 방식에 대해 친숙하게 사용할 수 있도록 계획했다.

image1

처음에는 기존에 만들었던 채팅 봇 빵떡의 통합 폴랫폼 추첨기(뽀바부러)에 넣어서 운영 할 목적으로 개발을 진행했으나, 여러 이슈(서로간의 연결 문제 등)가 있어 분리하여 단독적으로 운영 및 개발을 진행하기로 결정했다.

기존에 있었던 추첨기와 같이 간편 추첨1과 숫자 투표2을 지원하도록 하여 기존의 UI 와 전반적인 투표 시스템을 가져와 기존에 사용하던 스트리머에게 익숙함을 제공하고자 했다.

결론적으로는 아래 내용과 같이 만들려고 했다.

  • 치지직 뿐만 아니라 SOOP(구 아프리카TV) 등 다양한 플랫폼 지원
  • 기존 UI 와 시스템을 그대로 구현
  • 그 외에도 다양한 기능(투표 방식) 추가
  • 유지 비용을 최소화할 수 있도록 최적화 작업하는 등

개발 과정

◆ FrontEnd

본격적인 개발을 진행하기 위한 첫 걸음으로 협업 구성원이 Figma를 통해 FrontEnd, 즉 사용자에게 보여지는 UI 화면 부분을 구현했다.

image2 전반적인 구현 모습

◆ 채팅 및 채널 연동

  1. 채팅 및 채널을 연동하기 위해서 치지직 채널 UID를 입력하거나 이름을 입력하여 본인 채널을 선택하게 되면 Cookie 에 channelID를 저장한다.

  2. Cookie 에서 channelID 를 읽어 내부 코드에서 channel() 치지직 비공식 API 로 채널 상세정보를 불러온다.

  3. 내부 코드에서 Chat() 루프가 방송 온라인을 확인하고, client.chat() 로 WebSocket 채팅을 연결하고,

  4. chat 이벤트를 통해 실시간 메세지를 수신 받게된다. $emit('ChatEvent') 이벤트를 통해 페이지에 전달한다.

    • $emit 은 Vue.js 에서 구축된 components로 내장 메서드 이벤트를 발행하는 역할을 한다.

◆ 투표 시스템

  1. 간편 추첨 - 시청자가 채팅만 입력하면 자동으로 참여된다.

  2. 숫자 투표 - !투표 <번호>, !vote <번호>, !v <번호> 를 입력하면 시청자는 투표에 참여할 수 있다.

  3. 숫자 투표를 빠르게 진행할 수 있도록 스트리머가 ‘바탕화면’ 이나 전용 공간에 저장하고, 파일을 불러오면 해당 내용을 불러올 수 있도록 .ipvd 커스텀 포맷(Base64 인코딩된 JSON 파일)을 하여 숫자 투표 항목을 불러오거나 저장할 수 있도록 구축해두었다.
    • 또는 숫자 투표 항목을 CooKie 등에 저장하여 이전에 진행한 투표 항목을 그대로 불러올 수 있었다.
  4. 실시간으로 참여한 투표율을 표시할 수 있으며, 숨길 수 있도록 하는 등 이전의 시스템 등을 그대로 구축해두었다.

◆ 룰렛 구조

시청자를 모으고 당첨자를 뽑기 위한 구조는 다음과 같이 구현되었다. 전반적인 애니메이션 모습은 TailWind CSS 를 통해서 구축했다.

  1. 투표 당첨자는 애니메이션 시작 전 내부 코드에서 당첨자를 결정한다. 즉 룰렛 애니메이션은 연출용이라는 뜻.

  2. 참가자를 필터링할 수 있게 구축해두었다. 투표 중 이미 당첨된 시청자는 ban.participant 를 통해서 제외하며, 구독자만 투표하는 항목으로 this.subscribe_only 을 통해서 당첨자를 뽑을 수 있다.

1
2
3
4
5
6
7
8
9
10
let participant_list = []
if (this.subscribe_only) {
    participant_list = this.participant.filter(
        item => !this.ban_participant.includes(item.name) && item.subscription
    );
} else {
    participant_list = this.participant.filter(
        item => !this.ban_participant.includes(item.name)
    );
}
  1. 룰렛 애니메이션에 표시할 닉네임 리스트는 항상 맨 마지막에 표시될 수 있도록 하고, 참여한 시청자가 적을 경우에는 중복 표시될 수 있도록 하여 연출을 만들어 두었다.

  2. 애니메이션 같은 경우에는 TailWind CSS를 통해서 구축했다.

    • 총 550ms 동안 cubic-bezier(0, 0, 0, 1), translateY=10 효과를 주어 룰렛을 시작하겠다는 효과를 주었으며,
    • 각 이름 칸의 높이를 맞춰 속도를 자동적으로 대응하여 마지막 항목인 slot_translate 까지 스크롤 한 다음,
    • 스크롤이 완료 되었을 때 winner_user 를 당첨자 화면에 표시될 수 있도록 한다.

◆ 사용자 컬러 시스템

  1. chat.profile.color 를 통해 우선적으로 사용자(시청자)가 사용하고 있는 색상으로 적용 및 확인 할 수 있도록 하였다.
  2. 해당 색상이 적용되지 않거나 색상이 없다면, userIDHash, channelID 를 이어붙여 Hash 50가지의 색상을 배정받을 수 있도록 구축했다.

◆ 이모지 관련

치지직 unofficial API 를 통하여 이모지를 FETCH 하여 {emojiID:} 패턴을 받아 <img> 태그로 치환할 수 있도록 구축했다.

◆ TTS 기능

Web Speech API 을 통하여 일본어, 영어, 한국어를 자동으로 감지할 수 있도록 하였고, 로컬 브라우저 환경(Chrome, Edge 등)에 따라 다양한 TTS 를 적용할 수 있도록 기반다졌다. (API 사용량 등을 절감, 로컬 환경으로 구축)

◆ DataBase

이런 프로젝트의 가장 핵심적인건 DataBase라고 생각한다. 어떻게 관리되고 있으며 이런 정보들을 어떻게 사용되고 있는지 궁금할 수도 있을 꺼 같다. 이 프로젝트는 해당 정보들을 내부 서버에 데이터를 수집 하지 않는다.

모든 내용은 Cookie, SessionStorage, LocalStorage 로만 저장되어 DB에 관련 내용을 담지 않아 사용자와 개발자(및 운영자) 등 모두 데이터 수집을 하지 않아 개인정보 등 관련하여 이용 하는데 크게 신경쓰지 않아도 된다는 점이 있다.

Comments

image3

image4

실시간 채팅 및 채널 연동은 프로젝트의 핵심 기능이었다. CHZZK unofficial API를 활용하여 치지직 채팅을 WebSocket에 연결하고, 메시지 간 평균 시간을 계산하여 장시간 비활성 시 자동으로 연결을 해제하는 타임아웃 감지 시스템을 구현했다.

다만, 치지직(CHZZK)을 시작으로 SOOP(구, 아프리카TV), Twitch 등에도 지원하기 위하여 인프라를 구축하였지만, 실제 구현까지는 이어지지 못했다.

이 프로젝트를 기획하고 구축하는데에 총 4개월 정도 걸린거 같았다. 이 프로젝트의 8,90% 이상의 기능(시스템) 구축하는 것은 같이 협업하여 개발을 진행해준 지인 기우가 웬만한 기능을 주도적으로 나서서 구현해주었다.
(Nuxt 쪽은 잘 모르기에..)

이 글을 적으면서 아래 내용과 같이 이 프로젝트가 끝까지 이어가지는 못했지만, 여러 생각이 들었다.

◆ 최종 결산

  • 좋았던 점
    1. 기술적으로 이번 프로젝트를 하게 되면서 Nuxt.js 환경에 대해 조금이나마 알 수 있었던 좋은 계기였던 거 같다.
    2. 이 프로젝트를 통해 치지직(CHZZK)에 조금이나마 더 다가가 개발 환경을 구축할 수 있을 꺼 같다는 생각이 들었다.
      • 다만 사용하는 스트리머 분들 중에 타임아웃이 되거나 투표 홈페이지가 먹통이 되어 이 부분에 대해서는 보완해야 겠다는 생각이 들었다.
    3. 같이 이 프로젝트에 협업하여 개발하게 된 개발자 지인들에게 매우 고마웠다.
      • 짧은 시간만에 이 프로젝트를 기획하게 되어 부족한 기획 내용이 있었음에도 협업(개발)에 참여하여 개발자 기우님과 도움을 주신 개발자 박설명님에게 감사 한 말씀 올립니다 🙏
      • 협업 과정에서 기획자(서브) 와 개발자 간의 역할 분담에 대해 많은 내용을 배웠던 거 같다. 프로토타입 뿐만 아니라 Plan A~E 등을 고려하여 추가적으로 구축할 수 있도록 해야겠다는 점을 배웠다.
  • 아쉬웠던 점
    1. 치지직(CHZZK)을 시작으로 SOOP, Twitch, Kick 등 타 플랫폼 연계에 대해 인프라를 구축하였지만 실제 구현까지 이어지지 못해 아쉬웠다.
    2. Nuxt.js 엔진으로 구현이 되어 부족한 내 역량으로 직접적인 개발 참여는 어려워 시스템 추가 구현 및 보수(수정)가 어려웠다.
    3. 개발자들의 개인 사정으로 타임아웃이나 먹통 등 안정성 이슈를 빠르게 해결하지 못하여 아쉬웠다.
    4. 런칭 이 후 홍보와 이용자들을 모을만한 방법이 부족하여 더 많은 스트리머(이용자)를 모으지 못해 아쉬웠다.

P.S

이 프로젝트를 개발한 기간이 4개월 정도 되는데, 런칭 이 후 홍보 및 이용자를 모을만한 방법이 부족하여 더 많은 스트리머들을 모으지 못해서 아쉬웠다.

또한, Nuxt.js 로 구현이 되어 있었기 때문에 내 기술(Stack)으로는 보수 작업 및 시스템 구현이 어려워서 아쉬움이 많았다.

짧은 단 기간만에 기획을 하게 되었지만, 부족한 기획 내용이 분명 있었음에도 협업에 참여해주신 개발자분들에게 너무 감사했고, 짧은 기간 만에 이 서비스를 종료하게 되어 아쉬움이 많다.

이용해주셨던 스트리머 약 20명에게 감사드립니다!

이 프로젝트를 통해서 많은 부분을 배우고 경험했다.

2026년 현재는 큐브 프로젝트 라는 이름으로, 누구나 손 쉽게 사용할 수 있도록 하는 다용도 도구 웹 페이지를 구축하고 있다. 큐브(Cube)는 일반인이 사용할 수 있도록 하는 페이지와, 스트림 큐브(Stream Cube)는 스트리머(방송인)이 다양한 기능을 한 페이지에서 사용할 수 있도록 하는 메인? 프로젝트를 기획하고 개발하고 있다.

이 프로젝트의 후신 같은 느낌으로 치지직 투표 추첨기를 개발하고 있으며, 다양한 추첨 방식과 시스템을 제공하려 노력하고자 한다.

  1. ‘시작’ 했을 때 아무런 채팅을 입력하였을 경우 참여자로 올릴 수 있도록 하는 방식 ↩︎

  2. ‘시작’ 후 시청자가 ‘!투표 1’ 등 명령어를 입력했을 때 참여자로 올릴 수 있도록 하는 방식 ↩︎

이 글은 저작권자의 CC BY 4.0 라이센스를 따릅니다.