전체 그래프
dbt

Snapshots

data-engineeringdbtsnapshotscd

상위: dbt

요약

dbt Snapshot은 변경 가능한(mutable) 소스 테이블의 변경 이력을 추적하는 기능이다. SCD Type 2(Slowly Changing Dimension)를 구현하여, 특정 시점의 데이터 상태를 조회할 수 있다.

왜 필요한가

소스 시스템의 테이블은 UPDATE로 기존 값을 덮어쓴다. 예를 들어 주문 상태가 placedshippedcompleted로 변경되면, 소스에는 최종 상태만 남는다.

Snapshot은 변경 전 값을 보존하여 "이 주문이 언제 shipped 상태였는가?"를 추적할 수 있게 한다.

정의 방법

# snapshots/orders_snapshot.yml (dbt >= 1.9)
snapshots:
  - name: orders_snapshot
    relation: source('jaffle_shop', 'orders')
    config:
      schema: snapshots
      unique_key: order_id
      strategy: timestamp
      updated_at: updated_at

또는 SQL 블록 방식 (레거시):

-- snapshots/orders_snapshot.sql
{% snapshot orders_snapshot %}
{{
    config(
        target_schema='snapshots',
        unique_key='order_id',
        strategy='timestamp',
        updated_at='updated_at'
    )
}}

SELECT * FROM {{ source('jaffle_shop', 'orders') }}

{% endsnapshot %}

전략 (Strategy)

timestamp 전략

strategy: timestamp
updated_at: updated_at

소스 테이블에 updated_at 같은 타임스탬프 컬럼이 있을 때 사용한다. 해당 값이 변경되면 새 행을 삽입한다. 가장 권장되는 전략이다.

check 전략

strategy: check
check_cols: ['status', 'amount']
# 또는 check_cols: 'all'

타임스탬프 컬럼이 없을 때 사용한다. 지정한 컬럼의 값이 변경되면 새 행을 삽입한다. check_cols: 'all'은 모든 컬럼을 비교하지만 성능이 떨어진다.

결과 테이블 구조

Snapshot 실행 후 생성되는 테이블에는 dbt가 자동으로 메타 컬럼을 추가한다:

컬럼설명
dbt_scd_id각 행의 고유 ID
dbt_updated_at변경이 감지된 시점
dbt_valid_from이 행이 유효한 시작 시점
dbt_valid_to이 행이 유효한 종료 시점 (NULL = 현재 유효)

예시 데이터

order_id | status    | dbt_valid_from      | dbt_valid_to
---------|-----------|--------------------|-----------------
1001     | placed    | 2026-01-01 10:00   | 2026-01-03 14:00
1001     | shipped   | 2026-01-03 14:00   | 2026-01-05 09:00
1001     | completed | 2026-01-05 09:00   | NULL

dbt_valid_to가 NULL인 행이 현재 상태이다.

실행

dbt snapshot              # 모든 스냅샷 실행
dbt build                 # run + test + snapshot 통합

스냅샷은 주기적으로 실행해야 한다. 실행 간격 사이의 변경은 캡처되지 않는다. 예를 들어 하루 1회 실행하면, 하루 안에 placedshippedcompleted로 바뀌어도 최종 상태만 캡처된다.

관련 개념

  • Models: 스냅샷 테이블을 모델에서 ref()로 참조할 수 있다
  • Sources & Seeds: 스냅샷의 입력은 보통 Source이다