전체 그래프
dbt

Project Structure

data-engineeringdbtarchitecturebest-practice

상위: dbt

요약

dbt 프로젝트는 Staging → Intermediate → Marts의 3계층 구조를 권장한다. 각 계층은 역할과 Materialization 전략이 다르며, Medallion Architecture의 Bronze/Silver/Gold와 유사한 개념이다.

디렉토리 구조

models/
├── staging/
   ├── jaffle_shop/
      ├── _jaffle_shop__sources.yml
      ├── _jaffle_shop__models.yml
      ├── stg_jaffle_shop__orders.sql
      └── stg_jaffle_shop__customers.sql
   └── stripe/
       ├── _stripe__sources.yml
       └── stg_stripe__payments.sql
├── intermediate/
   └── finance/
       ├── _int_finance__models.yml
       └── int_payments_pivoted.sql
└── marts/
    ├── finance/
       ├── _finance__models.yml
       ├── fct_orders.sql
       └── dim_customers.sql
    └── marketing/
        └── dim_customer_segments.sql

Staging Layer

역할: 소스 시스템의 원본 데이터를 표준화하고 정리하는 첫 단계.

원칙:

  • 1 소스 테이블 = 1 Staging 모델 (1:1 매핑)
  • 소스 시스템별로 서브디렉토리 분리 (jaffle_shop/, stripe/)
  • 접두사 stg_ 사용
  • Materialization: View — 항상 최신 데이터 보장, 저장 공간 절약

변환 범위 (가벼운 정리만):

  • 컬럼 이름 표준화 (snake_case)
  • 타입 캐스팅
  • 기본 필터링 (삭제된 행 제외 등)
  • 비즈니스 로직은 여기서 적용하지 않는다
-- models/staging/jaffle_shop/stg_jaffle_shop__orders.sql
SELECT
    id AS order_id,
    user_id AS customer_id,
    order_date,
    CAST(status AS VARCHAR(20)) AS order_status,
    amount
FROM {{ source('jaffle_shop', 'orders') }}
WHERE _deleted IS FALSE

Intermediate Layer

역할: 비즈니스 로직을 적용하는 중간 변환 단계.

원칙:

  • 비즈니스 영역별로 서브디렉토리 분리 (finance/, marketing/)
  • 접두사 int_ 사용
  • 4~6개의 Staging 모델을 조합
  • Materialization: Ephemeral 또는 View — 최종 사용자가 직접 쿼리하지 않음

변환 범위:

  • JOIN, 집계, 윈도우 함수
  • 복잡한 비즈니스 규칙 적용
  • Marts에 공급할 데이터 준비
-- models/intermediate/finance/int_payments_pivoted.sql
SELECT
    order_id,
    SUM(CASE WHEN payment_method = 'credit_card' THEN amount END) AS credit_card_amount,
    SUM(CASE WHEN payment_method = 'bank_transfer' THEN amount END) AS bank_transfer_amount,
    SUM(amount) AS total_amount
FROM {{ ref('stg_stripe__payments') }}
GROUP BY order_id

Marts Layer

역할: 비즈니스 사용자가 직접 쿼리하는 최종 테이블.

원칙:

  • 부서/도메인별로 서브디렉토리 분리 (finance/, marketing/)
  • fct_ (팩트, 이벤트) 또는 dim_ (디멘션, 엔티티) 접두사
  • Materialization: Table 또는 Incremental — 빠른 쿼리 성능
  • 하나의 Mart 모델 = 하나의 엔티티/개념의 고유 grain
-- models/marts/finance/fct_orders.sql
{{ config(materialized='table') }}

SELECT
    o.order_id,
    o.customer_id,
    o.order_date,
    o.order_status,
    p.total_amount,
    p.credit_card_amount,
    c.customer_name,
    c.first_order_date
FROM {{ ref('stg_jaffle_shop__orders') }} o
LEFT JOIN {{ ref('int_payments_pivoted') }} p ON o.order_id = p.order_id
LEFT JOIN {{ ref('dim_customers') }} c ON o.customer_id = c.customer_id

Medallion Architecture 대응

dbt LayerMedallionMaterialization역할
StagingBronzeView원본 정리
IntermediateSilverEphemeral/View비즈니스 로직
MartsGoldTable/Incremental분석용 최종 테이블

완전히 1:1은 아니지만 개념적으로 유사하다. Medallion은 데이터 레이크 전체의 계층이고, dbt 레이어는 변환 단계의 계층이다.

네이밍 컨벤션 요약

접두사계층예시
stg_Stagingstg_jaffle_shop__orders
int_Intermediateint_payments_pivoted
fct_Marts (팩트)fct_orders
dim_Marts (디멘션)dim_customers

소스 시스템명은 더블 언더스코어(__)로 구분한다: stg_{source}__{entity}.

관련 개념