pile·
백엔드·카카오 엔터테인먼트 FE카카오 엔터테인먼트 FE·

우당탕탕~ 영상 서비스 개발기 3탄 : 플레이어 백엔드 서버와 데이터 수집

카카오엔터테인먼트 영상서비스개발팀이 소녀 리버스 서비스를 만들며 겪은 백엔드와 데이터 파이프라인 이야기다. Go 채택과 프레임워크·ORM 선정, Cloud Run에서 GKE로의 이전, SSE 기반 응원 기능과 부하 테스트, 로그 수집부터 시각화까지 순서대로 짚는다. 아쉬웠던 점을 스스로 정리한 대목이 마지막에 붙는다.

핵심 포인트
  • 서버리스에서 Java와 Spring은 기동 시간만큼 콜드 스타트가 생겨 Go를 택했다.
  • ORM은 GORM에서 ENTGO로 옮기려다 코드 생성 설정 부담이 커 다시 GORM으로 돌아왔다.
  • Cloud Run은 목표 10만 TPS에 한참 못 미치는 3,000~7,000 TPS라 GKE로 옮겼다.
  • 응원 기능은 서버에서 클라이언트로 가는 일방향이면 충분해 WebSocket 대신 SSE를 골랐다.
  • SSE를 처리하는 Pod는 일반 API Pod와 달리 CPU보다 메모리를 많이 써 리소스 할당 근거로 삼았다.
  • 로그는 vector로 GCS에 모으고 Dataflow로 BigQuery에 적재해 Looker Studio로 본다.
상세 정리
  • 서버리스 선택 배경: 내부용 CMS는 트래픽이 높지 않고 단순 CRUD라 Cloud Function이나 Cloud Run을 써보자는 의견이 나왔다.
  • Java를 접은 이유: Java 자체는 콜드 스타트가 짧지만 Spring으로 구성하면 기동에 30초가량 걸려 서버리스와 맞지 않았다.
  • Go의 이점: 컴파일과 실행이 빠르고 바이너리 하나로 배포되며, 고루틴과 채널로 병행 처리가 쉽고 가비지 컬렉터가 메모리를 관리한다.
  • Go의 대가: Spring이 기본 제공하던 기능을 일일이 구현해야 해서 스크럼마다 Java로 돌아가고 싶다는 말이 나왔다고 밝힌다.
  • 프레임워크: 처음 다루는 언어라 레퍼런스와 문서가 많은 쪽을 찾아 Gin을 골랐다.
  • ORM 1차 시도: GORM은 where 조건과 join을 문자열로 써야 하고 자동완성을 쓸 수 없어 SQL을 생각보다 많이 작성하게 됐다.
  • ORM 2차 시도: ENTGO는 스키마 기반으로 코드를 생성해줘 기존 감각에 가까웠지만 설정 작업이 많아 경험치가 낮은 상황에서 부담이 컸다.
  • ORM 결론: 사용자가 가장 많은 GORM으로 돌아와 Preload와 매핑 같은 편의 기능을 제대로 쓰는 방향으로 정리했다.
  • 서버리스 1차: Cloud Function 1세대만 있고 2세대가 베타여서 기능 지원이 부족하다는 조언을 듣고 컨테이너 기반의 Cloud Run으로 옮겼다.
  • 성능 벽: 좋아요와 응원, 이어 보기 API는 사용자가 늘수록 부하가 커지는데, 외부에서 접근하는 조건으로 부하 테스트를 하니 목표치에 한참 못 미쳤다.
  • 원인 확인: 기능이 전혀 없는 Cloud Run 서비스를 만들어 재봐도 같은 결과가 나와 코드 문제가 아니라고 판단했다.
  • 이전 결과: 결국 쿠버네티스 기반 GKE로 옮겨 만족할 만한 수치를 얻었다.
  • SSE와 WebSocket 비교: SSE는 브라우저 내장 EventSource로 구현이 간단하고 자동 재접속이 되지만 HTTP에서 브라우저당 6개 연결 제한이 있고, WebSocket은 양방향이지만 구현이 복잡하다.
  • SSE 활용처: 응원 이펙트 전파 외에 CMS의 인코딩 진행률을 실시간으로 보여주는 데도 쓴다.
  • 부하 테스트 도구: SSE 성능 테스트를 공식 지원하고 오픈소스이며 국내 사용자가 많은 Gatling을 골랐다.
  • 테스트 구성: 로컬에서 스크립트를 만든 뒤 대량 트래픽을 만들기 어려워, Pod당 2천 명이 접속하는 이미지를 만들어 EKS에서 Pod를 늘려가며 접속자를 키웠다.
  • 남은 한계: 접속자가 새 Pod로만 가지 않고 기존 Pod에도 유입돼 부하가 걸리는데, 연결이 가장 적은 Pod로 보내는 IPVS 모드를 GKE 클러스터가 지원하지 않아 Pod를 넉넉히 띄우고 지켜보는 방식으로 대응했다.
  • 수집 경로: Playback API 로그를 vector로 GCS에 파일로 모으고, Dataflow가 주기적으로 BigQuery에 적재하며, Looker Studio로 대시보드를 만든다.
  • 수집기 선택: fluentbit, fluentd, vector 중 GCS를 공식 지원하고 벤치마크 성능이 우수한 vector를 DaemonSet으로 띄웠다.
  • 제공 지표: 시청 수, 동접자 수, 채팅 메시지 수, 좋아요 수, 응원 수를 뽑는데 동접자 수는 SSE 서버의 커넥션 수로 센다.
  • 아쉬운 점 1: GCS 적재는 스트리밍으로 당겨오기에 부적합하고 파일 생성 시간 때문에 수집이 지연돼 메시지 브로커로 push하는 방식을 검토 중이다.
  • 아쉬운 점 2: Looker Studio는 가공과 커스터마이징이 제한적이라 일부는 BigQuery에서 계산한 뒤 표로 제공했다.
  • 아쉬운 점 3: 데이터 플랫폼 경험이 없는 팀이라 서비스 중간에 파이프라인을 바꾸거나 수집 대상 로그를 추가하는 일이 있었다고 인정한다.
