오토피디아 데이터 웨어하우스 구축하기

스타트업 데이터 배관공 생존기 1편 (DW.. 그거 어떻게 만드는건데)

Do not index
Do not index
안녕하세요? 오토피디아 리서치팀에서 데이터 엔지니어링과 머신러닝 프로젝트에 참여하고 있는 데이터 배관공 Kevin입니다.

들어가며

여러 회사들이 비즈니스 의사결정을 하는데 있어 데이터가 가지는 중요성과 파급력을 인지하고 사내 데이터 플랫폼을 구축하는데 많은 기술적, 인적 리소스를 투입하고 있습니다.
때는 2020년 11월, 닥터차 앱이 스토어에 올라간지 두 달 밖에 되지 않은 오토피디아에서도 앱 유입 추적 데이터와 사용자 행동 데이터를 수집하기 시작하면서 ‘이 데이터들을 어디에 어떻게 모아야하지?’, ‘지금 유저들이 어떤 채널을 통해 제일 많이 들어오지?’ 와 같은 고민과 질문들이 피어나기 시작했습니다.
그리고 예상보다 빠르게 다양한 광고 매체에서 캠페인이 시작됨에 따라 다루어야 할 데이터들도 많아졌고 의사결정을 위해 필요한 데이터 분석 요청도 많아졌습니다. 당시에 머신러닝 프로젝트 경험만 있던 리서치팀은 데이터 엔지니어링에 대한 지식과 SQL 쿼리 작성 경험도 없었던터라 프로덕션 MySQL DB의 덤프 파일을 로컬에 다운 받은 뒤, 주피터 노트북에서 다른 데이터와 함께 파이썬으로 이리저리 코드를 짜서 분석을 했었습니다. (이때를 회상하니 정신이 한껏 아득해지는군요)
분명 더 좋은 방법이 있을텐데.. 라는 고민이 들던 차에 커뮤니티의 몇몇 글과 발표 자료를 통해 데이터 엔지니어링에 대한 세계를 엿보게 되었습니다. 배워야 할 것과 해야 되는 일이 참 많아 보였지만, 자꾸 늘어나는 데이터 분석 요청과 미래의 닥터차 서비스에서 비즈니스 임팩트를 줄 수 있는 머신러닝 모델들을 효과적으로 운영하기 위해서는 사업의 극초기 단계부터 서비스 내/외부에서 생성되는 데이터를 올바르게 수집하고 빠르게 분석할 수 있는 데이터 웨어하우스를 구축하지 않으면 안된다고 판단했습니다.
스타트업 데이터 배관공 생존기 1편에서는 앱을 출시한지 두 달이 넘지 않은 극초기 스타트업에서 어떤 방식으로 데이터 웨어하우스를 구축했는지에 대한 경험을 다룹니다.
그때부터 였어요.. 제가 데이터 엔지니어가 된 게
 
 

1. 기초 조사와 배운 것

데이터 플랫폼의 경우 한번 기틀을 잡은 후에는 전사 구성원들의 매일 매일의 업무에 영향을 주게 되고 추후 서비스와 조직이 커졌을 때 리팩토링에 들어가는 리소스도 무지막지 할 것이라는 생각이 머리를 ‘휙’하고 스쳐 지나갔습니다. 따라서 처음 만들 때 충분한 시간과 자료 조사를 통해 우리 조직에 필요한 데이터 웨어하우스가 갖추어야 할 요구사항을 정립하고 최대한 많은 옵션을 검토하고 가능하다면 점진적으로 만들어나가기로 했습니다.
이 과정에서 업계의 선배님들, 선두에 있는 여러 기업들이 공유해주신 많은 주옥 같은 자료들을 탐닉할 수 있었고 아래 자료들은 이번 프로젝트의 의사결정을 하는데 특히 많은 도움을 받았습니다.
  • 마이리얼트립의 ‘데이터가 흐르는 조직 만들기’ 1편, 2편
  • Ziyad Mohiyudheen님의 ‘Organizing data in BigQuery’ 미디엄 글
  • 이재광님의 ‘대용량 로그분석, BigQuery로 간단히 사용하기’ Slideshare 자료
  • Databricks의 ‘Productionizing Machine Learning with Delta Lake’ 블로그 글
  • 이정운님의 ‘GCP에서 조직(Organization) 활용하기 시리즈’ 미디엄 글
 
이러한 자료들을 통해 아래와 같은 점들을 배우고 프로젝트를 시작할 수 있었습니다.
  • 서비스 DB(OLTP)에 직접 쿼리를 때려 박으면 안되는구나! + 분석용 DB(OLAP)가 따로 있구나!
  • 데이터는 최대한 한 곳에 모아놔야 조인해서 쿼리 할 때 편하구나!
  • ETL 보다는 ELT가 대세구나! (우리에게도 맞겠구나)
  • 원시 데이터로부터 매번 쿼리하기 보다는 데이터의 퀄리티 혹은 집계된 수준에 따라 단계를 나눠서 데이터 마트를 구축하는 것이 편리하겠구나!
  • 데이터를 모아놓고 나면 쉽게 시각화할 수 있는 BI 툴이라는 것이 존재하는구나!
  • 데이터가 많아지면 인프라 관리도 쉽지 않아지는구나!
  • 나중에는 데이터 거버넌스 관점에서 다양한 고도화가 필요하겠구나!
  • Delta Lake 같은게 좋아보이기는 하지만 지금 당장 필요한지는 모르겠다!

2. 프로젝트 요구사항 정립하기

기초 조사를 통해 배운 점을 바탕으로 프로젝트의 목표와 목표가 아닌 것을 정리해보았습니다.

