Search

[dbt] 3. dbt 구성요소 살펴보기

[dbt] 1. ELT의 시대 - dbt란 무엇인가?
dbt
Data Engineering
Data Analysis
2025/07/27
[dbt] 1. ELT의 시대 - dbt란 무엇인가?
dbt
Data Engineering
Data Analysis
2025/07/27
지난 글에서는 SQLite 환경에서 dbt 프로젝트를 세팅하고, 첫 번째 모델을 만들어 실행해보았습니다.
이번 글에서는 dbt의 7대 핵심 구성요소를 하나씩 짚으며, 각각이 데이터 파이프라인에서 어떤 역할을 하는지, 그리고 서로 어떻게 맞물려 동작하는지를 살펴보겠습니다.

왜 구성요소를 이해해야 할까?

dbt는 단순히 “쿼리를 실행하는 도구”가 아니라, 데이터 변환 과정을 코드처럼 관리하고, 테스트·문서화·계보 추적까지 통합하는 데이터 모델링 프레임워크입니다.
구성요소의 의미를 이해하면, 팀 내에서 일관성 있는 설계·운영이 가능해집니다.

dbt의 7대 구성요소

구성요소
역할
실무 포인트
Models
데이터 변환 로직의 최소 단위
쿼리·의존성 관리
Sources
원본 데이터 정의
위치 고정·계보 추적
Seeds
CSV 참조 데이터
코드와 함께 버전 관리
Snapshots
변경 이력 관리
Slowly Changing Dimension
Materializations
결과 저장 방식
성능·운영 전략 선택
Tests
데이터 품질 검증
unique, not_null 등
Documentation
모델·소스 문서화
계보와 설명 자동화

1. Models — 변환 로직의 최소 단위

모델(Model)은 dbt에서 데이터 변환 로직의 최소 단위입니다. 한 모델은 하나의 SQL 파일이며, 이를 실행하면 테이블(Table) 또는 뷰(View)로 생성됩니다.

주요 특징

SQL로 작성되며 Jinja 템플릿({{ }}) 문법과 함께 사용 가능
폴더 구조로 레이어 구분 가능 (staging, core, mart 등)
config를 통해 저장 방식, 태그, 결과물 이름 등을 제어 가능

예시 SQL

-- models/staging/stg_orders.sql -- 목적: -- 원본 주문 데이터(raw.orders)를 받아 -- 컬럼명·타입을 표준화하고 -- 향후 조인·집계가 쉽게 정리된 결과로 만든다. {{ config( materialized = 'view' -- 결과를 뷰로 생성 ) }} select order_id, -- 주문 ID (원본 그대로 사용) customer_id, -- 고객 ID cast(order_ts as timestamp) as order_time -- 문자열/숫자 → timestamp 변환 from {{ source('raw', 'orders') }} -- 원본 테이블 참조 (하드코딩 방지)
SQL
복사

예시 설명

원본 데이터 불러오기
source('raw', 'orders')sources.yml에 등록된 raw 레이어의 orders 테이블을 참조
하드코딩 대신 소스 정의를 사용하므로, 환경이 바뀌어도 수정할 SQL이 최소화
컬럼 표준화
order_tstimestamp 형식으로 변환해 order_time이라는 표준 이벤트 시간 컬럼을 생성
이후 모든 다운스트림 모델에서 동일한 시간 컬럼을 참조 가능
결과 저장 방식 설정
materialized='view' → 개발 단계에서 빠르게 반영 가능, 스키마 변경·테스트에 유리
운영에서는 필요 시 table 또는 incremental로 변경

구성요소 설명

구성 요소
역할
고려사항
{{ config(...) }}
모델 실행 시 동작 방식 정의 (저장 방식, 태그, alias 등)
저장 방식에 따라 성능·비용이 달라짐
source()
원본 데이터 참조
sources.yml 정의와 반드시 일치해야 함
cast(... as timestamp)
타입 변환
DB별 타임스탬프 포맷 차이 주의
materialized='view'
결과를 뷰로 생성
빠른 개발·테스트에 유리, 데이터 양 많으면 table 고려

2. Sources — 원본 데이터 고정점

