남는건 기록뿐

[Databricks] Silver Layer에서 dbt Incremental과 Materialized View 비교: 장단점과 비용 전략 본문

Databricks

[Databricks] Silver Layer에서 dbt Incremental과 Materialized View 비교: 장단점과 비용 전략

기록합시다 2026. 8. 25. 13:28
반응형
Databricks Silver Layer에서 dbt Incremental과 Materialized View 비교: 장단점과 비용 전략

Databricks의 Silver Layer를 설계할 때 흔히 다음과 같은 질문을 받는다.

Silver 데이터는 dbt로 물리 테이블을 만들어야 할까, 아니면 Materialized View로 구성해야 할까?

하지만 이 질문에는 서로 다른 두 개념이 섞여 있다.

  • dbt는 SQL 변환 코드를 개발·테스트·문서화·배포하는 프레임워크다.
  • **Materialized View(MV)**는 SQL 결과를 물리적으로 저장하고 Databricks가 새로고침하는 데이터 객체다.

따라서 dbt와 MV는 완전히 배타적인 선택지가 아니다. 최신 dbt-databricks Adapter는 table, incremental뿐 아니라 materialized_view도 지원한다. dbt 프로젝트 안에서 Databricks MV의 정의, 의존성, Schedule과 주요 설정을 관리할 수 있다.

실제 설계 질문은 다음에 가깝다.

Silver 모델을 dbt Incremental Delta Table로 직접 변경 처리할 것인가, 아니면 dbt가 정의한 Materialized View의 관리형 Refresh에 맡길 것인가?

이 글에서는 두 방식을 데이터 정합성, 변경 이력, 재처리, 개발 생산성, 운영 복잡도와 비용 관점에서 비교하고, SAP·MES·IoT·Master Data와 같은 구체적인 상황에서 무엇을 선택해야 하는지 정리한다.

이 글은 2026년 8월 Databricks와 dbt 공식 문서를 기준으로 작성했다. dbt-databricks 버전과 Databricks Runtime·SQL Warehouse·Serverless 지원 범위에 따라 사용할 수 있는 설정이 다르므로 적용 전 현재 환경을 확인해야 한다.


1. Silver Layer의 역할부터 다시 정의하자

Silver는 Bronze 데이터를 단순히 보기 좋게 바꾸는 계층이 아니다. 여러 Gold Mart와 데이터 제품이 공통으로 사용할 수 있도록 원천 데이터의 의미와 품질을 표준화하는 계층이다.

Silver에서는 보통 다음 작업이 수행된다.

  • 데이터 타입과 날짜·시간대 표준화
  • 중복 제거와 Business Key 확정
  • Insert·Update·Delete 반영
  • 코드와 단위 변환
  • 비정상 데이터 검증·격리
  • 여러 원천 간 기본 Enrichment
  • 변경 시각·적재 시각·원천 식별자 보존
  • 개인정보 제거 또는 접근 정책 적용

Silver의 핵심은 조회 속도만이 아니다. 같은 원천을 다시 처리해도 동일한 결과를 만들 수 있는지, 늦게 도착한 데이터와 삭제를 반영할 수 있는지, 오류가 생겼을 때 특정 범위만 복구할 수 있는지가 더 중요하다.

따라서 도구 선택 전 다음 질문에 답해야 한다.

  1. 각 행을 한 번만 처리해야 하는가?
  2. 원천에 Update와 Delete가 있는가?
  3. 변경 이력과 SCD가 필요한가?
  4. 전체 원천을 다시 계산할 수 있는가?
  5. 업무 Key와 증분 기준을 명확히 알고 있는가?
  6. 데이터 정합성이 실시간성보다 중요한가?
  7. 결과가 여러 Gold Model에서 반복 사용되는가?

2. dbt와 Materialized View는 무엇이 다른가?

dbt: 변환 생명주기를 관리하는 프레임워크

dbt는 SELECT 중심의 모델을 Compile해 Databricks에서 실행한다. dbt 자체가 데이터를 저장하는 것은 아니며, Model의 Materialization 설정에 따라 Table, View, Incremental Table, Materialized View 등을 생성한다.

dbt의 핵심 가치는 다음과 같다.

  • Git 기반 Version Control과 Code Review
  • ref() 기반 의존성 DAG
  • 재사용 가능한 Macro와 Package
  • Test, Documentation, Source Freshness
  • 개발·검증·운영 환경 분리
  • CI/CD와 선택적 실행
  • Model Owner와 Description 관리

Databricks 공식 문서도 dbt를 데이터를 Extract·Load하는 도구가 아니라, 이미 적재된 데이터를 변환하는 Transform after Load 환경으로 설명한다.