목표인 것

  1. 데이터 웨어하우스에 다양한 전사 데이터(대부분 정형화된 데이터)를 모두 모으기. 대표적으로는 광고 성과/비용 데이터, 유저 행동 데이터, 서비스 RDS, 외부 파트너 데이터 같은 유형의 소스들이 존재. 이때 데이터 웨어하우스 운영 시에 인프라를 신경 쓰고 싶지 않음. 그러나 대규모 데이터에 대해서도 쿼리 속도는 빨랐으면 좋겠음
  1. 시간이 흐르며 지속적으로 새로운 데이터 소스가 추가되고 멀티 프로덕트로 비즈니스가 확장될 수 있음을 고려하여 데이터 웨어하우스 내에 데이터 정리 규칙과 네이밍 컨벤션을 함께 정립하기
  1. 사내 구성원들이 쉽게 볼 수 있는(=접근성이 높은) BI 대쉬보드 구축하기

목표가 아닌 것

  1. 실시간 대쉬보드 만들기 : 실시간 대쉬보드 구축을 위해서는 스트리밍 기반의 데이터 수급 파이프라인 구축이 선행되어야 하는데 애초에 데이터 소스가 스트리밍을 지원하지 않는 경우도 있고 지원하더라도 투입되어야 하는 리소스 대비 추가적으로 발생되는 비즈니스 효용은 거의 0에 가까움. 1시간 단위의 업데이트 주기도 충분하다고 판단!
  1. JSON과 같은 반정형(Semi-structured) 혹은 이미지, 비디오와 같은 비정형(Unstructured)도 함께 관리하기 : 나중에 서비스에 머신러닝을 적극적으로 도입하려면 데이터 레이크로의 확장이 필요하겠지만 당장은 S3에 올려두는 것만으로도 충분하고 데이터 웨어하우스에서 들어갈 데이터의 대부분은 다 정형(Structured) 데이터이니 다음에 생각하자
  1. 데이터 거버넌스(Data governance), 데이터 디스커버리(Data Discovery), 데이터 리니지(Data Lineage) : 데이터 규모가 커지고 팀의 규모가 커지면 자연스레 필요한 요소들이지만 BigQuery 권한과 데이터 정리 규칙만 잘 잡아도 기본적인 요건은 충족될 것으로 예상

3. 바쁘다 바뻐, 결론부터 알려줘요!

오토피디아 데이터 웨어하우스 아키텍쳐
오토피디아 데이터 웨어하우스 아키텍쳐
앞서 정의한 프로젝트 요구사항을 달성하기 위해 최종적으로 구축한 전체 아키텍쳐는 위 그림과 같습니다. 프로덕트(=서비스) 별로 GCP 프로젝트(Product-level Project)가 할당되고 다양한 원시 데이터로부터 SaaS 툴, 스트리밍 삽입 API, 혹은 Airflow Task를 통해 모두 BigQuery US 멀티 리전 내 데이터셋, 테이블에 적재됩니다.
이후에는 dbt를 사용하여 분석용 GCP 프로젝트(Analytics Project)의 data_mart 데이터셋에 집계된 테이블들이 1시간 단위로 업데이트 됩니다.
BI 툴로는 Data Studio를 선택하여 구글 워크스페이스 계정이 있는 오토피디아 구성원이라면 누구나 자유롭게 상시 업데이트 되는 대쉬보드 탐색이 가능합니다.
이어질 내용에서는 어떤 과정을 거쳐 위와 같은 구조를 채택하게 되었는지 각 요소 별로 자세히 알아보고, 1년 6개월 동안 운영하며 느낀 점에 대해 기록해 보았습니다.

4. 데이터 웨어하우스 솔루션 선택하기

데이터 웨어하우스는 일반적으로 데이터 변경에 대한 트랙잭션을 처리하기 보다는 대량의 데이터에 분석을 수행하는 목적으로 활용되므로 OLTP가 아닌 OLAP 기반의 시스템을 활용합니다. 시중에는 각기 다른 특장점을 지닌 OLAP 서비스들이 있고 OLAP 서비스의 선택에 따라 케미가 잘 맞는 ETL 파이프라인과 BI 툴의 스택이 달라질 정도로 데이터 웨어하우스의 가장 중심이 되는 컴포넌트입니다. 저희는 아래와 같이 총 4개의 OLAP 서비스들을 비교해보았습니다.

BigQuery vs Redshift vs Snowflake vs Databricks