Source는 dbt에서 원본 데이터의 위치와 구조를 정의하는 고정점 역할을 합니다. SQL 안에서 하드코딩된 스키마·테이블명을 쓰지 않고, YAML 설정을 통해 중앙에서 관리합니다.

주요 특징

환경별(DB, 스키마, 테이블명) 변경에 유연
데이터 품질 검사(test)를 source 단위에서 바로 적용 가능
변경 추적 가능 → 원본 스키마나 필드 변경 시 알림

예시 설정

# models/sources.yml version: 2 sources: - name: raw # 원본 스키마 이름 (논리적) description: "원본 시스템에서 추출된 데이터 레이어" tables: - name: orders description: "주문 거래 로그 원본 데이터" columns: - name: order_id description: "주문 ID, 고유 식별자" tests: # 데이터 품질 테스트 - not_null - unique - name: customers description: "고객 기본 정보"
YAML
복사

예시 SQL

-- models/staging/stg_orders.sql {{ config(materialized='view') }} select order_id, customer_id, cast(order_ts as timestamp) as order_time from {{ source('raw', 'orders') }} -- 원본 데이터 참조 (YAML 정의 기반)
SQL
복사

예시 설명

원본 데이터 위치 정의
sources.yml에서 raw.orders를 정의하고, 해당 DB/스키마/테이블명을 명시
실제 DB 접속 시에는 profiles.yml의 연결 정보와 매핑
SQL에서 간단하게 참조
source('raw', 'orders') → 하드코딩 없이 raw.orders를 참조
환경이 dev/prod로 바뀌어도 YAML만 수정하면 모든 모델에 반영
데이터 품질 관리
not_null, unique 같은 테스트를 소스 정의에 포함
dbt test --select source:raw.orders로 품질 검사 가능

구성요소 설명

구성 요소
역할
고려 사항
sources:
원본 데이터 그룹 정의
프로젝트별 논리 이름과 실제 DB 매핑 필요
tables:
원본 테이블 목록
모든 원본 테이블을 여기에 등록
columns:
컬럼별 설명 및 테스트 정의
컬럼 테스트는 데이터 품질 관리 핵심
source()
SQL에서 source 참조
YAML 정의와 반드시 이름·스펠링 일치

3. Seeds — CSV도 코드처럼 관리

Seed는 CSV 파일을 테이블로 로드하는 기능입니다. 원래 CSV를 DB에 넣으려면 별도의 로드 스크립트나 툴이 필요하지만, dbt에서는 CSV 파일을 data/ 폴더에 넣고 한 줄 명령으로 테이블로 변환할 수 있습니다.

주요 특징

CSV 파일도 Git에 버전 관리 가능
배포 환경(dev/prod)에서 동일한 데이터 보장
초기 코드/데이터 로딩, 기준값(코드 테이블) 관리에 유용

예시 CSV

# data/country_codes.csv country_code,country_name KR,South Korea US,United States JP,Japan
SQL
복사

예시 실행

# seeds 로드 dbt seed
Bash
복사

예시 SQL

-- models/marts/country_summary.sql {{ config(materialized='table') }} select cc.country_name, count(o.order_id) as total_orders from {{ ref('country_codes') }} as cc -- CSV를 테이블처럼 참조 left join {{ ref('orders') }} as o on cc.country_code = o.country_code group by cc.country_name
SQL
복사

예시 설명

CSV → DB 테이블 로드
data/country_codes.csvdbt seed로 실행하면 DB에 country_codes 테이블 생성
일관성 있는 기준 데이터 관리
국가 코드, 상품 카테고리 코드, 상태 코드 등 변하지 않는 기준값을 Git에 저장
모델에서 참조 가능
ref('country_codes')를 사용하여 다른 테이블과 조인

구성요소 설명

구성 요소
역할
고려 사항
data/
seed CSV 저장 폴더
파일명 = 생성될 테이블명
CSV 헤더
컬럼명 정의
SQL에서 그대로 사용
dbt seed
CSV → 테이블 로드 명령
실행 시 기존 데이터 덮어씀
ref()
seed 참조 함수
모델명과 동일한 이름 사용