Materialized View: 결과와 Refresh를 관리하는 Databricks 객체

Materialized View는 정의 SQL의 결과를 물리적으로 저장한다. 원천이 변경되면 Schedule, TRIGGER ON UPDATE, 수동 REFRESH 등을 통해 결과를 최신화한다.

가능한 경우 Databricks가 변경분만 증분 처리하지만, 증분 처리가 불가능하거나 Full Recompute가 더 저렴하다고 판단되면 전체 결과를 다시 계산할 수 있다.

Standalone MV를 생성하면 각 MV를 관리하는 Serverless Pipeline이 자동으로 만들어진다. SQL Warehouse는 생성·Refresh 요청을 조정하지만 실제 Refresh Compute와 비용은 별도의 Serverless Lakeflow Pipeline에서 발생한다.

정확한 비교 구조

flowchart LR
          A["dbt Project"] --> B{"Materialization"}
          B --> C["table · incremental"]
          B --> D["view"]
          B --> E["materialized_view"]
          C --> F["Delta Physical Table"]
          D --> G["Logical View"]
          E --> H["Databricks MV"]

그림 1. dbt는 MV와 경쟁하는 저장 객체가 아니라 Table·Incremental·View·MV를 정의하고 배포하는 상위 개발 계층이다.

즉, dbt는 MV의 반대편에 있는 것이 아니라 MV까지 관리할 수 있는 상위 개발·배포 계층이다.


3. 비교 대상 1: dbt Incremental Delta Table

dbt Incremental Model은 첫 실행에서 Delta Table을 만든 뒤, 이후 실행에서는 조건에 해당하는 데이터만 MERGE, APPEND, REPLACE WHERE 등의 전략으로 반영한다.

기본 예시

{{
  config(
    materialized='incremental',
    incremental_strategy='merge',
    unique_key='inspection_id',
    file_format='delta',
    liquid_clustered_by=['plant_code', 'inspection_date'],
    on_schema_change='sync_all_columns'
  )
}}

with source_data as (
  select
    inspection_id,
    plant_code,
    barcode,
    cast(inspection_ts as timestamp) as inspection_ts,
    cast(inspection_ts as date) as inspection_date,
    result_code,
    updated_at,
    current_timestamp() as loaded_at
  from {{ ref('stg_mes_inspection') }}

  {% if is_incremental() %}
    where updated_at >= (
      select coalesce(
        max(updated_at) - interval 2 days,
        timestamp '1900-01-01 00:00:00'
      )
      from {{ this }}
    )
  {% endif %}
)

select * from source_data

dbt-databricks에서 Delta Incremental Model의 기본 전략은 merge다. 그 밖에도 append, insert_overwrite, replace_where, delete+insert, microbatch 등을 제공한다.

주요 Incremental 전략

전략 적합한 상황 주의점
append 수정 없는 Insert-only Event Update·Delete 미지원, 중복 위험
merge Key 기반 Upsert Key 품질과 Target Scan 비용 중요
replace_where 일자·공장 등 범위 재계산 해당 범위 전체를 정확히 다시 조회해야 함
insert_overwrite Partition·Cluster 단위 교체 잘못된 범위가 정상 데이터를 덮을 수 있음
delete+insert Key 일괄 교체가 단순한 경우 Delete와 Insert 비용 발생
microbatch Event Time 기반 대용량 시계열 Late Arrival과 Batch Window 설계 필요

장점

1) 변경 의미를 명시적으로 통제할 수 있다

어떤 Key로 Match하고, 어느 기간을 다시 읽고, Delete를 어떻게 반영할지 코드로 명확히 정의할 수 있다.

2) 이력과 재처리에 유리하다

SCD Type 2, 적재 Batch ID, 원천 수정 시각, Soft Delete 등 업무별 변경 규칙을 직접 구현할 수 있다. 특정 일자·공장·법인만 선택적으로 재처리하기도 쉽다.

3) 테스트와 배포 체계가 강하다

Model SQL, Test, Documentation과 의존성을 같은 Repository에서 관리할 수 있다. Pull Request 단계에서 Compile과 Test를 수행하고 변경 영향을 확인할 수 있다.

4) 물리 최적화 제어가 가능하다

Liquid Clustering, Table Property, Tag, OPTIMIZE 실행 여부 등을 Model 설정으로 관리할 수 있다.

5) 처리 비용을 예측하기 쉽다

증분 Window와 Target Predicate를 직접 정의하기 때문에 매 실행에서 어느 범위를 읽고 쓸지 비교적 명확하다. Full Refresh도 운영자가 선택한 시점에 수행할 수 있다.