2020년 11월 기준으로 BigQuery, Redshift, Snowflake, Databricks을 후보 선상에 놓고 고려했습니다. 이때 각 솔루션 별로 프로젝트의 요구 목표를 달성하는데 적합하지 않은 점이 있으면 소거하는 형태로 결정할 수 있었습니다.
Redshift
닥터차 앱의 백엔드와 DB가 모두 AWS 상에 배포되어 있는 만큼 AWS 상에 있는 여러 데이터 소스들과 쉽게 연동되는 것이 가장 큰 장점으로 보였습니다. 그러나 프로비저닝 할 수 있는 최소 인스턴스 옵션이 월 70만원 이상(서버비도 그 정도가 안 나오는데..)의 요금이 발생하는 것으로 인지하여 후보 선상에서 빠르게 제외하였습니다. 어찌되었든 인스턴스를 관리해야 되는 것도 단점이었습니다. (2022년 시점에서 다시 살펴 보니 Redshift Serverless가 Preview 출시되었군요)
자매품으로 AWS Athena는 S3 상의 파일에 바로 쿼리할 수 유용한 서비스인데 닥터차 유저분들이 올려주시는 이미지 파일 외에는 S3에 올라갈 데이터가 크게 없어 데이터 웨어하우스 구축 관점에서는 활용도가 충분하지 않았습니다. DW 구축에서는 배제되었지만 이후에 머신러닝 프로젝트의 라벨링 과정에서 생성되는 JSON 형태의 어노테이션 데이터들을 다룰 때 요긴하게 사용하고 있습니다.
Snowflake
AWS S3나 GCP의 GCS 저장소에 적재되어 있는 데이터를 바로 쿼리할 수 있는 것은 좋았으나 JSON 로그 파일과 같이 Semi-structured 형태의 데이터의 적재와 쿼리에 특화되어 있다는 느낌이 강하게 들었고 구축하고자 하는 DW에서 주로 다루는 데이터가 정형화된 데이터였기에 큰 장점을 느끼지 못했습니다.
Databricks
오픈소스인 Delta Lake, Spark 지원, 머신러닝 프로젝트 관리를 위한 MLflow를 전면에 내세우면서 데이터 레이크와 데이터 웨어하우스가 합쳐진 데이터 레이크하우스의 개념으로 접근하고 있는 점이 상당히 흥미로웠습니다.
그러나 리서치팀 멤버들이 모두 Spark를 다뤄본 경험이 없었고 인스턴스를 여전히 관리해야 한다는 점이 마이너스로 요소로 작용해 아쉽지만 다음을 기약하게 되었습니다. 그리고 MLflow도 오픈소스 프로젝트이기 때문에 추후 MLOps를 구축하더라도 MLflow만 자체적으로 운영이 가능하므로 꼭 Databricks 생태계에 속해 있을 필요가 없었습니다.
BigQuery (Winner!)
사용자들의 행동 데이터가 모이는 GA4의 데이터를 내보내기(Export) 할 수 있는 옵션이 BigQuery 밖에 없었기 때문에 일단 반 강제적으로 BigQuery를 사용하기 시작할 수 밖에 없었습니다.
다행히도 BigQuery는 완전한 Serverless 서비스로 인스턴스 프로비저닝 등이 필요 없으며 쿼리 할 때 읽은 데이터 양이 대부분의 과금을 차지합니다. 그리고 쿼리 실행과 함께 처리해야 되는 데이터의 양에 따라 알아서 필요한 연산 자원을 Scale-out 해주기 때문에 천만 행이 넘어가는 광고 성과 데이터에 쿼리를 날려 보았을 때도 수 초 이내로 뚝딱뚝딱 결과가 나오는 편입니다. 이때 파티션, 클러스터링을 적절히 활용하면 쿼리 비용을 크게 아낄 수 있습니다.
또한 정형화된 데이터 외에도 Record, Repeated 라는 BigQuery만의 열 타입을 스키마에 지정하면 Nested한 형태의 데이터도 적재 및 쿼리가 가능합니다. (2022년 현재, 기능이 다소 제한적이지만 JSON 열 타입을 Preview로 지원하기 시작했습니다.)
마지막으로 Streaming Insert API를 통해 스트리밍 삽입도 지원하기 때문에 실시간으로 생성되는 데이터 소스도 삽입과 함께 거의 즉시 쿼리 가능한 상태가 됩니다.
사용하면서 불편했던 점으로는 테이블의 스키마를 변경(열 추가, 열 데이터 타입 변경)하는 것이 다소 번거로우며 데이터셋은 한번 생성하면 이름과 리전을 바꿀 수 없었습니다. 이 때문에 팀 내에서 데이터 정리 규칙(프로젝트, 리전, 네이밍, 스키마)을 잘 계획하여 만들 때 한 방에 만들고 수정을 최소화하는 것이 유지보수를 줄이는데 중요한 요소라고 강하게 느꼈고 “이 많은 테이블들을 BigQuery에 어떻게 잘 정리하지?”에 대한 깊은 고민으로 이어졌습니다.

BigQuery 데이터 정리하기

BigQuery에 데이터를 저장하기로 마음 먹었다면 모든 테이블은 기본적으로 프로젝트-데이터셋-테이블에 이르는 계층을 따라 GCP 내에 위치하게 됩니다. “그냥 한 프로젝트에 다 밀어 넣어도 되는거 아니야?” 라고 생각했던 적도 있었지만 Best Practice를 조사하다보니 GCP 공식 문서에서 Resource hierarchyOrganizing BigQuery resources 자료를 읽고 큰 가닥을 잡을 수 있었습니다.
Project 정리하기
두번째 자료를 읽고 데이터 웨어하우스를 구축하는데 크게 2가지 패턴이 있다는 것을 알 수 있었는데요.
중앙화된 데이터 레이크, 부서별 데이터 마트 (출처: Google Cloud)
중앙화된 데이터 레이크, 부서별 데이터 마트 (출처: Google Cloud)
부서별 데이터 레이크, 중앙화된 데이터 웨어하우스 (출처: Google Cloud)
부서별 데이터 레이크, 중앙화된 데이터 웨어하우스 (출처: Google Cloud)
  1. 중앙화된 데이터 레이크, 부서별 데이터 마트(Central data lake, department data marts) : 데이터 엔지니어링 팀이 하나의 GCP 프로젝트에 모든 데이터를 적재한 뒤, 각 부서 팀 별 프로젝트 내에서 필요한 데이터만 참조해 분석하는 구조입니다.
  1. 부서별 데이터 레이크, 중앙화된 데이터 웨어하우스(Department data lakes, central data warehouse) : 데이터 엔지니어링 팀이 하나의 GCP 프로젝트에 모든 데이터를 적재한 뒤, 각 부서 팀 별 프로젝트 내에서 필요한 데이터만 참조해 분석하는 구조입니다.
실은 두 패턴은 상호 배타적이진 않고, 필요하다면 두 패턴을 조합해서 원본 데이터들도 개별 프로젝트에 적재하고, 분석 팀 별로 개별 프로젝트에 데이터 웨어하우스를 구축하는 것도 가능합니다. 반대로 단일 데이터 적재 프로젝트, 단일 분석 프로젝트과 같은 심플한 형태로도 구축이 가능합니다.
구축 시기에 닥터차 앱용과 랜딩 웹사이트용 GA4 프로젝트가 각각 있었는데 당시에는 GA4 → BigQuery 내보내기(Export) 기능을 설정할 때 GA4가 속해 있는 프로젝트로만 내보내기 설정이 가능해 반 강제적으로 프로덕트 별로 별도의 프로젝트에 적재하게 되었습니다. (이를 프로덕트 레벨 프로젝트로 칭함). 분석 프로젝트의 경우에는 당시 소수의 리서치팀 내에서 데이터 엔지니어링부터 데이터 분석까지 모두 담당했기 때문에 중앙화된 단일 프로젝트로 구성하였습니다.
위의 정리 방식에 따라 리서치팀 내에서 관리하는 일부 프로젝트-데이터셋-테이블들을 나열하면 아래와 같습니다.
<Product-level Projects>
    - Drcha App Project
        - analytics_2342342 (GA4 export dataset)
        - raw_mysql_rds
            - User
            - Vehicle
            - Payment
        - raw_facebook_ads
            - campaign
            - adgroup
            - creative
            - cost_report
        - raw_search_rank
            - playstore
            - app_store
    - Drcha Web Project
        - analytics_2342342 (GA4 export dataset)
            - events_*