4. Snapshots — 변경 이력 자동 관리

Snapshot은 테이블의 변경 이력(History)을 자동으로 관리하는 기능입니다. 예를 들어 고객의 주소, 주문 상태, 상품 가격처럼 시간이 지나면서 변하는 값을 "변경 전"과 "변경 후"를 모두 보관하고 싶을 때 사용합니다.

주요 특징

변경 감지 로직(변경된 행만 식별)
변경 시점 기록
기존 행 보존이 필요하지만, dbt의 Snapshot은 이를 SQL 한 장과 설정만으로 해결합니다.

예시 설정

-- snapshots/customers_snapshot.sql {% snapshot customers_snapshot %} {{ config( target_schema='snapshots', -- 이력 테이블 저장 위치 unique_key='customer_id', -- 변경 여부 판별 기준 strategy='check', -- 'check' 또는 'timestamp' check_cols=['email', 'address'] -- 변경 감지할 컬럼 ) }} select customer_id, email, address, updated_at from {{ source('raw', 'customers') }} {% endsnapshot %}
SQL
복사

예시 실행

# Snapshot 실행 dbt snapshot
Bash
복사
테이블 예시
customer_id
email
address
dbt_valid_from
dbt_valid_to
1001
Seoul, Korea
2024-01-01 00:00:00
2024-02-15 10:20:00
1001
Busan, Korea
2024-02-15 10:20:00
null

예시 설명

원본 테이블에서 고객 정보 조회
customer_id를 기준으로 기존 Snapshot 데이터와 비교
email 또는 address 컬럼 값이 변경되면,
기존 행은 dbt_valid_to에 변경 시각을 기록
새 행을 dbt_valid_from 시각과 함께 삽입
모든 변경 이력은 snapshots.customers_snapshot 테이블에 누적 저장

구성요소 설명

구성 요소
역할
고려 사항
snapshots/
Snapshot SQL 파일 저장 폴더
models 폴더와 별도로 관리
config()
Snapshot 동작 방식 정의
strategyunique_key는 필수
strategy
변경 감지 방식
check(컬럼 비교) / timestamp(갱신 시각 기반)
check_cols
변경 여부를 확인할 컬럼 목록
민감 데이터만 지정하면 불필요한 변경 감지 방지
dbt snapshot
Snapshot 실행 명령
주기적으로 실행해야 이력 축적 가능

5. Materializations — 저장 전략 선택

Materialization은 모델 실행 결과를 어떤 형태로 데이터베이스에 저장할지를 결정하는 방법입니다. dbt에서는 모델을 SQL로 작성하더라도, 그 결과를 View, Table, Incremental, Ephemeral 중 원하는 형태로 만들 수 있습니다. 즉, "쿼리 결과를 어떻게 보관할지"를 설정하는 단계입니다.

주요 Materialization 유형과 특징

유형
특징
장점
단점
활용 예시
view
쿼리 정의만 저장, 데이터는 즉시 조회
항상 최신 데이터 반영
조회 시 매번 쿼리 실행
경량 변환, Staging 레이어
table
쿼리 실행 결과를 물리 테이블로 저장
빠른 조회 속도
변경 시 전체 재생성 필요
집계, 마트(Mart) 모델
incremental
새 데이터만 추가/갱신
대규모 데이터 처리에 효율적
증분 조건 관리 필요
이벤트 로그, Append-only 데이터
ephemeral
물리 저장 없이 다른 모델에 인라인
중간 계산 용도에 최적
단독 조회 불가
복잡한 파이프라인 내부 조인

예시 모델

1.
view
-- models/stg_orders.sql {{ config(materialized='view') }} select order_id, customer_id, cast(order_ts as timestamp) as order_time from {{ source('raw', 'orders') }}
SQL
복사
2.
table
-- models/fct_orders.sql {{ config(materialized='table') }} select order_id, customer_id, sum(amount) as total_amount from {{ ref('stg_orders') }} group by order_id, customer_id
SQL
복사
3.
incremental
-- models/inc_orders.sql {{ config( materialized='incremental', unique_key='order_id' ) }} select order_id, customer_id, sum(amount) as total_amount from {{ source('raw', 'orders') }} {% if is_incremental() %} where order_ts > (select max(order_time) from {{ this }}) {% endif %} group by order_id, customer_id
SQL
복사

