Tech

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

ENTER TECH 2023. 4. 4. 11:02

 

 

앞서 인코더와 라이브 서비스에 관한 내용을 다뤘는데요.

이번 편에서는 플레이어 백엔드 서버와 로그 수집 분석에 대해 다뤄보고자 합니다.

 

아직 '우당탕탕~ 영상 서비스 개발기 2탄 : 인코더와 라이브 서비스' 편을 보지 못하셨다면 아래 글을 클릭해 주세요!

 

▶️ 우당탕탕~ 영상 서비스 개발기 2탄 : 인코더와 라이브 서비스

 

우당탕탕~ 영상 서비스 개발기 2탄 : 인코더와 라이브 서비스

앞서 영상 서비스 어드민, VODKA에 관한 내용을 다뤘는데요. 이번 편에서는 영상 서비스 인코더와 라이브 서비스에 대해 다뤄보고자 합니다. 아직 '우당탕탕~ 영상 서비스 개발기 1탄 : 어드민, VODK

kakaoentertainment-tech.tistory.com

 

 

 

 

오늘도 화목한 영상서비스개발팀💕

 


 

[Chater 5] 플레이어 백엔드 서버

 

VODKA(CMS) 백엔드 API부터 Player 백엔드 API까지 다양한 기능의 API를 개발합니다. 해당 챕터에서는 백엔드 API를 개발할 때 어떤 기술과 Framework를 사용했는지, 어떤 고민이 있었고 어떻게 해결해 나갔는지에 대해 설명하고자 합니다.

 

1.  Go VS Java 

첫 시작은 위에서 설명한 VODKA(CMS)의 백엔드 API 개발부터 시작되었습니다. 이번 프로젝트는 GCP를 활용하여 개발을 진행하였습니다. VODKA는 내부에서만 사용하는 Admin 툴이다 보니 트래픽이 높지 않고, 비교적 간단한 CRUD 형태의 백엔드 서버를 개발하면 될 것으로 생각했기에 다른 환경에서는 사용해보지 못한 GCP의 Serverless 서비스인 Cloud Function이나 Cloud run을 사용해 보면 좋겠다는 의견이 나왔습니다. 단, Serverless를 이용하게 되면 Cold Start 시간문제가 발생하는데, 이 때문에 과거 백엔드 API 구성 시 주로 사용했던 Java + Spring boot를 사용하지 못한다는 결론이 나왔습니다.

 