<Analytics Projects>
    - data-dev Project
        - data_mart
	    - stg_*
	    - mid_*
	    - tbl_*
    - data-prod Project
        - data_mart
            - stg_*
            - mid_*
            - tbl_*
위 예시에서 알 수 있듯이 프로덕트 레벨 프로젝트와 분석용 프로젝트에 따라 데이터셋과 테이블 구성 방식에 차이가 있습니다. 두 프로젝트 유형별 테이블 정리 방식은 이어지는 두 섹션에서 후술하겠습니다.

4. EL은 어떻게?

BigQuery에 어떻게 데이터를 정리할지 결정한 뒤에는 각 데이터 소스를 BigQuery로 적재하는 파이프라인을 만들기 시작했습니다. GA4는 자체적으로 BigQuery 내보내기를 지원하고 (자주 쓰지는 않지만) 구글 스프레드시트도 별도의 적재 과정 없이 바로 쿼리하는 것이 가능했습니다.
이 외의 데이터 소스 별 연동은 아래와 같이 진행했습니다.
  • AWS MySQL DB : RDS에 대한 ETL 파이프라인은 단순히 데이터 동기화 뿐만 아니라 프로덕트의 업데이트에 따라 지속적으로 변화될 수 있는 스키마에도 대응해야 된다는 번거로움이 있습니다. 따라서 3가지 정도의 ETL SaaS 서비스를 검토하여 높은 안정성과 스무스한 연동 경험을 준 Fivetran을 최종적으로 선택하였습니다. AWS Public Subnet 내의 Replication 인스턴스에 접속하여 15분 단위로 BigQuery로 선택한 테이블들을 모두 동기화 시켜줍니다.
  • SaaS를 사용하지 않고 직접 구축할 때 고려할 수 있는 다른 옵션으로는 정기적으로 DB 스냅샷을 GCS로 저장한 뒤 BigQuery로 가져오기 작업을 실행하기, 실시간 파이프라인 구축이 목표라면 Debezium과 같은 오픈소스 프로젝트를 활용하여 CDC(Change Data Capture) 파이프라인을 만들기 등이 있겠습니다.
  • 앱스토어 / 플레이스토어 : 스토어 방문자 수와 같은 통계 정보를 받아올 수 있습니다. Fivetran이 두 스토어로부터의 데이터 추출을 모두 지원해서 쉽게 해결되었습니다. 이때 불필요한 테이블을 제외하지 않으면 요금 폭탄이 발생할 수 있으니 주의가 필요합니다.
  • 스토어 검색 순위 : 여러 키워드들에 대해 날마다 스토어에서의 닥터차 앱의 검색 노출 순위를 기록하기 위해 Selenium으로 제작한 크롤러를 Airflow Task로 걸어두어 해결했습니다.
  • 광고 매체 집행 비용 : 마케팅팀에서는 광고 캠페인을 운영할 때 각 광고 매체/소재 별로 집행된 비용 대비 성과를 가장 중요한 지표 중 하나로 여깁니다. 만약 사내에 자동화된 파이프라인이 없다면 마케터가 매일 아침마다 모든 광고 매체를 돌며 엑셀 다운로드 버튼을 누르고 성과 데이터와 함께 정리해 일간 성과보고서를 만들며 하루를 시작해야 되는 슬픈 일이 발생할 수 있습니다. 마케터 분들이 슬퍼하시지 않도록 꼭 자동화된 대쉬보드를 만들어 드립시다.
  • 각 광고 매체에서 제공하는 API를 활용하면 날짜/캠페인/광고그룹/소재를 Dimension 으로 하는 성과 데이터를 추출할 수 있습니다. 구글, 페이스북과 같은 1티어 광고 매체는 Fivetran을 사용하면 쉽게 BigQuery에 일간 리포트 테이블을 생성할 수 있습니다.
  • Fivetran이 지원하지 않는 국내외 광고 매체들은 파이썬과 Airflow를 활용하여 직접 BigQuery에 적재했습니다.
  • 유저 행동 데이터 : MMP 툴인 Adjust에서 실시간으로 수신되는 유저 행동 데이터는 Lambda에서 간단한 전처리를 수행한 뒤에 Streaming Insert API를 활용하여 스트리밍 방식으로 적재했습니다.
EL 파이프라인을 만들 때 중점을 두었던 부분은 최대한 SaaS 서비스를 활용하여 파이프라인 유지보수를 최소화하고 데이터 엔지니어들이 더 의미 있는 비즈니스 임팩트를 창출하는 프로젝트에 기여할 수 있는 환경을 조성하는 것이었습니다. (조금은 극단적이지만) 만약 파이프라인 별로 평균적으로 한 달에 1회씩 유지보수를 위해 하루를 투입한다면, 20개의 파이프라인을 운영하기 위해서 최소 한 명은 일 년 내내 유지보수만 담당하는 상황이 펼쳐질 수도 있겠습니다.

5. T는 어떻게?

처음 EL파이프라인을 통해 데이터를 적재하고 난 직후에는 원시 데이터를 직접적으로 참조하는 쿼리를 뷰(View) 테이블로 BigQuery에 등록한 뒤, BI 툴에 바로 연결하여 사용했습니다. 그러나 데이터 소스가 다양해지고, 더 복잡한 쿼리를 작성하기 시작하면서 아래와 같은 불편한 점이 생겼습니다.
(1) 반복적이고 비생산적인 쿼리
  • 보고싶은 영역은 유저(유입, 주요 마일스톤 달성 여부), 상담(당시 앱내 주요 서비스) 에 대한 것으로 매우 명확했는데, 조금 다른 데이터를 해당 영역에서 추출하기 위해서 매번 반복적이고 복잡한 쿼리를 작성하였음.
  • 간단한 쿼리라도 조회하는 table 들의 용량이 크거나 다양할 경우 불필요한 쿼리비용이 발생하였음.