예시 설명

stg_orders
원본 데이터를 변환한 뷰(View) 생성 → 항상 최신 데이터 반영
fct_orders
집계 결과를 테이블(Table)로 저장 → 실행 시 전체 재생성
inc_orders
증분(Incremetal) 방식 → 새로 들어온 데이터만 추가 처리

구성요소 설명

구성 요소
역할
초보자 주의 포인트
config(materialized=...)
Materialization 지정
기본값은 view
ref()
다른 모델 참조
ref를 쓰면 실행 순서 자동 관리
is_incremental()
증분 실행 시 True
증분 조건을 명확히 작성해야 함
this
현재 모델의 DB 객체 참조
증분 비교 시 유용

6. Tests — 데이터 품질 보장

dbt의 Tests는 모델이 만든 결과가 기대하는 조건을 충족하는지 자동으로 검증하는 기능입니다. 데이터 변환이 아무리 복잡해도, 품질이 담보되지 않으면 신뢰할 수 없습니다. dbt는 SQL 기반으로 작성한 규칙을 실행해, 오류나 결측 데이터를 사전에 발견하도록 도와줍니다.

예시1 - 기본 테스트 (Not Null & Unique)

# models/core/customers.yml version: 2 # dbt YAML 메타데이터 스키마 버전 models: # 테스트를 적용할 모델 목록 - name: customers description: "고객 정보 테이블" columns: - name: customer_id description: "고유 고객 식별자" tests: # dbt 내장 테스트 키워드 (별도 SQL 작성 없이 사용 가능) - not_null # 모든 customer_id가 반드시 존재해야 함 - unique # 중복된 customer_id가 없어야 함
YAML
복사

예시2 - 커스텀 조건 테스트

-- tests/positive_order_amount.sql select * from {{ ref('orders') }} # 테스트 대상 모델 참조 where amount <= 0 # 주문 금액이 0 이하인 경우를 실패 조건으로 지정 #쿼리 결과가 한 행이라도 있으면 테스트 실패로 처리
SQL
복사

예시 설명

내장 테스트
YAML에서 짧게 정의
null, unique, accepted_values 등 기본 품질 규칙 빠르게 적용
커스텀 테스트
SQL 파일로 직접 작성
비즈니스 규칙(예: 주문 금액 양수, 날짜 범위 제한 등) 반영 가능

7. Documentation — 지식의 공유와 계보 추적

dbt의 Documentation 기능은 단순한 주석을 넘어, 데이터 모델, 컬럼, 소스의 의미와 의도를 체계적으로 기록하고 데이터 계보(Lineage)를 자동으로 시각화합니다. 이 덕분에 새로운 팀원이 합류하거나, BI 분석가가 쿼리를 작성할 때도 “이 데이터가 어디서 왔고, 어떻게 가공됐는지”를 한눈에 파악할 수 있습니다.

예시1 - 모델 및 컬럼 문서화

# models/core/orders.yml # 이 정보는 dbt docs generate 시 HTML 문서로 변환되어 검색 가능 version: 2 models: - name: orders # description -> 모델 또는 컬럼의 의미, 가공 방식, 주의사항 기록 description: "고객 주문 내역 테이블. 원본 데이터는 raw.orders에서 가져와 가공." columns: # 각 컬럼별 설명을 개별적으로 추가 - name: order_id description: "고유 주문 식별자" - name: customer_id description: "주문한 고객의 ID" - name: order_date description: "주문이 생성된 날짜" - name: total_amount description: "주문 총 금액(할인, 세금 포함)"
YAML
복사

예시2 - 소스(Source) 문서화

# models/staging/stg_sources.yml # 원본 테이블의 역할과 생성 주기 등도 함께 기재 가능 version: 2 sources: # 외부/원본 데이터에 대한 설명을 추가 - name: raw description: "원본 데이터베이스 스키마" tables: - name: orders description: "주문 원본 테이블 (운영 DB에서 추출)"
YAML
복사

