📗DBT(data build tool) 개요
dbt란 데이터 변환(transform)을 SQL 기반으로 관리하는 도구이다. 데이터 엔지니어 → 데이터 모델러 → 비즈니스 분석가" 사이를 자연스럽게 이어주는 ELT 중심 도구이다.
dbt가 처음 등장한 이유는 다음과 같은 예전 데이터 파이프라인 문제점 때문이다.
dbt가 해결한 것은 다음과 같다.
"ETL은 개발자가 만든다"는 전통적 사고방식은 버려야 한다. dbt를 쓰려면 조직이 "데이터 변환을 오픈하고 협업한다"는 마인드가 필요하다.
🏳️🌈 [궁금한점]
🔗목차
| 이유 | 설명 |
|---|---|
| SQL만 알면 된다 | Python이나 Java 몰라도 된다. |
| 버전 관리 | Git으로 파이프라인 버전 관리가 가능하다. |
| 테스트 내장 | 데이터 검증 로직이 쿼리 옆에 붙는다. |
| 문서 자동화 | 데이터베이스 구조를 자동으로 문서화해준다. |
| DAG 관리 | 테이블 간의 의존성(DAG)을 코드로 선언적으로 관리한다. |
| DevOps 친화적 | CI/CD 파이프라인에 쉽게 연결된다. |
| 예전 | dbt 이후 |
|---|---|
| 데이터 엔지니어가 ETL 담당 → 분석가들은 못 건드림 | 분석가, 엔지니어 모두 SQL로 협업 |
| Python/Java 스크립트 복잡 | SQL 기반 간결한 모델링 |
| 수작업 문서화 | 문서화 자동화, lineage도 자동 |
| ETL 배포 어려움 | Git+CI/CD로 배포 자동화 가능 |
| 오류나면 디버깅 힘듦 | dbt test로 사전 검증 |
| 개념 | 설명 |
|---|---|
| Model | SQL 파일 하나 = 하나의 테이블(또는 뷰). select 쿼리로 정의 |
| DAG | 모델 간 의존 관계를 그래프로 그려준다. (upstream → downstream) |
| Test | 컬럼 값이 NULL이면 안 된다, unique해야 한다 같은 걸 자동 검증 |
| Documentation | 모델 정의서, lineage(계보)를 자동 문서화해줌 |
| Seed | CSV 파일을 테이블처럼 로딩해서 쓸 수 있음 |
| Snapshot | 테이블 변경 이력을 관리하는 기능 (타임 트래블처럼) |
| Run / Build | 정의한 모델을 실제로 실행해서 테이블/뷰로 만들어줌 |
팀이 커지고, 테이블 수가 많아지거나, 운영환경(dev/stg/prod)이 나뉘면 dbt 없이 버티기 힘들다. dbt는 규모가 커질 때 진가를 발휘한다. dbt는 작은 문제에는 과하지만, 큰 문제를 미리 예방하는 보험 같은 도구이다.
foo.sql, bar.sql 이렇게 파일 여러 개 만들어 놓고 쿼리 작성해서 데이터베이스에 직접 CREATE TABLE AS SELECT 실행한다. 이 경우, 각 쿼리 간 의존성(순서)을 사람이 기억해야하고, 변경사항은 수작업 (ALTER TABLE 직접 실행)으로 진행된다. 문서화는 엑셀이나 위키 따로 정리해야 한다. 테스트는 사람 눈으로 직접 확인 (null 체크, unique 체크)한다.
이 경우 발행할 수 있는 문제점은 다음과 같다
models/ 안에 각 계층별로 폴더 구분 (raw/, staging/, mart/)한다. 모델 간 의존성을 ref() 함수로 명시한다. dbt run 하면 의존성 순서대로 자동 실행된다. 변경사항은 Git PR로 관리한다. 문서화는 dbt docs로 자동진행된다. 데이터 품질은 dbt test로 자동화한다. 코드 재사용은 macro로 템플릿화한다.
좋아지는 점은 다음과 같다.
| 항목 | dbt | Spark |
|---|---|---|
| 정체성 | 데이터 변환(Transform) 자동화 도구 | 분산 데이터 처리 엔진 |
| 핵심 기능 | SQL 기반 모델 작성, 실행, 관리, 테스트 | 대규모 데이터 연산(ETL, 머신러닝, 스트리밍 처리) |
| 주 언어 | SQL (Jinja 템플릿 사용 가능) | Scala, Java, Python, SQL |
| 동작 방식 | 명령어로 SQL을 순차 실행 (ELT 중심) | 클러스터 기반 분산 컴퓨팅 (RDD, DataFrame) |
| 처리 대상 | 보통 "테이블 가공" (데이터 양은 작을 수도 있음) | 수 TB~PB급 데이터 처리 가능 |
| 리소스 관리 | 없음 (백엔드에 의존) | 있음 (Executor, Driver 관리) |
| 용도 | 데이터 모델링, 파이프라인 오케스트레이션 | 복잡한 변환, ML, 대규모 데이터 분석 |
dbt는 "어떤 변환을 할지" 정의하고, Spark는 "변환을 실제로 어떻게 처리할지" 실행한다. 둘을 연계해서 활용한다.
| 구성 | 설명 |
|--------------------|----------------------------------------------|
| dbt-spark adapter | dbt가 Spark를 통해 테이블 생성/변환 명령을 날림 |
| Spark backend | 실제로 클러스터가 데이터 가공 실행 |
| 결과 | dbt 프로젝트에서 만든 모델이 Spark에서 병렬로 빠르게 처리 |
Spark에서는 SELECT * FROM 테이블 할 때 그냥 코드 복붙하거나 별도 스크립트 관리한다. 수정하려면 모든 스크립트 찾아다니면서 고쳐야 한다.
Spark만 쓰면 "테이블이 잘 만들어졌는지" 자동으로 검증하기 어렵다. 일일이 수작업으로 테스트하거나, 별도 스크립트 짜야 한다.
Spark만 쓰면 버전 관리가 어렵다. 어떤 쿼리가 운영에 올라간 건지 추적 힘들다. rollback(롤백)도 수작업으로 진행해야 한다. 프로덕션/개발 환경 분리도 별도 커스텀 짜야 한다. 데이터팀이 커질수록 "배포 실수" 늘어난다.
파이프라인의 의존관계(DAG)가 명시적이지 않다. 어느 테이블이 어느 테이블을 참조하는지 파악하기 힘들다. 문제 생기면 어디가 원인인지 찾기 힘들어서 장애 대응 시간 늘어난다.
| Spark만 | dbt + Spark |
|---|---|
| 쿼리 흩어짐 | SQL 모델 관리, 디렉토리 구조 |
| 수동 의존성 관리 | DAG 자동 생성 |
| 수동 테스트 | 자동 test 관리 (dbt test) |
| 수동 배포 | 버전 관리 + 배포 (dbt run) |
| 수작업 품질검사 | 데이터 품질 체크 자동화 |
도구가 처리하는 목적이나 실행 시점, 사용되는 언어가 매우 다르다
| 항목 | MyBatis | DBT |
|----------------|------------------------------------------|--------------------------------------|
| 주요 목적 | 애플리케이션 코드에서 DB 조회/변경하기 (ORM/SQL Mapper) | 데이터 웨어하우스에서 데이터 변환(Transform)하고 관리하기 |
| 사용하는 곳 | 백엔드 서버 (Java/Spring 등) | 데이터 엔지니어링, 데이터 플랫폼 |
| 다루는 SQL | 단일 트랜잭션(SQL) → Insert/Select/Update/Delete | 대량 변환(SQL) → Create Table as Select (CTAS), View 생성 |
| 주요 대상 | 트랜잭션성 데이터 (고객, 주문 데이터 CRUD) | 분석용 데이터 (DW, DM, Data Lake) |
| 실행 시점 | 사용자 요청시 (API 호출 등) | 스케줄러가 주기적으로 실행 (ETL 파이프라인) |
| 버전 관리 | 코드에 같이 묶여 관리 (Java 소스랑 함께) | 별도 Git 저장소에 SQL만 관리 |
| 주 사용 언어 | Java + XML(SQL) | SQL + Jinja (템플릿) |
dbt는 기본적으로 쿼리를 실행해서 테이블/뷰를 만든다. Iceberg는 쿼리로 조작 가능한 테이블 포맷이다 (ex. Trino, Spark, Flink, Snowflake 등에서 읽기/쓰기 가능). 즉, dbt가 Iceberg 테이블을 대상으로 모델링/변환 작업하는 게 가능하다.
| 구성 | 설명 |
|---|---|
| dbt → Trino | Trino가 Iceberg를 읽고 쓸 수 있으니까, Trino adapter로 dbt 연결 |
| dbt → Spark | Spark SQL로 Iceberg 테이블 조작 가능, Spark adapter 사용 |
| dbt → Snowflake | 요즘은 Snowflake도 Iceberg 테이블 외부로 연결 가능해서 이걸 통해 사용 가능 |
{{ config(
materialized='table',
schema='iceberg',
database='lakehouse'
) }}
SELECT
customer_id,
COUNT(*) AS total_orders,
SUM(amount) AS total_amount
FROM {{ source('iceberg', 'orders') }}
GROUP BY customer_id
dbt run 하면, Iceberg에 새로운 테이블이 생성된다.
| 항목 | 설명 |
|---|---|
| SQL 하나로 | Iceberg 테이블 생성/변경 모두 SQL로 가능 |
| Schema Evolution | 컬럼 추가/삭제도 dbt 모델에서 관리 가능 |
| Version 관리 | dbt가 Git 기반이라 모델 버전 히스토리 관리 가능 |
| DAG 자동 생성 | Iceberg 테이블 가공하는 흐름도 자동으로 시각화 |