단점

  • 잘못된 unique_key와 증분 조건이 중복·누락을 만든다.
  • Delete, Late Arrival, 동일 Timestamp를 직접 처리해야 한다.
  • Model마다 Incremental Logic이 달라지면 유지보수가 어려워진다.
  • MERGE가 Target의 넓은 범위를 Scan하면 예상보다 비용이 커진다.
  • Logic 변경 시 과거 전체를 다시 처리해야 하는지 개발자가 판단해야 한다.
  • Test와 Documentation도 별도의 실행 Compute와 운영 절차가 필요하다.

4. 비교 대상 2: Databricks Materialized View

MV에서는 결과를 정의하는 SQL에 집중하고 변경 추적·결과 갱신은 Databricks에 맡긴다.

Databricks SQL 예시

CREATE OR REPLACE MATERIALIZED VIEW analytics_silver.mv_valid_inspection
COMMENT '유효한 MES 검사 결과 Silver 모델'
REFRESH POLICY AUTO
TRIGGER ON UPDATE AT MOST EVERY INTERVAL 15 MINUTES
AS
SELECT
  inspection_id,
  plant_code,
  barcode,
  CAST(inspection_ts AS TIMESTAMP) AS inspection_ts,
  result_code,
  updated_at
FROM analytics_bronze.mes_inspection
WHERE inspection_id IS NOT NULL
  AND barcode IS NOT NULL;

dbt가 MV를 관리하는 예시

dbt-databricks에서는 다음처럼 MV를 Model로 정의할 수 있다.

{{
  config(
    materialized='materialized_view',
    schedule={
      'on_update': true,
      'at_most_every': '15 MINUTES'
    },
    liquid_clustered_by=['plant_code', 'inspection_date'],
    databricks_tags={
      'layer': 'silver',
      'domain': 'quality',
      'cost_center': 'data_platform'
    }
  )
}}

select
  inspection_id,
  plant_code,
  barcode,
  cast(inspection_ts as timestamp) as inspection_ts,
  cast(inspection_ts as date) as inspection_date,
  result_code,
  updated_at
from {{ ref('mes_inspection_bronze') }}
where inspection_id is not null
  and barcode is not null

schedule.on_update, schedule.every, liquid_clustered_by 등은 Adapter 버전별 지원 범위가 다르다. 예를 들어 on_update와 every Schedule은 dbt-databricks v1.12 이상에서 지원된다.

장점

1) Incremental Logic을 직접 작성하지 않아도 된다

개발자는 최종 결과 Query를 선언하고, Databricks가 지원되는 경우 변경된 결과만 갱신한다. 복잡한 MERGE 코드와 Watermark 관리가 줄어든다.

2) Late Arrival과 Dimension 변경에 강하다

MV는 Refresh 시점의 Batch Query와 동일한 정확한 결과를 제공한다. 늦게 도착한 행이나 Dimension 수정으로 기존 Join 결과가 달라져야 할 때, Streaming 방식보다 사고 모델이 단순하다.

3) 반복되는 Join과 계산 결과를 재사용할 수 있다

결과가 물리적으로 저장되므로 여러 Gold Model이 동일한 Silver Enrichment를 반복 계산하지 않는다.

4) 선언형 Schedule과 Refresh를 사용할 수 있다

시간 Schedule, TRIGGER ON UPDATE, 수동 Refresh를 객체 정의에 포함할 수 있다. Standalone MV의 Backing Pipeline은 Databricks가 관리한다.

5) dbt와 결합하면 개발 거버넌스를 유지할 수 있다

MV를 dbt Model로 관리하면 ref(), Git, Test, Documentation과 CI/CD를 그대로 활용하면서 실행은 Databricks의 관리형 Refresh에 맡길 수 있다.

단점

1) 항상 증분 처리되는 것은 아니다

Query 구조, Source 유형, 변경량과 비용 모델에 따라 Full Recompute가 발생할 수 있다. AUTO는 증분 가능 여부뿐 아니라 어느 방식이 더 저렴한지도 판단한다.

2) 한 번만 처리해야 하는 Ingestion에는 부적합하다

Kafka·Kinesis·Auto Loader처럼 Record를 한 번씩 소비해야 하거나 원천의 과거 데이터가 사라지는 경우에는 Streaming Table이 적합하다.

3) 직접 DML과 세밀한 변경 제어가 어렵다

MV 결과에 직접 MERGE, UPDATE, DELETE할 수 없다. SCD Type 2, 복잡한 Delete Rule과 감사 이력을 직접 제어해야 한다면 일반 Delta Table이 유리하다.

4) Serverless 비용과 실행 방식이 분리되어 있다