Cold Starts in Google Cloud Functions (https://mikhail.io/serverless/coldstarts/gcp/)
Cold Starts in Google Cloud Functions (https://mikhail.io/serverless/coldstarts/gcp/)

 

위 그림에서 보이듯이 기본 Java만 사용한다면 Cold Start 시간이 오래 걸리지 않습니다. 하지만 대부분 Java로 웹 프로젝트를 생성할 때는 Framework로 Spring을 사용하게 됩니다. Serverless 기반에서 Spring으로 프로젝트를 구성하고 첫 호출을 하게 되면 Spring의 기동시간만큼 딜레이(일반적으로 약 ~30초)가 발생하기 때문에 Cold Start 이슈가 발생합니다. 이러한 이유로 성능적으로 문제가 되지 않는 Go를 고려하게 되었습니다.

 

Go 언어의 장점은 아래와 같습니다

1️⃣ 빠른 컴파일과 실행 속도
Go는 컴파일 시간이 빠르며, 실행 속도도 빠릅니다. 이는 Go 언어의 특징 중 하나인 병행성(Concurrency)과 관련이 있습니다. 또한, Go는 컴파일러와 런타임을 하나의 바이너리 파일로 묶어서 배포할 수 있기 때문에 실행 환경 구성이 간단합니다.

2️⃣ 간결하고 가독성 높은 코드
Go 언어는 문법이 간결하며, 가독성이 높은 코드를 작성하기 쉽습니다. 이는 코드 유지 보수성을 높이고 개발 생산성을 높일 수 있습니다.

3️⃣ 병행성 처리를 위한 고루틴(Goroutine)과 채널(Channel)

Go 언어는 고루틴(Goroutine)이라는 가벼운 스레드와 채널(Channel)이라는 통신 메커니즘을 제공하여 병행성 처리를 쉽게 구현할 수 있습니다. 이는 멀티코어 환경에서 높은 성능을 발휘할 수 있도록 합니다.

4️⃣ 메모리 관리

Go 언어는 가비지 컬렉터(Garbage Collector)를 사용하여 메모리 관리를 자동으로 처리합니다. 이는 개발자가 메모리 관리를 수동으로 처리할 필요가 없어지므로 개발 생산성을 높일 수 있습니다.

5️⃣ 크로스 플랫폼 지원

Go 언어는 크로스 플랫폼을 지원하며, 다양한 운영체제와 아키텍처에서 실행 가능합니다. 이는 개발자가 다양한 플랫폼에서 언어를 사용할 수 있도록 하며, 서버 개발 등에서 유용합니다.

 

결론적으로 Go는 Java보다 더 빠르고 간결하며, 병행성 처리 등에 적합하다고 판단되어 다 같이 학습하며 프로젝트를 진행해 보자는 결론을 내렸습니다. Go는 오랫동안 사용해왔던 Java와는 문법이 달라서 학습 초기에 언어에 익숙해지는 데 시간이 오래 걸렸습니다. 하지만 어느 정도 익숙해져 가면서 하나의 서비스를 구성하기 위한 기본적인 코드 자체가 많지 않고, 단순하고 빠르게 개발하는 데에는 정말 편리한 언어라는 생각을 하게 되었습니다. 물론, spring에서 기본적으로 제공해 주던 기능들을 Go는 기본적으로 지원하지 않아 일일이 다 구현을 해야 한다는 사실을 발견하면서 다시 Java로 돌아가고 싶다고 스크럼 시간마다 외친 적도 있습니다.

 

vodka 2차 스프린트 회고 내용 중...

 

물론 지금은 Go와 Java의 다름을 이해하게 되었고, 개발요건에 따라 두 가지 언어 중 무엇이 더 적합한지 빠르게 판단하여 활용할 수 있어 개발에 대한 유연성이 생긴 것 같아 한층 성장한 기분입니다.

 

 


 

2.  Golang Framework 선정

Go를 본격적으로 개발하기 위해 가장 먼저 고려한 것은 Framework였습니다. Go에는 정말 많은 Framework가 존재합니다. 사실 아래에 자세하게 설명하겠지만, Go 활용해 개발하기 위해서는 Framework 말고도 정말 많은 것들을 선택해야 하는 순간들이 발생했습니다.

 

Go HTTP Framework 비교

 

Framework별로 여러 가지 장/단점이 있지만, 처음 개발하는 언어이기 때문에 레퍼런스와 문서들이 많은 Framework를 찾게 되었고 그 결과 Gin Framework를 사용하는 걸로 결정하게 되었습니다. 

 
 
gin github에 있는 Benchmarks (GitHub - gin-gonic/gin: Gin is a HTTP web framework written in Go (Golang). It features a Martini-like API with much better performance -- up to 40 times faster. If you need smashing performance, get yourself some Gin.)

 

ORM의 선택

Gin으로 개발을 시작하면서, 가장 먼저 필요했던 건 DB 연동을 위한 ORM 선택이었습니다.
여기서부터 고난이 시작되었습니다... 😭
ORM도 정말 많은 종류가 있었고, 여러 ORM을 비교한 끝에 레퍼런스와 참고할 문서가 비교적 많은 GORM을 선택했는데, 문서만 참고해도 개발이 어렵지 않았던 초기와 달리 개발을 계속하면 할수록 '이거.. 내가 생각했던 ORM이 아닌데??...'라는 생각을 하게 되었습니다.

 
where 조건을 넣을때 string형태로 작성이 필요
 

일단 GORM을 사용하면서 가장 번거롭고 불편하게 느껴졌던 부분은, SQL을 생각보다 많이 작성해야 한다는 점이었습니다. (JPA를 쓰면서는 느끼지 못했던) 예를 들어, Join의 처리도 Join이라는 메서드로 연결되긴 하지만 사실 그 안에 작성되는 코드들은 대부분 string 형태로 되어 있어 조건을 string 형태로 작성해야 한다는 점, 그리고 그동안 편의기능으로 제공되었던 자동완성 기능을 하나도 사용하지 못한다는 점에서 이건 아니다 싶어 다른 ORM을 찾아보기 시작했습니다.

그다음으로 검토했던 것은 ENTGO입니다. ENTGO는 스키마에 정의된 내용을 기반으로 코드를 자동 생성해 주는 방식의 ORM이었습니다. GORM 보다는 기존에 사용해 봤던 ORM의 특징에 더 가까웠지만, 코드 Generation을 위한 설정 작업이 생각보다 많이 필요했습니다.

 

code generation을 위한 스키마 설정 및 생성 처리
 

당시 golang에 대한 경험치가 낮은 상황이라 새로 구조를 설정할 부분이 많다는 것에 부담이 크게 작용했고, 이러한 이유로 다른 ORM을 더 찾아보았지만, 결론적으로 사용자가 가장 많은 GORM을 다시 잘 구현해 보는 방향으로 전향하였습니다.

 

Preload로 연관된 데이터 쿼리를 자동으로 생성해줍니다~

 

다대다 관계 설정도 가능해요~
 

 

GORM은 Preload나 Mapping 등 편의 기능을 잘만 사용하면 원하는 결과를 얻을 수 있어 현재까지는 특별한 이슈 없이 사용하고 있지만, 이제 경험치가 좀 쌓인 만큼 ENTGO로 변환하는 것도 도전해보고 싶네요~!

 

 


 

3.  GCP와 친해지기

GCP는 이번 프로젝트에 처음으로 사용해 보게 되었는데, 먼저 GCP에 어떤 서비스들이 있는지 확인을 하고 기존에 사용하던 AWS와 GCP 서비스를 비교하는 작업을 시작했습니다.

 

클라우드 플랫폼 별 서비스 비교 페이지


처음 개발을 시작할 때, serverless 서비스를 쓰기로 했기 때문에 GCP의 cloud function을 학습하였습니다. cloud function은 AWS의 lambda와 비교되는 서비스로, 함수형태로 서비스를 구성하여 생성하면 그에 대한 endpoint로 서비스를 호출할 수 있게 해주는 serverless 서비스입니다. 하지만 Google과의 서비스 구성에 대한 회의에서 cloud function의 단점을 듣게 되었습니다.

지금은 2세대로 사용해도 될듯 합니다

 

당시에는 cloud function 1세대만 존재하였고 2세대는 베타인 상태라 현재 2세대에 있는 기능에 대한 지원이 부족하였습니다. 이 문제에 대한 솔루션으로 cloud function에서 문제가 되는 부분을 커버할 수 있는 cloud run 사용을 권장받게 되었습니다. cloud run은 컨테이너 기반의 serverless 서비스로, 기존 함수를 컨테이너로 변경하여 개발을 진행할 수 있었습니다. 현재 CMS에서 사용하는 모든 백엔드 서비스는 cloud run으로 서비스하고 있습니다.

 

 

GKE(Google Kubernetes Engine)로 또 한 번 이동

하지만, 또 한 번에 고난이 찾아왔습니다. 😭 플레이어에서는 '좋아요, 응원, 이어 보기' 등의 API가 필요한데, 이 API들의 경우 유저 수가 많아질수록 사용량이 증가하기 때문에 API의 성능이 매우 중요했습니다. 지금까지 해왔던 대로 cloud run으로 서비스를 구성하고, 실제 환경과 유사한 외부에서 접근하는 테스트를 위해 AWS에 ngrinder(성능테스트 도구)를 설치하여 성능테스트를 수행해 보니 팀 목표로 설정한 10만 tps에 턱없이 부족한 3,000~7,000 tps 이상의 성능이 나오지 않았습니다. (목표치를 너무 높게 잡긴 했습니다만...)

코드상의 문제일까 싶어, 아무 기능도 없는 cloud run 서비스를 만들어서 테스트도 해보았지만 동일한 결과가 도출되는 것을 보고 고성능을 요구하는 서비스 구성에는 cloud run이 적합하지 않다는 결론을 내리게 되었습니다.

결국 GCP사용 전에 많이 사용했던 kubernetes 기반의 GKE를 사용하였고, GKE에서는 만족할만한 결과를 얻을 수 있었습니다.

 

개발환경에서 resource를 줄이고 테스트

 

 


 

4.  응원 SSE(Server-Sent Events)

이번 소녀 리버스 플레이어를 개발하면서 새로 추가한 기능이 있는데 바로 '응원'입니다. 시청자가 지지하는 소녀가 나올 때 응원 버튼을 클릭하면 그 시점에 effect가 발생하게 되고, 그 effect를 시청자 모두가 볼 수 있도록 하는 기능을 구현하는 것이었습니다. 기능 구현을 위해 검토한 기술은 SSE와 WebSocket이었는데, 둘 다 서버와 클라이언트 간의 통신을 지원한다는 점에서는 비슷해 보이지만 목적과 사용 방법에 차이가 있습니다.

 

SSE vs WebSocket

구분 SSE(Server-Sent Events) WebSocket
통신방법 - 일방향 통신 (서버 -> 클라이언트) - 양방향 통신 (서버 <-> 클라이언트)
특징 - EventSource 객체를 사용하여 구현
- 서버에서 클라이언트로 데이터를 전송할 수 있고, 클라이언트는 이를 수신하여 적절한 처리를 할 수 있음
- WebSocket 객체를 사용하여 구현
- 서버와 클라이언트 간에 언제든지 데이터를 전송할 수 있음
장점 - 간단한 구현, 브라우저 내장 기능을 사용하기 때문에 별도의 라이브러리가 필요 없음, 자동으로 재접속 처리 - 양방향 통신이 가능하므로 실시간 채팅, 멀티플레이 게임 등에 유용함
단점 - HTTP로 연결할 경우 브라우저당 6개까지만 가능, HTTP2의 경우 100개까지 가능 - 구현이 복잡하며, 서버와 클라이언트 모두 WebSocket을 지원해야 함

 

이번 서비스에서 필요한 '응원' effect는 일방향 통신만 가능하면 되는 것이어서 빠르고 구현이 쉬운 SSE를 선택하였습니다. SSE는 하나의 브라우저에서 6개까지의 연결만 허용하므로 7개 이상의 연결이 필요할 경우 사용을 할 수 없지만, 이번 서비스에서는 하나의 연결만 필요하기 때문에 특별한 이슈는 없었습니다. 서버 접속 시에 필요한 데이터를 확인하기 위한 최소한의 정보는 query parameter를 사용하여 값을 전달하고, 서버에서는 해당 값을 이용하여 필요한 값을 주기적으로 응답해 줄 수 있습니다. 현재는 라이브 시 응원데이터를 노출하는 데 사용하고 있고, 추가적으로 CMS인 VODKA에서 영상 인코딩 시에 인코딩 진행률을 실시간으로 보여주는 데 활용하고 있습니다.

 

인코딩 진행률 SSE 연동

'응원'의 경우에는 영상을 보는 모든 사용자에게 해당 메시지가 전달되고 실시간 반영되어야 하므로 성능적으로도 중요도가 높고, 팀 목표치인 10만 명 동접자를 고려해 부하테스트를 진행했습니다.

 

 


 

5. 부하테스트

Tool 선정

SSE로 성능테스트를 진행해 본 경험이 없다 보니, SSE에 대한 성능테스트가 가능한 테스트 Tool을 중점으로 검색하게 되었습니다. 여러 성능테스트 Tool이 있었지만, 대부분 SSE를 지원하지 않거나, 편법으로 해야 하는 부분들이 있어 선택을 못하던 중 Gatling이라는 성능 테스트 Tool을 찾게 되었습니다. Gatling은 국내 사용자가 많고, 공식적으로 SSE 성능테스트 기능을 지원하고 있다는 점과 무엇보다 오픈 소스로 되어 있어 Gatling을 선택하게 되었습니다.

 

유레카~

물론 관련 문서도 아주 깔끔하게 잘 되어 있습니다.

 

방식

구성 방식은 Java, Kotlin, Scala를 이용하여 스크립트를 작성하고, 해당 스크립트를 Gatling을 통하여 수행하도록 하는 방식입니다.

 

scala로 작성된 sse 공식 예제

 

스크립트는 체인방식으로 수행하는 부분과 그 수행결과를 체크하는 방법 등 여러 가지 기능들이 있어 이를 조합하여 하나의 시나리오를 만들어 테스트할 수 있습니다.

 

하나의 pod에서 2,000명이 접속하여 데이터를 정상적으로 수신하는 테스트 중

 

우선 로컬 환경에서 테스트를 해보며, 스크립트를 작성하였고, 로컬환경에서는 대량의 트래픽을 만들기 어려워, AWS의 EKS(Elastic Kubernetes Service)를 이용하여 Pod별 2천 명의 유저가 접속하는 형태의 이미지를 생성하여, 테스트 시 Pod를 늘려가며 점점 많은 유저가 접속하는 테스트를 진행하였습니다.

 

 

결과 & 후기

테스트 결과, '일반적인 API 요청을 받아 처리하고 응답을 주는 Pod'는 메모리보다 CPU를 더 많이 사용하는 현상을 보였지만, 'SSE를 처리하는 Pod'는 CPU보다 메모리를 많이 사용하는 현상이 나타났고, 이 정보를 바탕으로 Pod의 리소스를 할당하는 데이터로 활용하였습니다. Kubernetes의 Pod로 구성하여 Pod의 수를 늘리며 대량 접속자를 대응하도록 구성하였는데, 특정 Pod에 접속하게 되면 이를 유지하고 해당 Pod의 리소스를 사용하게 됩니다. 준비된 Pod 이상으로 동시접속자가 몰리면 Pod는 추가로 늘리면서 접속자를 대비하지만, 문제는 접속자가 새로운 Pod로만 유입되지 않고 기존 Pod로도 유입되어 Pod에 부하가 걸리는 경우가 발생하는 부분이었습니다. 서스 라우팅 방식인 IPVS 모드를 사용하면 least connection 방식으로 가장 적게 연결된 Pod로 유입할 수 있었지만, 아쉽게도 GKE의 cluster에서는 해당 모드를 지원하지 않아 적용하지 못하였고, 결국 예상치보다 많은 Pod를 구성하고 사용자의 유입을 보면서 대응하는 방식으로 처리한 부분이 아쉬웠습니다.

 

 

 

[Chapter 6] 데이터 수집

 

우리 서비스를 사용하는 유저에게 제공해야 하는 지표와 마케팅에 활용할 데이터 분석을 위한 로그 데이터 수집이 필요했습니다. 이를 위해 서버에서 발생하는 로그 데이터를 수집하고 적재, 가공, 분석할 수 있는 데이터 파이프라인이 필요했고, 우리는 전체 데이터 수집 파이프라인을 구축하였습니다.

 

1.  전체적은 흐름

데이터 수집 파이프라인 구성도는 아래와 같습니다.

 

데이터 파이프라인 구성도

 

Playback API로 수집되는 플레이어 관련 데이터는 vector(데이터 수집기)를 통해 Cloud Storage(GCS)로 로그 파일 형태로 수집됩니다. Dataflow는 주기적으로 GCS에 적재된 로그 파일을 가져와 GCP BigQuery에 데이터를 적재시키고, BigQuery에 적재된 데이터는 Looker 등을 이용해 대시보드로 활용하고 있습니다.

 

 


 

2. 데이터 수집

서버에서 발생하는 로그 데이터를 활용하여 다양한 지표를 제공하고 있습니다. 아래 항목은 우리가 제공하는 지표의 일부 항목에 대한 설명입니다.

 

1️⃣ 시청 수(View): 영상이 재생된 횟수를 나타내며, 영상의 인기도나 성공도를 판단하는 지표입니다.

2️⃣ 동접자 수(Concurrent viewer): 특정 시점에 동시에 영상을 시청하고 있는 사용자 수를 나타냅니다. 위에서 설명한 SSE 서버에서 커넥션 수를 활용하여 수집합니다.

3️⃣ 채팅 메시지 수(Chat message): 영상을 시청하면서 채팅 기능을 이용하여 전송된 메시지 수를 나타냅니다. 이는 사용자와의 상호작용을 나타내는 중요한 지표 중 하나입니다. 채팅 플랫폼에서 메시지 수를 N분 마다 호출해서 수집합니다.

4️⃣ 좋아요 수(Like): 사용자가 영상에 '좋아요'를 클릭한 횟수를 나타냅니다. 이는 영상의 인기도를 판단하는 데 중요한 지표 중 하나입니다.

5️⃣ 응원 수(Upvote): 라이브를 진행할 때 시청자가 응원하기 버튼을 클릭한 횟수를 나타냅니다. 이 데이터는 실시간으로 업데이트되며, 누적 응원 수를 파악하는 데 활용됩니다.

 

 

사용자에서 GCS까지

유저 액션을 통해 발생하는 로그는 Playback API를 통해 Raw 데이터가 GCS(Google Cloud Storage)에 저장됩니다. 일반적으로 컨테이너화된 애플리케이션의 표준 출력 로그는 컨테이너의 특정 경로에 쌓이고, logrotate 설정에 따라 보관되고 제거됩니다.

/var/log/*.log {
    rotate 5
    copytruncate
    missingok
    notifempty
    compress
    maxsize 100M
    daily
    dateext
    dateformat -%Y%m%d-%s
    create 0644 root root
}

gke의 컨테이너 로그 기본 설정으로 100M 단위로 rotate 되는 걸 알 수 있습니다.

 

이러한 로그나 메트릭(source)을 수집하여 가공(transform)하고 전달(sink) 하는 오픈소스 프로젝트에는 fluentbit, fluentd, vector 등이 있습니다. 성능 비교표는 아래와 같습니다.

 

성능 비교(출처 : https://github.com/vectordotdev/vector)

 

 

vector는 GCS를 공식으로 지원하고, 벤치마크 상 성능도 매우 우수하여 선택하게 되었습니다. (다른 서비스도 비공식 커뮤니티 플러그인은 존재합니다.) GKE에 DaemonSet으로 vector를 띄워두고 데이터를 수집해서 GCS로 보내고 있는데, 더 안정적인 구조를 위해 중간에 vector aggregator를 둬서 데이터 유실을 최소화하고 처리 속도를 높일 수 있습니다.

 

sinks:
  prod_to_gcs:
    type: gcp_cloud_storage
    inputs: [action_logs]
    bucket: prod-reverse-log
    key_prefix: "{{.message.action_type}}/%F/%H/{{kubernetes.pod_name}}_%Y%m%d%H"
    filename_time_format: ""
    encoding:
      codec: text

vector를 통해 저장된 GCS 로그 파일

 

로그 데이터를 수집하는 방법은 다양한데 우리가 GCS를 선택한 이유는 다음과 같습니다.

1️⃣ 확장성 : Kubernetes Pod에서 출력되는 로그는 매우 많을 수 있습니다. 이러한 대규모 로그 데이터를 수집하려면 클라우드 기반의 스토리지를 사용해야 합니다. GCS는 Google의 클라우드 기반 스토리지이며, 대규모 로그 데이터를 저장하고 검색하는 데 매우 적합합니다.

2️⃣ 저렴한 비용 : GCS는 저렴한 비용으로 대용량 데이터를 저장할 수 있습니다. 오랫동안 저장된 데이터에 접근할 수 있으며, 이 데이터를 BigQuery와 같은 데이터 분석 도구에서 분석할 수 있습니다.

3️⃣ Datadog Vector와의 호환성 : Datadog Vector는 GCS를 지원하므로 Vector를 사용하여 Kubernetes Pod에서 수집한 로그를 GCS로 전송할 수 있습니다.

4️⃣ 데이터 안정성 : GCS는 데이터를 안정적으로 보호하며, 데이터를 백업하고 복원하는 데 사용할 수 있는 다양한 기능을 제공합니다. 이는 로그 데이터와 같은 중요한 데이터를 안전하게 보호하는 데 매우 유용합니다.

 

 

Big Query - Looker Studio (Data Studio)

저희는 로그 데이터를 기반으로 데이터 분석을 하기 위해 BigQuery와 Looker Studio를 선택했습니다. 우리 서비스는 GCP에 올라가 있기 때문에 BigQuery와 연동이 용이하며, 대용량 데이터 처리와 SQL 기반 쿼리를 통한 데이터 분석, 시각화가 필요했습니다. 이에 BigQuery를 선택해, 효율적인 데이터 처리와 분석을 가능하게 했습니다. 또한 BigQuery를 시각화하기 위해서는 Looker Studio를 선택했습니다. 이는 무료로 제공되며 BigQuery와의 연동이 간편하며, 개발자도 쉽게 사용할 수 있어 선택했고, 이를 통해 안정적이고 효율적인 데이터 관리와 분석이 가능해졌습니다.

 

GCO Looker studio 시청 관련 보고서 일부

 

 

Dataflow

GCS에 저장된 로그 파일을 BigQuery의 데이터 전송 기능을 통해 바로 BigQuery로 전송할 수 있습니다. 그러나 이 기능은 데이터를 변환, 조합과 같은 가공을 하는 데에 한계가 있고, 지원하는 기능도 적습니다. 그래서 데이터 파이프라인 구축을 위해 여러 가지 툴을 비교, 분석해 보았습니다.

 

Data Pipeline Framework 비교

 

 

위와 내용을 참조하여 우리는 GCP의 다른 서비스와 쉽게 연동되고, 실시간 스트리밍을 지원하며 GCP에 구축하는데 가장 적합하다고 생각하는 Dataflow를 선택하였습니다.

 

 


 

3. 이렇게 활용했어요

영상 서비스에서 수집된 데이터를 마케팅 측면에서 활용하는 방법은 여러 가지가 있습니다.

1️⃣ 사용자의 시청 패턴 및 취향을 파악하여 맞춤형 추천 서비스를 제공하여 서비스 이용에 대한 만족도를 높일 수 있습니다.
2️⃣ 광고 타겟팅을 위한 데이터로 활용할 수 있습니다. 사용자의 시청 이력 데이터를 분석하여 광고 타겟을 정확하게 설정할 수 있으며, 이를 통해 불필요한 광고 비용을 줄이고 광고 효과를 극대화할 수 있습니다.
3️⃣ 시청 이력 데이터를 활용하여 새로운 콘텐츠를 개발하는 데 활용할 수 있습니다. 수집된 데이터를 분석하여 사용자가 선호하는 콘텐츠의 특징을 파악하고, 이를 기반으로 사용자의 선호도에 맞는 새로운 콘텐츠를 제공함으로써 사용자 이탈률을 낮출 수 있습니다.

 

 이렇게 영상 서비스에서 수집된 데이터를 마케팅 측면에서 다양하게 활용할 수 있으며, 이를 통해 사용자 만족도와 비즈니스 성과를 동시에 향상할 수 있습니다. 또, 우리는 마케팅 외에도 제작, 사업과 같은 영역에서도 활용하였는데 콘텐츠 위클리 리포트를 통해 진성 시청자수 및 동접자를 파악하여 콘텐츠 RT(Running Time) 설정 등 성과 측정에도 활용할 수 있었습니다.

 

 

4. 아쉬웠던 점 

1️⃣ GCS 적재 방식을 메시지 브로커으로 변경한다면?

 우리는 위에 설명한 이유로 GCS에 데이터를 적재하는 방식을 사용하였습니다. 하지만 서비스를 운영하다 보니 GCS에 데이터를 적재하는 방식에도 한계가 존재하였습니다. 스트리밍으로 데이터를 pull 하기에 적합하지 않았으며, 파일을 생성하는 시간으로 인해 전체 수집 시간이 지연이 발생하기도 했습니다. 이로 인해 Playback API에서 로그를 메시지 브로커로 push 한다면 더 효율적인 파이프라인이 되지 않을까 하여 내부 검토 중입니다.


2️⃣ Looker Studio의 한계

 Looker Studio는 분석, 디자인, 데이터 가공 기능이 한정적이고, 커스터마이징도 자유롭지 않습니다. Looker Studio로 데이터 분석 보고서를 유관부서에 제공하다 보니 담당자들이 원하는 모든 지표를 정확하게 구현하는 것이 어려웠습니다. 일부 데이터 가공이 불가한 부분은 BigQuery에서 연산한 후 그 결과를 표로 제공하는 방식을 사용하였습니다. 이 부분을 보완할 수 있는 대체 가능한 도구 또는 방법론을 찾는다면 서버에서 발생하는 로그를 가지고 더 다양한 분석 데이터를 제공할 수 있다고 생각됩니다.

 

3️⃣ 데이터 수집에 대한 아쉬움

 데이터 플랫폼 개발 경험이 없는 팀에서 데이터를 수집하려고 하다보니 많은 시행착오를 겪었습니다. 물론 스토리데이터팀에서 주요 데이터 분석도 진행히 주셨고 Looker Studio 보고서도 협업하여 작성했으나, 서버에서 발생한 로그 데이터를 사내 DW에 적재하기 위한 파이프라인의 일부와 유저에게 제공되는 지표는 저희 팀에서 담당해야 했는데 데이터 파이프라인, 분석 툴에 대한 전문성이 떨어지고, 러닝 커브도 존재하다 보니 단기간에 합리적이고 효율적인 파이프라인을 구성하는 데에 한계가 있었습니다. 이를 보완하기 위해 서비스 중간에 파이프라인을 변경하거나 수집 대상 로그가 추가되는 경우도 존재하였습니다. 다음 프로젝트에서는 콘텐츠 오픈 이전부터 완성된 파이프라인을 구성하여 진행할 수 있도록 더욱 숙련도를 높여 완성도 있는 파이프라인을 구축하는 게 목표입니다.

 

 

 

 

소녀 리버스를 마치며

 

발랄하고 위트 넘치는 30인 소녀들과 3개월간의 여정을 마친 후의 느낌은 다른 프로젝트 종료와는 다른 느낌으로 다가왔습니다. 30인의 소녀들 그리고 많이 사랑해 주신 시청자분들과 많은 정도 들었고, 함께 고생하며 제작하고 운영했던 구성원들과의 유대감도 형성되어 그런지 이렇게 마무리되며 종료되는 게 아쉽고 서운한 느낌이 들었던 것 같습니다.

 

초기 서비스를 기획/개발하면서 어려웠던 점은 얼마나 많은 사용자가 이 콘텐츠를 시청할지 예측하는 부분이었습니다. 하지만 국내(어찌 보면 세계?) 최초 여자 아이돌 버츄얼 서바이벌 형태의 콘텐츠이다 보니, 비교 대상의 플랫폼, 콘텐츠가 없었기 때문에 러프하게나마 예측하기도 매우 어려운 일이었습니다. 이 때문에 사전에 리소스를 가능한 한 최대한으로 준비해야 하고, 성능테스트도 여러 번 진행하면서 최적화를 했지만, 그런데도 문제가 발생할까봐 첫 회 방송할 때는 운영, 개발, 기획할 것 없이 모두 긴장의 연속이었던 것 같습니다. 그렇게 한 회차 한 회차 진행하다 보니 어느덧 마지막 방송을 무사히 마무리하게 되었네요. 

 

그동안 소녀 리버스 영상서비스의 성공적인 운영과 유지보수를 위해 다양한 기술과 프로세스를 도입했던 경험으로 인해 보다 더 효율적인 개발 방법과 안정적인 서비스 운영 방법을 발견할 수 있었고, 소통과 피드백 수렴을 통해 저희 팀은 더 나은 서비스 개발 방향성을 찾을 수 있었던 것 같습니다. 사용자들의 요구사항과 피드백을 수집하고 분석하여, 더욱 새로운 아이디어를 발굴하고 다음 서비스에 반영하고자 노력하고 있습니다. 다음서비스에서는 사용자들의 요구사항과 피드백을 적극적으로 수렴하여, 더욱 나은 서비스를 개발하고 제공할 수 있도록 계속해서 노력하고 있습니다.

 

다음 콘텐츠도 더욱더 재미있고 즐거운 콘텐츠로 만나 뵙길 바라며!

 

 

그동안 즐거웠어~🥰😇

 

 

 

📷 photo by. Selian