Building dbt Models은(는) 무엇을 하나요?
사용 시기
- dbt 프로젝트에서
.sql모델을 생성하거나 리팩터링할 때 - 구체화 방식(뷰 / 테이블 / 증분 / 임시)을 결정할 때
- 레이어를 구조화할 때(staging → intermediate → marts)
- 대규모 증가 테이블을 위한 증분 모델을 작성할 때
- 테스트 작성을 위해서는
testing-dbt-projects를, 실행 실패 처리는debugging-dbt-runs를 사용하세요.
워크플로우
- [ ] 올바른 레이어(staging/intermediate/marts)에 모델 배치
- [ ] ref()/source()로만 업스트림 참조 — 하드코딩된 이름 사용 금지
- [ ] 크기와 갱신 필요성에 따라 구체화 방식 선택
- [ ] 증분 모델의 경우 unique_key + is_incremental() 필터 설정
- [ ] 테스트가 포함된 schema.yml 항목 추가
- 레이어링.
staging/= 소스 테이블당 하나의 모델, 가벼운 이름 변경/타입 변환, 뷰로 구체화.intermediate/= 재사용 가능한 비즈니스 로직.marts/= BI에서 소비하는 최종 차원 모델, 테이블로 구체화. - 올바른 참조.
{{ ref('stg_orders') }}및{{ source('shop', 'orders') }}를 사용하여 dbt가 DAG를 구축하고 환경을 관리하도록 합니다. 원시 schema.table은 절대 작성하지 마세요. - 구체화 방식 선택: 뷰(저렴, 항상 최신, 소규모), 테이블(빠른 읽기, 실행마다 재구축), 증분(대규모 추가/업데이트 테이블), 임시(인라인 CTE, 객체 없음).
- 증분 모델은 새 행 또는 변경된 행만 처리합니다.
패턴
Staging 모델 — 소스당 하나, 얇고 일관성 있음:
-- models/staging/shop/stg_orders.sql
with source as (select * from {{ source('shop', 'orders') }})
select
order_id,
customer_id,
cast(order_ts as timestamp) as ordered_at,
round(amount_cents / 100.0, 2) as amount
from source
증분 모델 — 새 행으로 필터링하고 멱등성 병합 키 설정:
{{ config(materialized='incremental', unique_key='order_id',
incremental_strategy='merge') }}
select * from {{ ref('stg_orders') }}
{% if is_incremental() %}
-- 이미 로드된 데이터보다 최신 행만, 지연 데이터를 위한 lookback 포함
where ordered_at >= (select coalesce(max(ordered_at), '1900-01-01') from {{ this }})
- interval '3 days'
{% endif %}
unique_key + merge는 재실행을 멱등하게 만듭니다. lookback은 지연 도착 행을 포착합니다. BigQuery/Spark에서는 날짜 파티션에 insert_overwrite를 선호합니다.
일반적인 함정
ref()/source()대신 하드코딩된 테이블 이름 — DAG, 계보 및 환경 전환을 깨뜨립니다.unique_key없는 증분 모델 — 재실행 시 중복이 추가됩니다.- lookback 없는
max(id)증분 필터 — 지연 데이터를 조용히 누락시킵니다. - staging의 비즈니스 로직 — staging은 얇게 유지하세요. 조인/집계는 intermediate/marts에 속합니다.
- 모든 것을
table로 구체화 — 웨어하우스 시간 낭비입니다. 소규모/저렴한 모델은 뷰를, 대규모 모델은 증분을 사용하세요. - 하나의 거대한 모델 — 테스트 가능성과 재사용을 위해 중간 단계로 분할하세요.