(2) 데이터 소스 마다 원천 테이블의 컬럼 네이밍 규칙이 다름
  • 당시 adjust 등에서는 snake_case를 사용하였으나, Service DB는 camel case를 사용하였으며, fivetran을 통해 MySQL DB를 bigquery 로 export 하면 자동으로 언더바 없는 snake_case로 변한되었음. 이로인해 유저의 앱 내 이벤트와 Service DB상의 데이터를 조인할 때 서로 다른 네이밍 규칙으로 인해 쿼리문이 더러워짐.
(3) 차트마다 데이터 필터링을 항상 염두해 두어야 함
  • 지표를 오염시키는 내부(Internal) 유저의 데이터, 수집 과정의 오류로 발생한 원시 데이터 내 불필요한 항목과 같이 필터링 해야하는 항목들을 항상 잊지 않고 쿼리문에 추가해야 함.
  • 특히 앱 서비스의 사용자 행동 이벤트 데이터의 경우 데이터를 다루는 과정에서 누락이나 실수가 종종 발생했는데, 이 때 마다 백데이터 채우기와 보정을 했어야 하는 불편함이 있었음.
(4) 테이블 조인 방식이 혼재되어 있음
  • 후술할 BI 툴에 대쉬보드를 처음 구축할 때, 테이블 조인이 필요한 경우 몇몇 차트는 BigQuery 콘솔 상에서 조인 쿼리문을 뷰로 등록한 뒤 사용하였고, 나머지는 Data Studio의 GUI 환경에서 제공하는 조인 기능을 활용하여 차트 단에서 바로 조인을 수행하는 등 규칙이 없었음.
  • 두가지 방식 모두 코드로 관리되지 않아 각 차트들이 어떤 컬럼들을 참조하고 있는지 연결 관계를 추적하기가 금새 어려워짐.
(5) 너무 긴 쿼리 시간
  • 1회성 데이터 추출에서는 긴 쿼리 시간이 크게 문제 되지 않았으나, BI 툴에서는 다양한 필터 조건을 걸며 여러번에 걸쳐 시각화하는 경우가 많음. 이때 차트와 연결된 테이블이 모두 뷰로 구성되어 참조 중인 모든 원시 데이터에 대한 쿼리가 발생해 새로운 필터를 적용할 때 마다 20초씩 이상씩 기다리는 문제가 발생함.
  • 따라서 내부 구성원들의 데이터 접근성이 매우 떨어졌음.
위의 불편한 점들은 데이터 적재(EL) 이후 시각화 및 데이터 추출로 이어지는 변환(T) 과정에서 SQL 작성 체계가 없었고 충분히 효율적이지 못해서 발생했던 문제였습니다. 여러 시행착오를 거치며 최종적으로는 dbt(Data Build Tool)를 기반으로 분석용 프로젝트 내의 모든 데이터셋과 테이블들을 관리하게 되었습니다.
dbt는 앞서 비교했던 Snowflake, Redshift, Databricks, BigQuery를 모두 지원하며 하나의 레포지토리 내에서 프로젝트의 모든 데이터 모델(dbt에서의 테이블 개념)을 SQL 파일과 설정 파일만으로 관리할 수 있어 DaC(Data as Code)가 가능하다는 장점이 있습니다. 특히 프로젝트 컴파일 단계에서 모델 간의 참조 관계를 자동으로 인식하기 때문에 여러 번의 참조 관계가 존재할 때 항상 앞단의 테이블부터 순차적으로 쿼리를 실행하고 순환 참조를 사전에 감지해줍니다.
분석용 프로젝트 data-proddata-dev 에는 data_mart 라는 단일 데이터셋을 생성한 뒤에 아래와 같은 규칙으로 모델을 생성했습니다.
(1) 모든 조인은 dbt 내에서
  • 2021년 당시 Data Studio가 제공하던 조인 기능은 제약 사항과 버그가 많았고, 참조하고 있는 테이블의 스키마가 변경되는 경우 Data Studio의 차트와 연결이 끊어지는데 이를 복구하는 것도 만만치 않았음. 이를 해결하기 위해 BI 툴에서는 조인하지 않고 분석용 프로젝트 내에서 이미 조인이 완료된 테이블만을 불러와서 시각화하기로 함.
(2) 집계 수준에 따라 stg/mid/tbl 모델 구분
  • stg_* : 프로덕트 레벨 프로젝트 내에 있는 원시 테이블을 간단히 정제(Cleansing)하는 목적으로 생성되는 뷰 모델. 데이터 소스 별로 상이한 열 이름을 정리하고, 필요한 경우 flattening을 적용함. stg 모델은 1 원시 테이블 - 1 stg 테이블을 기본 원칙으로 고수하며 조인 연산 등을 포함하지 않음
예시1) counsel 테이블의
id
counsel_id
예시2) 카카오 광고 성과 테이블에서
dimensions.accountId
ad_account_id
  • tbl_* : 데이터 분석 시에 자주 다뤄지는 주요 엔티티를 중심으로 할 수 있는 가장 많은 조인을 붙여놓은 구체화된(materialized) 모델. 예를 들자면 닥터차 앱에서는 유저, 상담, 게시글, 차량 엔티티를 중심으로 나머지 엔티티를 모두 엮은 데이터 마트들이 가장 인기가 좋습니다. 데이터 마트를 구축함으로써 각 엔티티로부터 시작하는 데이터 추출/분석 요청에 대해 중복되는 조인 쿼리를 제거할 수 있고 운이 좋을 땐 단순한 WHERE문과 GROUP BY문 만으로도 원하는 결과를 얻을 수 있습니다.