문서 생성과 계보 확인

dbt docs generate # 문서 파일 생성 dbt docs serve # 로컬 웹 서버로 문서 확인
Bash
복사

예시 설명

데이터 맥락(Context) 보존
수개월 후에도 “이 컬럼이 왜 이렇게 계산됐는지” 이해 가능
협업 속도 향상
데이터 정의서를 별도로 작성·관리할 필요 없이, dbt 코드와 함께 버전 관리
데이터 계보 추적
ETL 파이프라인을 블랙박스처럼 쓰지 않고, 데이터 흐름을 투명하게 공개

구성요소 간 연결 흐름

flowchart LR
    A[Sources<br/>원본 데이터] --> B[(Seeds<br/>CSV 참조 데이터)]
    A --> C[Staging Models<br/>표준화 변환]
    B --> C
    C --> D[Core Models<br/>비즈니스 로직]
    D --> E[Mart Models<br/>최종 분석 테이블]
    A --> F[Snapshots<br/>변경 이력]
    
    classDef source fill:#E3F2FD,stroke:#1565C0,stroke-width:1px;
    classDef seed fill:#FFF3E0,stroke:#EF6C00,stroke-width:1px;
    classDef staging fill:#E8F5E9,stroke:#2E7D32,stroke-width:1px;
    classDef core fill:#F3E5F5,stroke:#6A1B9A,stroke-width:1px;
    classDef mart fill:#FCE4EC,stroke:#AD1457,stroke-width:1px;
    classDef snapshot fill:#FFFDE7,stroke:#FBC02D,stroke-width:1px;

    class A source;
    class B seed;
    class C staging;
    class D core;
    class E mart;
    class F snapshot;
Mermaid
복사

Sources — 시작점

외부 또는 원본 데이터베이스의 테이블/뷰
ETL에서 Extract 단계에 해당
ex) 운영 DB의 orders 테이블

Seeds — 보조 참조 데이터

CSV 파일을 코드로 관리하고 DB에 로드
외부 시스템 호출 없이, 변환 시 참조할 고정 데이터 제공
ex) 국가 코드 매핑표, 카테고리 정의

Staging Models — 원본 데이터 표준화

소스 데이터를 그대로 쓰지 않고 타입 변환, 컬럼명 표준화, 불필요 컬럼 제거
모든 변환의 출발점 → 이후 모델들이 안정적으로 참조 가능
ex) stg_orders.sql (order_ts → timestamp 변환)

Core Models — 비즈니스 로직 반영

도메인별 핵심 지표, 집계, 가공 로직 적용
분석에서 직접 활용 가능한 중간 데이터 세트
ex) 월별 매출 집계, 고객 생애 가치(LTV) 계산

Mart Models — 최종 분석/리포트용

BI, 대시보드, 리포팅 툴에서 바로 쓸 수 있는 형태
ex) 마케팅 팀용 퍼널 분석 테이블

Snapshots — 변경 이력 축적

Slowly Changing Dimensions(SCD) 관리
소스 데이터의 값이 변할 때, 이전 상태를 보존
ex) 고객 주소 변경 이력

Materializations — 저장 전략

모델 실행 결과를 Table / View / Incremental / Ephemeral 중 선택
성능·비용·데이터 신선도 요구사항에 맞게 조정

Tests · Documentation — 품질과 이해도 보장

Tests: null, unique, foreign key 등 데이터 무결성 검증
Documentation: 모델·컬럼·소스 설명과 계보(Lineage) 자동 생성

마무리

이번 글에서는 dbt의 7대 핵심 구성요소를 하나씩 살펴보며, 각 요소가 데이터 파이프라인 속에서 어떤 역할을 하는지 구체적으로 알아봤습니다. Sources로 시작해 Documentation까지 이어지는 흐름을 이해하면, 단순 쿼리 관리 이상의 구조적이고 재사용 가능한 데이터 모델링을 설계할 수 있습니다.
다음 글에서는 이러한 모델과 파이프라인이 안정적으로 운영되도록 보장하는 데이터 품질 관리에 도움이 되는 테스트 기능을 자세히 알아보겠습니다.