상위: dbt
요약
dbt 모델은 하나의 SQL SELECT 문이다. 파일 하나가 모델 하나이며, dbt가 이를 웨어하우스에 테이블이나 뷰로 자동 생성한다. Materialization 전략에 따라 데이터가 저장되는 방식이 달라진다.
모델 기본 구조
-- models/staging/stg_orders.sql
SELECT
id AS order_id,
user_id,
order_date,
status,
amount
FROM {{ source('jaffle_shop', 'orders') }}
WHERE status != 'deleted'
- 파일명이 모델명이 된다 (
stg_orders) - SELECT만 작성 — CREATE TABLE/VIEW는 dbt가 처리
{{ source() }}로 원본 테이블 참조{{ ref() }}로 다른 모델 참조
ref() 함수
-- models/marts/fct_orders.sql
SELECT
o.order_id,
o.order_date,
c.customer_name,
o.amount
FROM {{ ref('stg_orders') }} o
JOIN {{ ref('stg_customers') }} c ON o.user_id = c.customer_id
ref()는 dbt의 핵심 함수이다:
- 모델 간 의존성을 자동으로 파악하여 실행 순서를 결정
- 환경(dev/prod)에 따라 스키마를 자동 전환
- 리니지 그래프를 자동 생성
Materialization 전략
모델이 웨어하우스에 어떤 형태로 저장되는지 결정한다.
View (기본값)
# dbt_project.yml
models:
my_project:
staging:
+materialized: view
- 매 쿼리 시 SQL을 재실행한다
- 저장 공간을 사용하지 않는다
- Staging 레이어에 적합 — 항상 최신 데이터 보장
Table
{{ config(materialized='table') }}
SELECT ...
- 결과를 물리적 테이블로 저장한다
- 쿼리 성능이 빠르다 (사전 계산)
dbt run시 DROP + CREATE로 완전 재빌드- Marts 레이어에 적합 — 자주 쿼리되는 최종 테이블
Incremental
{{ config(materialized='incremental', unique_key='order_id') }}
SELECT *
FROM {{ source('jaffle_shop', 'orders') }}
{% if is_incremental() %}
WHERE updated_at > (SELECT MAX(updated_at) FROM {{ this }})
{% endif %}
- 신규/변경된 행만 INSERT 또는 UPDATE
- 대용량 테이블에서 빌드 시간을 대폭 줄인다
is_incremental()매크로로 분기 처리unique_key로 중복 방지 (MERGE 전략)- 대규모 팩트 테이블에 적합
Ephemeral
{{ config(materialized='ephemeral') }}
SELECT ...
- 웨어하우스에 물리적 객체를 생성하지 않는다
- 참조하는 모델에 CTE로 인라인된다
- 중간 계산용 가벼운 변환에 적합
Materialized View
{{ config(materialized='materialized_view') }}
SELECT ...
- 웨어하우스가 자동으로 데이터를 최신 상태로 유지
- View와 Table의 중간 — 저장하되 자동 갱신
- Snowflake, BigQuery 등에서 지원
선택 가이드
| 전략 | 저장 | 빌드 시간 | 쿼리 성능 | 사용처 |
|---|---|---|---|---|
| View | X | 즉시 | 느림 | Staging |
| Table | O | 매번 전체 | 빠름 | Marts (소규모) |
| Incremental | O | 변경분만 | 빠름 | Marts (대규모 팩트) |
| Ephemeral | X | 없음 | - | 중간 CTE |
| Materialized View | O | 자동 | 빠름 | 실시간성 필요 시 |
관련 개념
- Project Structure: 모델을 Staging/Intermediate/Marts로 조직하는 방법
- Macros & Jinja: 모델에서 동적 SQL을 생성하는 방법
- Tests: 모델에 테스트를 추가하는 방법