예시)
tbl_user_properties
  • mid_* : dbt 도입 초기에는 tbl_* 만으로도 충분히 빠르게 사내 분석 요청을 수행할 수 있었으나, 여러 팀에서 더 세분화된 데이터 요구사항들이 생기면서 주요 엔티티들을 중심으로 생성된 tbl 모델로는 충분하지 않게 되었음. 예를 들자면 여러 요구사항에 맞추어 tbl 모델을 바로바로 수정해버리면 tbl 모델이 추구하는 높은 재사용성이라는 목적을 잃거나 애매한 수준에서 집계된 모델들이 무분별하게 생성될 수 있음. 따라서 간단한 조인이 필요한데 tbl로 제작 되어있지 않은 경우에는 뷰 형태의 mid_ 접두사를 갖는 모델로 제작하고, Data Studio에 연결해서 사용함. 이때 일정 수준의 유사한 mid 뷰들이 쌓이며 요구사항들이 중첩될 때는 mid 테이블들을 tbl에 통합시켜 midtbl 모델들이 추구하는 정체성을 지켜주었습니다.

6. 전사 BI 툴 선택하기

이제 집계된 데이터셋까지 준비되어, 다양한 사내 구성원들이 지표들을 모니터링 할 수 있게끔 대쉬보드를 제공하는 BI(Business Intelligence) 툴을 선택하는 순간이 왔습니다. 처음에는 누구에게 어떠한 대쉬보드가 필요한지, 대쉬보드는 어떤 기능까지 지원해야 되는지에 대한 경험도 전무했고, 각 BI 툴들도 구체적으로 어디까지 지원되는지 파악이 어려워 여러 툴들을 직접 써보며 아래와 같은 평가 기준에 의해 최종적으로 Data Studio를 선택하였습니다.
  • 비용 : 유료 BI 툴들의 경우 주로 에디터/뷰어 유저당 월 과금을 하는 경우가 많습니다. ‘사내 구성원들이 쉽게 볼 수 있는(=접근성이 높은) BI 대쉬보드 구축’ 이라는 목표 달성을 위해서는 사내 구성원 수 만큼의 라이센스 비용이 지출되기 때문에 최대한 무료 혹은 오픈소스 툴로 범위를 좁혔습니다.⇒ Tableau, QuickSight, Power BI와 같은 유료 툴 탈락!
  • 언어 : 오토피디아에는 개발자, 마케터, 디자이너, 메카닉, 물류 등 다양한 배경의 직군이 함께 일하고 있으며 영어에 진입 장벽을 느끼시는 분들도 계신데요. 전사 구성원 분들의 데이터 접근성을 높이기 위해 한국어 지원 여부도 중요한 고려 사항이었습니다. 테스트 결과 몇몇 오픈소스 프로젝트들은 차트 요소에 한국어 입력을 아직 지원하지 않는 경우가 있었습니다.⇒ Superset 탈락!
  • 속도 : 한국인의 특성 상 로딩 시간이 조금만 길어져도 점점 대쉬보드를 멀리하게 되고, 결국 아무도 안 보는 애물단지가 되기 십상입니다. 이때 BI 툴의 호스팅 위치와 쿼리 결과로 나오는 데이터의 크기에 따라서 BigQuery로부터 BI 툴로 데이터가 전송되는 시간에 의해 로딩 시간이 크게 달라질 수 있습니다. 특히 집계를 많이 하지 않는 쿼리 결과에 대해 차트를 그릴 때 데이터 전송으로 인해 몇 분에 걸쳐 로딩을 기다리는 경험을 했습니다.⇒ Redash 탈락!
  • 보안 : 전사 대쉬보드는 보안이 유지되어야 하는 회사 정보 중 하나로 내부 구성원들에 한하여 열람이 가능해야 하고 경우에 따라서는 특정 구성원들 혹은 퍼블릭 액세스가 가능하도록 권한 설정이 가능해야 합니다.
<최종 승자> : Data Studio
Data Studio는 한국어를 지원하며 완전 무료(BigQuery 쿼리 비용은 별도)라는 장점이 있습니다. 사내 구성원 분들의 크롬 브라우저는 구글 워크스페이스로 로그인 되어 있기 때문에 내부 인원이라면 별도의 인증 절차 없이 바로 대쉬보드 열람이 가능하며 그룹 별로 세부적인 권한 설정도 가능했습니다.
더불어서 Data Studio 차트는 BigQuery의 데이터셋 리전 내에서 처리된 결과를 바로 표시해주기 때문에 집계 수준에 관계 없이 쿼리 시간 외에 추가적으로 발생하는 지연 시간이 거의 없다고 느껴졌습니다.
만약 더 빠른 대쉬보드를 원한다면 BigQuery BI Engine 서비스를 활용해 캐싱해놓을 데이터 용량을 구매하여 인 메모리 데이터 쿼리도 가능합니다.
오토피디아에서는 사내 노션 메인 페이지에 주요 지표에 대한 차트를 대자보 처럼 임베딩하여서 Data Studio에 접속하지 않더라도 누구나 지나가는 길에 한번씩 보고 갈 수 있도록 세팅하였습니다.
(한가지 팁으로, 열심히 만든 대쉬보드가 실제로 얼마나 활용되는지 궁금하다면 대쉬보드 파일 별로 GA4 추적 세팅을 지원합니다. 하루에 몇 명이나 대쉬보드를 보고 가는지 모니터링이 가능합니다)

7. 1년 6개월 간의 운영 회고

2020년 11월부터 점진적으로 구축을 시작하여 운영한지 어느덧 1년 6개월이 흘렀습니다. 이 과정에서 글에 다 담지 못한 많은 우여곡절이 있었지만 안정화가 된 후에는 소기의 목표들이 달성되어 팀 내에서 상당히 만족하며 사용하고 있습니다. 이어지는 글에서는 잘했다고 생각한 점과 아직 개선이 필요한 점들을 회고해 보았습니다.
(1) 데이터 웨어하우스에 다양한 전사 데이터를 모두 모으기.
  • 데이터 소스의 특성에 따라 ETL SaaS 툴, Airflow Task, Streaming Insert API 등등을 활용하여 모두 BigQuery에 모을 수 있었습니다.
