통합 데이터 허브로 가는 길 - Part 1

도입 배경과 선택 과정
Gray Yoon's avatar
Nov 03, 2025
통합 데이터 허브로 가는 길 - Part 1

1. 지금은 데이터를 활용하기 어렵다

우리가 이 프로젝트를 시작했을 때 가장 먼저 부딪힌 문제는 단순했습니다.

“데이터는 많지만, 활용은 어렵다.”

분석가는 각자 다른 도구를 쓰고 있었습니다. 어떤 사람은 Zeppelin(Athena), 어떤 사람은 Zeppelin(Spark), 또 누군가는 AWS Console, 혹은 DBeaver로 직접 쿼리를 날렸습니다.

데이터 탐색은 OpenMetadata, 테스트는 로컬, 운영 반영은 Slack이나 Jira Ticket으로 수동 요청.

즉, 데이터는 중앙에 있었지만, 일하는 방식은 흩어져 있었습니다.

SQL을 한 줄 수정하려 해도 일이 복잡했습니다.

  • GitHub를 모르면 코드 구조를 파악하기 어렵고,

  • Spark 코드를 알아야 배치를 수정할 수 있으며,

  • 배치 등록·DDM·Alert 같은 업무는 모두 수작업 요청으로 처리됐습니다.

문제의 본질은 “도구의 부족”이 아니라 “흐름의 단절”이었습니다.

우리는 분석과 탐색, 개발과 시스템화를 하나의 연속된 흐름으로 통합해야 했습니다.


2. 우리가 원한 것은 ‘한 곳에서 시스템화까지’

핵심 요구사항은 명확했습니다.

“한 곳에서 데이터를 탐색하고, 분석하고, 시스템화까지 할 수 있는 플랫폼.”

여기서 한 곳에서 란, 각자 환경을 따로 구성하지 않아도 동일한 환경에서 바로 업무를 시작할 수 있는 것,

그리고 시스템화 란, 분석가가 작성한 SQL 모델을 그대로 배치 파이프라인이나 애플리케이션에 연결할 수 있는 구조를 의미했습니다.

즉, 분석가가 SQL을 작성하면 엔지니어가 그 로직을 Spark 코드로 옮겨 빌드·배포하는 단계를 없애는 것.

이것이 우리가 정의한 ‘통합 데이터 허브’의 출발점이었습니다.


3. Zeppelin을 검토했지만 한계를 느낀 이유

분석가들이 이미 Apache Zeppelin을 쓰고 있었기 때문에

처음에는 이를 확장·유지보수하는 방안을 검토했습니다.

UI도 익숙했고, SQL 실행기 역할도 충분했으니까요.

그러나 엔터프라이즈 플랫폼으로 발전시키기엔 한계가 명확했습니다.

  • 확장성 부족: 동시 접속 시 세션 충돌이 잦고, 무거운 쿼리 하나가 전체 세션 안정성에 영향을 줬습니다.

  • 언어적 제약: Zeppelin은 Java 기반이라 Python 생태계와 거리가 멀었습니다. dbt, pandas, PySpark, boto3 같은 핵심 라이브러리를 일관되게 다루기 어려웠습니다.

  • 운영 부담: Interpreter 구조가 비유연해 확장을 위해 소스 레벨 수정이 필요했고, 유지보수가 까다로웠습니다.

결국 Zeppelin은 SQL 실행기 수준에서는 훌륭했지만,

dbt와 Python 생태계를 포괄하는 엔터프라이즈 데이터 허브로 발전하기엔 구조적으로 제약이 컸습니다.


4. Spark 위의 Athena, 그 비효율을 바꾼 dbt

당시 우리의 분석 파이프라인은 단순했지만 비효율적이었습니다.

분석가들은 Zeppelin(Athena)에서 SQL을 작성해

“이걸 배치로 등록해달라”고 데이터 엔지니어링 팀에 요청했습니다.

그러면 우리는 그 쿼리를 Spark Job으로 감싸 EMR에서 실행하도록 만들었습니다.