SQL Warehouse에서 명령을 제출해도 실제 Refresh는 별도 Serverless Pipeline에서 실행된다. Warehouse 크기를 줄였다고 MV Refresh 비용이 같이 줄어드는 것은 아니다.

5) dbt 설정 변경이 재생성을 유발할 수 있다

현재 dbt-databricks에서는 MV의 Schedule 변경을 제외한 주요 Configuration 변경 시 Drop·Recreate가 필요할 수 있다. 대형 Silver MV라면 작은 설정 변경도 전체 재생성과 비용 증가로 이어질 수 있다.

6) 운영 객체가 이중으로 보일 수 있다

dbt DAG뿐 아니라 Databricks의 MV Backing Pipeline과 Refresh History도 모니터링해야 한다. dbt Run 성공만으로 MV Refresh 방식과 비용까지 확인했다고 볼 수 없다.

flowchart LR
          A["MV Refresh 요청"] --> B{"원천 변경이 있는가?"}
          B -->|아니오| C["No Change"]
          B -->|예| D{"증분 Refresh가 지원되고 효율적인가?"}
          D -->|예| E["Incremental Refresh"]
          D -->|아니오| F["Full Recompute"]
          C --> G["Refresh History 확인"]
          E --> G
          F --> G

그림 2. AUTO Refresh는 증분 가능 여부뿐 아니라 비용 효율까지 고려하므로 실제 처리 방식을 Refresh History에서 확인해야 한다.


5. dbt Incremental과 MV 직접 비교

비교 항목 dbt Incremental Delta Table Materialized View
핵심 책임 개발자가 변경 처리 정의 Databricks가 Refresh 관리
데이터 저장 Delta Table 관리형 결과 저장
증분 기준 is_incremental(), Key, Predicate Query·Source 변경 추적과 비용 모델
Update·Delete 직접 통제 가능 Query 결과 기준 자동 반영 가능
SCD Type 2 적합 일반적으로 부적합
Late Arrival Lookback·재처리 직접 구현 Batch 정합성 기준으로 반영
Full Recompute 개발자·운영자가 결정 시스템이 선택할 수 있음
직접 DML 가능 불가능
재처리 범위 Table·Partition·Key 단위 제어 Refresh 또는 Full Refresh 중심
테스트·문서화 dbt 기본 기능 활용 dbt로 정의하면 동일하게 활용 가능
물리 최적화 세밀한 제어 일부 설정 가능, 유지 관리는 시스템 중심
실행 Compute dbt가 연결한 Warehouse·Job Compute Serverless Lakeflow Pipeline
비용 예측성 증분 범위가 명확하면 높음 Full Recompute 발생 시 변동 가능
운영 난이도 코드 복잡도 높음 코드 단순, Refresh 모니터링 필요
적합한 Silver Core Entity·CDC·이력 재계산 가능한 Enrichment·Join·정제 결과

6. 비용 관점에서 비교하기

비용을 DBU나 저장 용량 하나로 비교하면 잘못된 결론을 내리기 쉽다. Silver 모델의 총비용은 다음과 같이 봐야 한다.

총비용 = 변환·Refresh Compute
       + 읽기·쓰기·Shuffle 비용
       + Storage와 내부 상태
       + Test·CI·Maintenance 비용
       + 사용자 Query 비용
       + 개발·운영 인건비
       + 장애·재처리 위험 비용

dbt Incremental의 비용 구조

직접 비용

  • dbt Model SQL을 실행하는 SQL Warehouse 또는 Job Compute
  • Source 증분 범위 Scan
  • Delta MERGE의 Target 탐색과 Rewrite
  • Full Refresh 시 전체 Source 재계산과 Target 교체
  • Test Query와 Source Freshness 실행
  • 필요에 따른 OPTIMIZE, Maintenance
  • Delta 결과 저장

간접 비용

  • Incremental Predicate와 Key 설계
  • 중복·누락·Delete 처리 개발
  • Schema 변경과 Backfill 대응
  • 실패한 Batch의 구간 재처리
  • Macro·Package·Adapter 버전 관리

비용이 낮아지는 조건

  • 일 변경량이 전체 데이터에 비해 작다.
  • unique_key와 변경 시각이 정확하다.
  • Liquid Clustering으로 MERGE Target을 잘 Pruning할 수 있다.
  • Lookback Window가 작고 Late Arrival 범위가 제한적이다.
  • 여러 Model을 같은 dbt Run과 Compute에 효율적으로 묶을 수 있다.
  • CI에서 변경된 Model과 하위 의존성만 선택적으로 실행한다.