왜 읽나서버리스로 시작했다가 성능 벽에 부딪히거나 실시간 전파 기능을 붙여야 하는 상황이라면, 선택마다 무엇을 재보고 무엇 때문에 되돌렸는지가 구체적으로 나온다.
카카오 엔터테인먼트 FE
카카오 엔터테인먼트 FE 블로그
원문은 여기서 이어서 읽을 수 있어요
원문 읽기
읽음 (0)

이 글과 비슷한

  1. 백엔드·twilio-engTwilio Engineering·

    Programmable Messaging에서 Verify API로 마이그레이션하기

    Twilio의 Programmable Messaging API로 자체 OTP 솔루션을 운영하던 서비스가 Verify API로 전환하는 방법을 코드 예시와 함께 설명한다. Verify는 OTP 전송·검증을 위한 전용 API로, 전화번호 구매, 토큰 생성, DB 저장·만료 관리를 내부에서 처리해 개발자가 직접 구현할 코드를 크게 줄인다.

    요약 이어보기
    #authentication#twilio#sms+2
  2. 백엔드·포스타입포스타입·

    포스타입이 개인화 추천을 하는 방법 2부

    포스타입 백엔드 엔지니어가 벡터 기반 개인화 추천 시스템을 실제 운영하며 맞닥뜨린 성능 장애와 용량 문제를 해결한 과정을 담은 2부다. 수백만 개의 벡터 KNN 검색이 피크 시간대에 전체 Elasticsearch 검색 성능을 흔드는 문제부터 클러스터 OOM 사태까지, 쿼리 최적화와 인프라 분리 두 가지 경로로 근본 해결에 이른다.

    요약 이어보기
    #elasticsearch#vector-search#recommendation-system+2
  3. 백엔드·포스타입포스타입·

    포스타입이 개인화 추천을 하는 방법 1부

    포스타입이 태그 기반 추천의 한계를 극복하고 벡터 임베딩 기반 개인화 추천 시스템을 구축한 과정을 담은 1부다. 유사한 콘텐츠가 다른 용어를 쓰거나 동일한 태그가 전혀 다른 톤의 콘텐츠를 가리키는 문제를 임베딩 벡터로 해결하고, OpenSearch의 HNSW ANN 검색으로 수백만 벡터를 실시간 검색하는 시스템을 구축해 구매율 15% 향상을 달성했다.

    요약 이어보기
    #opensearch#vector-search#recommendation-system+2