(2) 시간이 흐르며 지속적으로 새로운 데이터 소스가 추가되고 멀티 프로덕트로 비즈니스가 확장될 수 있음을 고려하여 데이터 웨어하우스 내에 데이터 정리 규칙과 네이밍 컨벤션을 함께 정립하기
  • 프로덕트 레벨 프로젝트와 분석용 프로젝트를 분리하고 데이터셋과 테이블의 네이밍 컨벤션을 정립해 놓은 덕분에 지난 5월, 두번째 서비스인 닥터트레드 신규 런칭 시에도 필요한 데이터 파이프라인을 빠르게 구축할 수 있었습니다.
  • 모든 데이터셋을 동일한 리전에 생성함으로써 리전 간 별도의 데이터 복제 과정 없이 모든 테이블을 함께 조인하여 쿼리할 수 있었습니다.
  • dbt와 Airflow를 활용하여 dbt 모델 SQL을 작성하고 local → dev → prod 브랜치에 순서대로 병합하면 자동으로 분석용 프로젝트 내 BigQuery에 반영되어 Transformation 단계에 한하여 DaC(Data as Code)를 구축할 수 있었습니다.
(3) 사내 구성원들이 쉽게 볼 수 있는(=접근성이 높은) BI 대쉬보드 구축하기
  • 구글 워크스페이스와 Data Studio를 사용함으로써 BI 비용 지출 없이 인증된 내부 구성원들에게 대쉬보드를 제공할 수 있었고 상황에 따라 추가적인 권한 설정도 가능했습니다.
  • dbt를 활용한 덕분에 적재부터 시각화까지 모든 Transformation이 BigQuery 내에서 이루어져 인프라에 대한 고민 없이 많은 데이터를 참조하는 쿼리 결과도 수초 이내에 대쉬보드로 볼 수 있었습니다.
(4) 비용
  • 가장 궁금할 수 있는 항목인데요. 서술한 ETL 파이프라인부터 데이터웨어하우스, BI 시스템까지 모두 운영하는데 2022년 5월 기준으로 약 70만원이 소요되었습니다. 이 중 40%가 BigQuery 쿼리 비용, 50%는 Fivetran, 10%는 기타 비용이 차지하였습니다.
  • 데이터가 US 리전에 적재된 이후에는 GCP 환경을 떠나지 않기 때문에 네트워크 Egress, 리전 간 데이터 전송 비용이 발생하지 않았고 RKE2 기반의 온프레미스 쿠버네티스와 Data Studio를 운영한 덕분에 인스턴스 사용료와 BI 비용이 0원에 가까웠습니다.

8. 남은 과제와 다음 목표

영원하고 완벽한 시스템은 없듯이 지금의 데이터 웨어하우스도 아직은 부족한 점이 많으며 아래와 같은 주제들로 꾸준히 개선하는 것을 목표로 하고 있습니다.
  • Data Privacy : 민감한 개인식별정보(PII, Personally identifiable information)가 담겨있는 컬럼들에 대해 Column-level Access Control을 적용하여 개인 정보 처리 담당 구성원들만 접근할 수 있도록 액세스를 관리합니다. 민감한 정보를 제외한 나머지 사내 데이터는 누구든지 쿼리할 수 있는 환경을 조성합니다.
  • Data Security : 각종 파이프라인에서 사용되는 서비스 계정 별로 세분화된 권한을 부여하고 VPC Service Controls과 Service Perimeter를 설정해 불특정한 외부의 접근을 차단하고 온프레미스 리소스로부터 접근은 가능하도록 변경합니다.
  • Data Lineage 고도화 : 현재는 하나의 Airflow BashOperator에 의해 모든 dbt 모델이 실행되므로 개별 모델별 상태 모니터링, 재실행이 어렵습니다. dbt 컴파일 시에 생성되는 모델 간 디펜던시 그래프 정보를 바탕으로 dbt 모델 레벨의 Operator를 자동으로 생성(Astronomer의 Integrating Airflow and dbt 글)해보려고 합니다. 더불어 지금은 특정 열이 변경될 때 해당 열의 전후로 엮여 있는 열들을 dbt SQL 파일을 통해 파악해야 되는 불편함이 있습니다. 이 과정을 개선하기 위해 열 수준의 Data Lineage를 쉽게 파악할 수 있는 오픈소스 프로젝트를 도입해보고 싶습니다.
  • MLOps 준비하기 : 기본적인 사내 데이터 웨어하우스가 자리 잡아감에 따라 리서치팀에서는 닥터차 앱과 닥터트레드의 사용 경험을 더 극대화시킬 수 있는 정비 콘텐츠 검색 엔진, 타이어 인식 모델과 같은 머신러닝 프로젝트들을 고도화하려고 합니다. 이를 위해 텍스트, 이미지와 같은 비정형 데이터셋과 모델 아티팩트, 모델 서빙을 더 체계적으로 관리할 수 있도록 데이터 레이크(어쩌면 BigLake?)와 Feature Store로 시스템을 확장해나갈려고 합니다.