비용이 커지는 조건

  • 매 실행마다 넓은 기간을 다시 읽는다.
  • MERGE Key와 물리 배치가 맞지 않아 Target 전체를 Scan한다.
  • 작은 Model을 지나치게 많이 만들어 Query·Startup Overhead가 누적된다.
  • 모든 Test를 매 실행마다 Full Scan한다.
  • 빈번한 --full-refresh가 발생한다.
  • dbt가 매 실행 후 OPTIMIZE를 수행하고 별도로 Predictive Optimization도 켜 중복 Maintenance가 발생한다.

Materialized View의 비용 구조

직접 비용

  • 생성·Refresh를 수행하는 Serverless Lakeflow Pipeline DBU
  • 증분 Refresh 시 변경 추적과 결과 반영
  • Full Recompute 시 전체 Source Scan·Shuffle·결과 재작성
  • Materialized 결과와 Incremental Refresh용 내부 상태 저장
  • MV를 조회하는 Consumer Compute

간접 비용

  • Incrementalization 가능 여부 분석
  • Full Recompute 원인 모니터링
  • Backing Pipeline과 Schedule 관리
  • Configuration 변경에 따른 재생성 검토
  • dbt Run과 Databricks Schedule의 Refresh Owner 조정

비용이 낮아지는 조건

  • Source가 Delta이고 Row Tracking이 활성화되어 있다.
  • Query가 증분 처리 가능한 연산으로 구성된다.
  • 변경량이 작고 결과가 여러 하위 Model에서 반복 사용된다.
  • 복잡한 Join·Aggregate를 Consumer마다 다시 계산하지 않는다.
  • TRIGGER ON UPDATE에 AT MOST EVERY를 적용해 잦은 Refresh를 제한한다.
  • Full Recompute가 발생해도 감당 가능한 데이터 규모다.

비용이 커지는 조건

  • Source에 Row Tracking이 없거나 지원되지 않는 연산이 많다.
  • 변경량이 커서 비용 모델이 Full Recompute를 자주 선택한다.
  • 외부 Foreign Catalog를 원천으로 사용해 증분 Refresh가 불가능하다.
  • Source Table 전체가 매우 크고 Refresh 주기가 짧다.
  • Standalone MV가 과도하게 늘어 Pipeline과 Refresh가 파편화된다.
  • dbt Run과 MV 자체 Schedule이 모두 Refresh를 요청한다.

가장 중요한 비용 차이

dbt Incremental은 개발자가 Scan 범위를 잘못 설계하면 비용이 커진다. MV는 개발 코드가 단순하더라도 Databricks가 Full Recompute를 선택하면 비용이 커질 수 있다.

dbt Incremental의 비용 위험 = 잘못된 Predicate·Key·MERGE 설계

Materialized View의 비용 위험 = 증분화 실패·변경량 증가·Full Recompute

즉, dbt Incremental은 설계 통제력과 비용 예측성을 얻는 대신 개발 복잡도를 부담한다. MV는 개발 단순성과 관리형 최적화를 얻는 대신 실행 방식의 변동성을 수용한다.

단순 계산 예시

전체 Silver Source가 5TB이고 하루 변경량이 50GB라고 가정해 보자.

방식 정상 증분 실행 비정상·전체 재계산 시
dbt Incremental Source 50GB와 관련 Target 범위 처리 운영자가 5TB Full Refresh 수행
MV Incremental 변경 추적이 지원되면 영향 범위 처리 시스템 판단 또는 제약으로 5TB 재계산 가능
일반 View 저장·Refresh 없음 Consumer 조회마다 원천 계산 반복

실제 비용은 Join, Shuffle, File Rewrite, Warehouse·Serverless SKU와 실행 시간에 따라 달라진다. 이 표의 목적은 가격을 계산하는 것이 아니라 변경량과 전체량의 비율, Refresh 빈도, Consumer 재사용 횟수가 핵심 변수라는 점을 보여주는 것이다.

dbt 라이선스 비용도 분리해서 본다

dbt Core 자체와 dbt Cloud·Platform의 비용 구조는 다르다. 조직은 다음을 별도로 비교해야 한다.

  • dbt Cloud·Platform 라이선스와 사용자 수
  • dbt Core를 직접 운영하는 CI/CD·Scheduler·Artifact Hosting 비용
  • Databricks Job·Warehouse Compute
  • MV Serverless Pipeline 비용

dbt Core가 소프트웨어 라이선스 측면에서 무료라고 해도 운영 인프라와 엔지니어링 비용이 0인 것은 아니다.


7. MV 비용을 낮추기 위한 Source 설정

Delta Source에서 MV 증분 Refresh를 최대한 활용하려면 Row Tracking, Deletion Vector, Change Data Feed를 검토한다.