문제는 애초에 Athena에서 충분히 처리 가능한 쿼리조차 Spark로 돌려야 했다는 점이었습니다.

작은 수정에도 Spark 배치를 다시 빌드해야 했고,

단순한 데이터 추출 로직 하나를 바꾸려면 운영 배포가 필요했습니다.

리소스는 낭비됐고, 속도는 느려졌습니다.

“SQL을 바로 수정해서 돌릴 수 있으면 끝날 일을 굳이 Spark에서 돌린다.”

이 구조가 계속 발목을 잡았습니다.

이 비효율을 근본적으로 해결하기 위해 도입한 도구가 dbt(Data Build Tool)입니다.

dbt는 SQL만으로 파이프라인을 정의할 수 있어

분석가들이 익숙한 언어로 직접 배치를 구성할 수 있습니다.

조금만 구조를 익히면 Git PR을 통해 모델을 등록·수정할 수 있고,

엔지니어는 환경과 품질만 관리하면 됩니다.

즉, “분석가는 SQL로 직접 배치를 구성하고, 엔지니어는 환경을 관리한다.”

이게 우리가 만들고자 한 이상적인 형태였습니다.


5. dbt 도입 시 마주한 GitFlow 장벽

Git branch conflict 예시

dbt는 훌륭한 도구지만, 전제 조건이 있습니다.

모든 사용자가 Git 워크플로우를 능숙하게 다뤄야 한다는 점입니다.

일반적인 dbt 작업 흐름은 이렇습니다.

  1. Feature 브랜치 생성

  2. SQL 모델 수정 및 커밋

  3. Pull Request 생성

  4. 리뷰 후 Merge → CI/CD 배포

데이터 엔지니어에게는 자연스럽지만,

비개발 직군에게는 merge conflict, rebase, squash 같은 Git 개념에서 매번 멈춰섰습니다.

“SQL 모델 하나 추가하려면 Git 충돌부터 해결해야 한다.”

이 현실은 생산성의 적이었습니다.

GitFlow 자체가 잘못된 것은 아니지만,

모든 사용자가 같은 수준으로 Git을 다루어야 한다는 전제는

조직 전체 확산의 큰 장애물이었습니다.

우리가 찾던 것은

“Git을 잘 몰라도 안전하게 dbt 모델을 작성·배포할 수 있는 환경.”

즉, Git 워크플로우를 사용자 친화적으로 추상화할 수 있는 플랫폼이 필요했습니다.

그 해답이 JupyterHub였습니다.


6. 결론 — 우리가 택한 조합, Jupyter + dbt

정리하면, 우리가 만든 “통합 데이터 허브”는

두 가지 문제를 동시에 해결하기 위한 조합이었습니다.

  • Zeppelin의 확장성 한계와 Python 단절 문제

  • dbt 도입 시 GitFlow 장벽 문제

이 두 가지를 함께 해결할 수 있었던 유일한 선택이 JupyterHub + dbt였습니다.

  • JupyterHub: 인증, 격리, 버전관리, 확장성, 사용자 경험을 모두 포괄하는 기반 플랫폼

    Zeppelin VS JupyterHub
    Zeppelin VS JupyterHub
  • dbt: SQL 중심의 모델 정의와 배치 자동화를 담당하는 데이터 로직 엔진

결국 우리는 이렇게 정리했습니다.

“분석가는 SQL로 모델을 만들고,

JupyterHub는 그것을 운영 가능한 시스템으로 만든다.”

Zeppelin 시절의 “각자 하는 분석”에서

JupyterHub + dbt 기반의 “같은 공간에서 함께 만드는 분석”으로 전환한 것.

그게 우리가 진짜로 원했던 변화였습니다.


이제 다음 편, Part 2에서는

이 구조를 실제로 어떻게 설계하고 구축했는지,

즉, 우리의 JupyterHub 아키텍처 설계 원칙과 구축 과정을 구체적으로 다뤄보겠습니다.

Share article