9. Key Takeaway겸 구축 후기

  • 처음 사용하는 솔루션일수록 공식 문서 상의 가이드라인을 통해 Best Practice를 숙지하면 시행 착오를 덜 겪을 수 있다는 것을 느꼈습니다.
  • 아무리 계획과 규칙을 잘 세워도 예외는 발생하니 완벽한 규칙을 만들기 보다는 협업하는 팀원들이 포괄적으로 이해할 수 있는 수준의 가이드라인 개념으로써 활용하고, 일부 예외들은 그때 그때 임기응변으로 유연하게 대응하는 방식이 생산성이 높았던 것 같습니다.
  • 위 글에서는 데이터 웨어하우스 솔루션 선택, ELT 파이프라인, BI 툴 선정의 순서대로 나열했지만 실제로는 데이터 웨어하우스를 이루는 각 컴포넌트들의 스택(조합) 구성에 따라 연동 가능한 범위와 퍼포먼스, 데이터 전송 비용, 유지보수, 확장성이 다르기 때문에 컴포넌트를 순차적으로 결정하는 방식 보다는 모든 컴포넌트들을 최대한 동시에 고려하여 시너지가 날 수 있는 스택 후보군을 추리고, 프로젝트 목표를 가장 잘 달성할 수 있는 스택을 선정하는 것이 중요하다고 느꼈습니다.
  • Product-level Project에 데이터 적재 → dbt → Analytics Project에 staging, mid, tbl 모델 관리 → Data Studio, Spreadsheet 의 프로세스가 적응하기 쉽고, 신규 파이프라인, 신규 대쉬보드를 구축 할 때 확장하기에도 용이하다고 느껴 다른 스타트업에도 추천드리고 싶습니다.
  • Data Studio는 유료 BI 툴에 비해 기능이 턱없이 부족해 심도 있는 분석용으로는 부적합 하지만 전사 구성원들이 모니터링하는 용도로는 충분한 역할을 하는 것 같습니다. 더불어 개발 속도는 느리지만 꾸준히 개선되고 있기 때문에 릴리즈 노트를 팔로우업 하는 것이 중요하다고 느꼈습니다. 아쉽다고 생각했던 기능(가령 아직 매개변수에 날짜를 만들 수 없는 부분)들이 어느날 신규 배포되어 있는 경우를 종종 겪었기에 항상 관심을 가져줍시다.
  • 실제 데이터를 사용하는 구성원들에게 친화적인 환경을 만드는 것, 그들이 데이터 기반의 생각을 할 수 있도록 지속적으로 알려주는 과정이 훨씬 더 중요하다는 것을 배웠습니다. 실제 프로덕트를 만들고 고민하는 사람들이 생각하는 가설들이 실제로 시장에 임팩트를 낼 수 있는 경우가 더 많기 때문에, 데이터 사이언티스트는 그런 생각을 씨앗으로 더 큰 비즈니스 임팩트를 낼 수 있는 생각으로 키워내는 것이 중요하다고 느꼈습니다.
  • 파이프라인을 한번 세팅하고 난 뒤에도 멀리서 보면 멀쩡해보이지만 자세히 들여다 보아야지만 발견할 수 있는 정합성 문제들이 존재함을 알게 되었으며 정합성 100%를 달성하기 위해서는 데이터 엔지니어의 ‘집착’에 가까운 정성이 필요하다고 느꼈습니다.

맺음말

꽤나 긴 글을 시간 내어 읽어주셔서 감사합니다!
커뮤니티에 올라온 여러 구축 사례, 발표 세션, 글들은 데이터 엔지니어링에 대해 아무것도 몰랐던 우리 팀에게 거인의 어깨가 되어 주었습니다. 많은 도움을 받은 만큼, 스타트업 데이터 배관공 생존기는 저희 팀이 겪은 시행착오를 통해 배운 지식과 교훈을 공유하여 커뮤니티에 다시 기여할 수 있기를 희망하며 투고됩니다. 다음 편에서는 ‘스타트업에서 온프레미스 쿠버네티스 클러스터 운영해 본 썰’로 돌아오겠습니다.
끝으로 자동차에 관심이 있고 정비 시장의 넘버원 플랫폼을 만드는 과정에서 데이터 엔지니어링, 프론트/백엔드, 머신러닝 개발에 관심이 있거나 참여하고 싶으신 분들은 언제든지 편하게 연락주세요. 대화 나누어요! (커피는 제가 사겠습니다)

Reference

오토피디아 채용에 관한 모든 것을 준비했어요

첨단기술을 통한 모빌리티 혁신, 함께 하고 싶다면?

채용 둘러보기

글쓴이

Kevin Jo
Kevin Jo

Software Engineer (Data/ML) | 오토피디아 공동창업자 지금 여기서, 인공지능 기술로 세상을 바꿀 수 있다고 믿습니다.

0 comments

같이 보면 좋은 글

온프레미스 쿠버네티스에서 NAS, GPU 사용하기 (with RKE2, NFS, gpu-operator)

온프레미스 쿠버네티스에서 NAS, GPU 사용하기 (with RKE2, NFS, gpu-operator)

스타트업 온프레미스 K8S 구축기 2편

온프레미스 쿠버네티스 프로덕션 환경 10개월 운영기

온프레미스 쿠버네티스 프로덕션 환경 10개월 운영기

스타트업 온프레미스 K8S 구축기 1편 (야, 너두 할 수 있어)

ECS 톺아보기

ECS 톺아보기

ECS 기본 개념을 확실히 알아보고, ECS로 서비스를 출시하는 방법에 대해 알아봅시다!

데이터 엔지니어: 오토피디아 5개월 인턴 후기

데이터 엔지니어: 오토피디아 5개월 인턴 후기

Streamlit으로 정비소 탐색 지도 만들기

Streamlit으로 정비소 탐색 지도 만들기

Streamlit은 프로토타입용으로만 쓰는 거 아닌가요?

코어 웹 바이탈 LCP 개선을 통한 검색 엔진 최적화(SEO)  Part 1: Google Search Console, Next.js

코어 웹 바이탈 LCP 개선을 통한 검색 엔진 최적화(SEO) Part 1: Google Search Console, Next.js

월간 20만명 이상의 자연 유입 사용자 모으고 유지하기

쿠버네티스 oauth-proxy로 구글 SSO 적용하기

쿠버네티스 oauth-proxy로 구글 SSO 적용하기

oauth-proxy를 이용하여 내부 쿠버네티스 서비스 보안 지키기

로컬 Airflow on K8S 구축에 Vault 곁들이기 - Airflow 개발 환경 고도화

로컬 Airflow on K8S 구축에 Vault 곁들이기 - Airflow 개발 환경 고도화

Airflow 쿠버네티스 로컬 환경 구축과 Vault로 보안 강화하기

실시간 데이터 파이프라인 구축기 - Terraform으로 EKS를 띄워보자

실시간 데이터 파이프라인 구축기 - Terraform으로 EKS를 띄워보자

CDC 파이프라인 구축하기

ApplicationSet, Kustomize로 다중 환경/다중 클러스터 GitOps 운영하기 - ArgoCD 도입기 1편

ApplicationSet, Kustomize로 다중 환경/다중 클러스터 GitOps 운영하기 - ArgoCD 도입기 1편

누가 내 yaml에 똥 쌌어?