ALTER TABLE analytics_bronze.mes_inspection
SET TBLPROPERTIES (
  delta.enableDeletionVectors = true,
  delta.enableRowTracking = true,
  delta.enableChangeDataFeed = true
);

MV 생성 전 Query가 구조적으로 증분 처리 가능한지 확인한다.

EXPLAIN CREATE MATERIALIZED VIEW analytics_silver.mv_valid_inspection
AS
SELECT
  inspection_id,
  plant_code,
  barcode,
  CAST(inspection_ts AS DATE) AS inspection_date,
  result_code
FROM analytics_bronze.mes_inspection
WHERE inspection_id IS NOT NULL;

EXPLAIN이 증분 가능하다고 해도 REFRESH POLICY AUTO에서는 변경량과 비용 모델에 따라 Full Recompute가 선택될 수 있다. 비용 폭증보다 Refresh 실패가 낫다면 INCREMENTAL STRICT를 검토할 수 있지만, 그 경우 실패 대응 Runbook이 필요하다.

CREATE OR REPLACE MATERIALIZED VIEW analytics_silver.mv_valid_inspection
REFRESH POLICY INCREMENTAL STRICT
AS
SELECT ...;

8. dbt와 MV를 함께 사용할 때의 핵심 운영 전략

1) dbt를 Source of Truth로 정한다

dbt로 MV를 관리한다면 Workspace에서 수동으로 Query와 Schedule을 변경하지 않는다. dbt Model과 실제 객체 정의가 달라지면 다음 배포에서 설정이 되돌아가거나 재생성될 수 있다.

2) Refresh Owner를 하나만 둔다

다음 중 하나를 선택한다.

  • dbt·Lakeflow Jobs가 순서를 통제하며 수동 REFRESH
  • MV의 SCHEDULE EVERY
  • MV의 TRIGGER ON UPDATE

중복 Schedule은 동일 데이터를 불필요하게 다시 처리할 수 있다.

특히 dbt Adapter의 cron Schedule은 dbt Run 때 수동 Refresh를 요청한다. 반면 v1.12 이상의 every와 on_update는 Databricks가 Refresh를 관리하고, 변경 없는 dbt 재실행에서 별도 수동 Refresh를 요청하지 않는다. 운영 방식에 맞는 Mode를 선택해야 한다.

3) dbt Test와 MV Refresh 순서를 맞춘다

MV Refresh가 비동기로 실행되는데 바로 dbt Test가 시작되면 이전 결과를 검사할 수 있다. 하위 Model이 즉시 결과를 사용해야 한다면 동기 Refresh 또는 Job Dependency로 완료를 보장한다.

4) Model 변경이 Drop·Recreate를 유발하는지 확인한다

대형 MV의 설정과 Query를 변경하기 전에 예상 동작과 재생성 비용을 확인한다. 개발 환경에서 먼저 dbt compile, Diff와 실행 계획을 검증한다.

5) 비용 Tag를 표준화한다

databricks_tags={
  'layer': 'silver',
  'domain': 'manufacturing',
  'owner': 'data_platform',
  'cost_center': 'dt'
}

dbt Query는 Model·Run 기준으로, MV는 system.billing.usage의 MV·Pipeline Metadata 기준으로 비용을 추적한다. SQL Warehouse Tag는 MV Serverless Refresh Billing Record로 전달될 수 있으며, 객체 Tag는 information_schema.table_tags와 Billing Table을 결합해 분석할 수 있다.


9. Silver 상황별 권장 방식

상황 1. 대용량 MES 검사 데이터의 Upsert

특성

  • 시간 단위로 데이터가 추가·수정된다.
  • inspection_id 또는 업무 Key가 있다.
  • 공장·시간 범위 재처리가 필요하다.
  • 삭제와 오류 정정 이력을 관리해야 한다.

권장: dbt Incremental merge 또는 replace_where

변경 범위와 재처리를 직접 통제하는 편이 안전하다. 공장·일자별 Gold KPI는 하위 MV로 집계할 수 있다.

상황 2. 제품·공장 Master의 현재 상태 정제

특성

  • 데이터가 비교적 작다.
  • 현재 상태만 필요하다.
  • 수정 시 과거 결과도 현재 기준으로 다시 계산되어야 한다.

권장: dbt-managed MV

간단한 Query로 정확한 현재 상태를 유지할 수 있고 Full Recompute 위험도 제한적이다. 과거 Master 이력이 필요하다면 dbt Incremental 또는 AUTO CDC 기반 SCD Type 2가 적합하다.

상황 3. SAP Transaction과 Master Enrichment

특성

  • Bronze Delta끼리 Join한다.
  • Master 변경 시 기존 Transaction의 표현도 바뀌어야 한다.
  • 결과를 여러 Gold Model이 재사용한다.

권장: MV 우선 검토

Batch Query 정합성과 결과 재사용의 이점이 크다. 단, 전체 Transaction이 매우 크고 Full Recompute가 SLA를 위협하면 dbt Incremental Table로 변경 범위를 직접 통제한다.

상황 4. SCD Type 2 고객·제품 이력

특성

  • 유효 시작·종료 시각이 필요하다.
  • 변경 순서와 중복 제거가 중요하다.
  • 과거 시점 기준 분석이 필요하다.

권장: dbt Incremental 또는 Lakeflow AUTO CDC

MV는 현재 Query 결과를 유지하는 데는 편리하지만 SCD 행의 생명주기를 직접 통제하는 용도에는 맞지 않는다.

상황 5. Kinesis·Kafka·Auto Loader Ingestion

특성

  • 이벤트를 한 번씩 처리해야 한다.
  • 원천 Retention 이후 과거 데이터가 사라진다.
  • 낮은 지연이 중요하다.

권장: Streaming Table

dbt Incremental과 MV 중 하나를 억지로 고르지 않는다. Ingestion은 Streaming Table로 처리하고, 그 이후 Silver Enrichment를 dbt Incremental 또는 MV로 구성한다.

상황 6. Federation 원천의 Silver Snapshot

특성

  • 외부 Oracle·PostgreSQL·Data Warehouse를 Foreign Catalog로 조회한다.
  • 데이터가 소규모이고 하루 한 번 결과면 충분하다.

권장: 소규모는 MV, 대규모는 dbt Incremental Ingestion

Foreign Catalog는 MV 증분 Refresh 지원 원천이 아니므로 대규모 Transaction을 MV로 감싸면 Full Recompute 비용이 반복될 수 있다.


10. 권장 Silver Architecture

flowchart LR
          A["Bronze Delta · Streaming Table"] --> B{"변경 의미"}
          B -->|CDC · SCD| C["dbt Incremental Core"]
          B -->|재계산 가능| D["dbt-managed Silver MV"]
          B -->|Insert-only| E["Silver Streaming Table"]
          C --> F["Silver Contract View"]
          D --> F
          E --> F
          F --> G["Gold Data Product"]

그림 3. Silver Core의 변경 처리는 Incremental·Streaming이 담당하고, 재계산 가능한 Enrichment는 MV가 담당한다.

실무에서는 다음 조합이 안정적이다.

  • Silver Core Entity: dbt Incremental 또는 Streaming Table
  • Silver Reusable Enrichment: dbt-managed MV
  • Silver Public Contract: 얇은 View
  • Gold 반복 집계: MV

Silver Core는 변경 이력과 재처리를 책임지고, MV는 결과 재사용과 선언형 Refresh에 집중한다.


11. 의사결정 체크리스트

flowchart LR
          A["Silver 모델 요구사항"] --> B{"Insert-only · Low Latency?"}
          B -->|예| C["Streaming Table"]
          B -->|아니오| D{"CDC · SCD · 부분 재처리?"}
          D -->|예| E["dbt Incremental"]
          D -->|아니오| F{"원천 보존 · 전체 재계산 가능?"}
          F -->|예| G["dbt-managed MV"]
          F -->|아니오| E

그림 4. 선택의 핵심은 도구 선호가 아니라 변경 의미, 재처리 요구사항, 원천 보존 여부다.

dbt Incremental을 선택한다

Materialized View를 선택한다

Streaming Table을 선택한다


12. 반드시 모니터링해야 할 지표

영역 dbt Incremental Materialized View
실행 Model Duration, Rows Affected Refresh Duration, Status
처리 방식 Incremental·Full Refresh Incremental·Full Recompute·No Change
데이터 Source·Target Watermark Last Refresh Time
비용 Warehouse·Job DBU Serverless Pipeline DBU
Scan Source·Target Scan Bytes Refresh Processed Volume
품질 dbt Test Failure Expectation·dbt Test Failure
물리 구조 File 수, Clustering 상태 시스템 관리 상태와 Query 성능
운영 Retry, Model Failure Backing Pipeline Failure

MV는 성공 여부만 보지 말고 실제 Refresh가 Incremental, Full recompute, No change 중 무엇으로 처리됐는지 확인해야 한다. dbt Incremental도 실행 성공만으로 충분하지 않다. 증분 입력 건수, MERGE 영향 행 수, Source·Target Watermark를 함께 모니터링해야 한다.


13. 자주 발생하는 안티패턴

안티패턴 1. dbt와 MV를 경쟁 도구로 본다

dbt는 MV를 정의하고 배포할 수 있다.

개선: 개발 거버넌스는 dbt, 실행 의미는 Incremental Table·MV·Streaming Table 중 적합한 객체로 분리한다.

안티패턴 2. 모든 Silver Model을 MV로 만든다

CDC·SCD·Ingestion까지 MV에 맡기면 Full Recompute와 이력 손실 위험이 커진다.

개선: Core 변경 처리는 Incremental/Streaming Table, 재계산 가능한 Enrichment는 MV로 분리한다.

안티패턴 3. MV는 항상 증분이라 가정한다

Query와 Source 조건에 따라 전체 재계산될 수 있다.

개선: EXPLAIN CREATE MATERIALIZED VIEW와 실제 Refresh History를 확인한다.

안티패턴 4. dbt Incremental에 unique_key만 지정하면 끝이라고 생각한다

Late Arrival, Delete, 중복 Source Key와 Null Key는 별도 처리가 필요하다.

개선: Lookback, Deduplication, Delete Rule과 Data Test를 함께 설계한다.

안티패턴 5. dbt와 MV Schedule을 중복 운영한다

dbt Run과 MV Schedule이 동일 결과를 연속 Refresh할 수 있다.

개선: Refresh Owner를 하나로 정하고 Schedule Mode별 Adapter 동작을 확인한다.

안티패턴 6. Compute 비용만 비교한다

개발·테스트·재처리·장애 복구 비용을 제외하면 총비용을 왜곡한다.

개선: DBU, Storage, Consumer Query와 운영 인건비를 함께 측정한다.

안티패턴 7. dbt Incremental과 Predictive Optimization을 중복 운영한다

dbt가 매번 OPTIMIZE를 수행하면서 Predictive Optimization도 같은 Table을 관리하면 불필요한 Maintenance 비용이 발생할 수 있다.

개선: skip_optimize 또는 프로젝트 설정을 통해 유지 관리 주체를 하나로 정한다.


14. 최종 권장 전략

Silver Layer의 기본 전략은 다음과 같이 정리할 수 있다.

Silver 데이터 유형 우선 선택
CDC·Upsert·Delete dbt Incremental 또는 Streaming Table
SCD Type 2·감사 이력 dbt Incremental 또는 AUTO CDC
대용량 Insert-only Event Streaming Table
Delta 원천 간 재사용 Join dbt-managed MV
현재 상태 Master dbt-managed MV
소규모 주기적 Snapshot dbt-managed MV
Foreign 대용량 Transaction Delta 증분 적재 후 dbt Incremental
단순 Rename·Projection View 또는 Ephemeral Model

조직 차원의 기본값을 하나 정한다면 다음이 실용적이다.

변경 이력과 재처리를 책임지는 Silver Core는 dbt Incremental·Streaming Table로 만들고, 전체 원천에서 다시 계산 가능한 Join·Enrichment 결과는 dbt-managed Materialized View로 구성한다.

이 방식은 dbt의 Version Control, Test, Documentation을 유지하면서 Databricks MV의 관리형 Incremental Refresh를 선택적으로 활용한다.


15. 결론

dbt와 Materialized View 중 하나만 선택해야 하는 것은 아니다. dbt는 Silver 모델을 개발하고 통제하는 프레임워크이며, MV는 그 모델을 실행·저장하는 하나의 Materialization 방식이다.

핵심 차이는 누가 증분 상태를 책임지는지에 있다.

  • dbt Incremental: 개발자가 Key, Predicate, Merge, 재처리와 비용 범위를 통제한다.
  • Materialized View: Databricks가 변경 추적과 Refresh 방식을 관리하고 개발자는 결과 Query에 집중한다.

비용 관점에서도 절대적인 승자는 없다.

  • 변경량이 작고 Key와 Window가 명확하면 dbt Incremental의 비용 예측성이 높다.
  • 지원되는 Delta Source와 Query에서 결과 재사용이 많으면 MV가 개발·조회·운영 총비용을 낮출 수 있다.
  • Full Recompute가 자주 발생하는 대형 MV는 간단한 코드와 달리 높은 비용을 만들 수 있다.
  • 복잡한 Incremental Logic과 장애 복구에 드는 엔지니어링 비용까지 포함하면 MV가 더 경제적일 수 있다.

따라서 가장 좋은 선택 기준은 다음 한 문장으로 정리할 수 있다.

변경의 의미를 직접 통제해야 하면 dbt Incremental, 결과의 정확한 재계산을 플랫폼에 맡길 수 있으면 dbt-managed MV를 선택한다.


참고 문서

반응형
Comments