Data & AI

ETL vs ELT

meellon 2026. 7. 15. 11:30

학습 목표

ETLELT에서 변환이 일어나는 위치를 설명할 수 있다.

warehouse layering (staging · intermediate · marts)으로 역할을 나눌 수 있다.

dbt가 warehouse 안 SQL DAG·테스트를 담당하는 방식을 설명할 수 있다.

orchestration (Airflow·Dagster)과 transform 엔진역할 분리를 말할 수 있다.

5·6편 Spark 출력을 warehouse 적재연결해 설계할 수 있다.

문제 상황

  • Spark에서 join·집계 후 JDBC bulk load — warehouse는 거의 idle, 재처리는 Spark만 다시
  • 변환된 테이블만 적재 — 원본이 warehouse에 없어 컬럼 추가·replay소스부터 다시
  • Airflow DAG 안에 SQL 200줄의존성·테스트·문서스크립트에 묻힘
  • dbt와 Airflow 둘 다 쓴다는데 — 누가 schedule·누가 transform인지 겹침
  • 5편 gold parquet와 BI Snowflake 테이블 숫자 불일치어느 쪽이 정본인지 없음
  • Kafka Connect sink는 있는데 staging·mart 계층 정의가 없음

이번 편은 process 이후 — 데이터를 warehouse어떻게 넣고 SQL로 다듬는지다. lakehouse 파일 포맷은 8편.

1. Warehouse loading이 파이프라인에서 하는 일

3편 배치·6편 스트림 모두 process까지는 Spark·Kafka. BI·ML·운영 리포트는 대개 warehouse (또는 mart 테이블)를 읽는다.

역할 loading이 해주는 것
정본 집약 여러 소스를 한 곳에서 join·집계
소비자 분리 BI·ML·ops가 동일 mart 참조 — Spark job 직접 의존 감소
거버넌스 PII·권한·계보 — warehouse role·masking
재현 raw 보존 시 정의 변경재실행
Kafka / lake raw  ──►  Spark batch · streaming  ──►  load path  ──►  warehouse  ──►  BI · features
  • 4편 Connect warehouse sinkingest 경로 중 하나
  • 5편 gold/user_day_revenue파일 mart; warehouse 동기 또는 대체 선택
  • 6편 스트림 metric — warehouse 근실시간 테이블 vs 배치 gold 역할 분리
  • ETL — transform이 warehouse 밖; ELTraw load 후 transform이 warehouse 안

2. ETL 흐름

Extract → Transform → Load. 변환적재 전 — Spark·Python·전용 ETL 툴.

단계 설명
Extract 소스에서 읽기 JDBC, S3 export, API
Transform 정제·join·PII 마스킹 PySpark, pandas (소량)
Load 정제된 행만 warehouse COPY, JDBC append
Consume curated dims/facts Looker, notebook
orders (RDS)  ──►  Spark: dedupe · join users  ──►  fact_orders (Snowflake)
  • 장점 — warehouse CPU·스토리지raw 안 실을 때 비용 절감; 민감 데이터 적재 전 제거
  • 단점원본 미보존 시 스키마 변경·버그 수정소스 재추출; transform 로직Spark에만 있으면 SQL 팀 배제
  • 흔한 실무대용량 join·ML feature는 Spark ETLparquet gold + 요약만 warehouse
  • 5편 배치 job이 사실상 ETLT — 출력이 lakeL은 파일, warehouse면 JDBC/connector
# code/etl_load.example.py (발췌) — Spark에서 정제 후 warehouse 적재
curated = (
    orders.join(users, "user_id")
    .filter(col("status") == "PAID")
    .select("order_id", "user_id", "amount", "paid_at")
)
curated.write.format("jdbc").option("dbtable", "analytics.fact_orders").mode("append").save()

3. ELT 흐름

Extract → Load → Transform. raw를 먼저 warehouse(staging)에 넣고 SQL·dbtmart 생성.

단계 설명
Extract CDC·export Debezium, Fivetran, Spark copy
Load 가공 최소 staging raw.orders JSON 그대로
Transform warehouse SQL dbt stg_int_mart_
Test 품질 게이트 unique, not_null, 관계 테스트
CDC  ──►  staging.raw_orders  ──►  dbt: stg_orders → mart_revenue_daily
  • 장점raw 보존으로 replay·계보 용이; SQL만으로 비분석가리뷰; cloud warehouse 탄력 compute
  • 단점raw 스토리지·반복 스캔 비용; PIIstaging에 두면 권한·마스킹 필수
  • 현대 스택 — Snowflake·BigQuery·Redshift + dbtELT대표 조합
  • Spark 역할 — ELT에서도 heavy 전처리·비정형 파싱은 lake·staging 적재 전에 유지
-- code/dbt_mart_revenue.example.sql (발췌)
with paid as (
    select * from {{ ref('stg_orders') }} where status = 'PAID'
)
select
    date_trunc('day', paid_at) as revenue_date,
    sum(amount) as revenue
from paid
group by 1

4. ETL vs ELT 선택

  ETL ELT
Transform 위치 warehouse (Spark 등) warehouse (SQL/dbt)
Raw 보관 보통 별도 lake staging적재
적합 PII 사전 제거, Spark 이미 표준 cloud DW, SQL 중심 팀
재처리 Spark job 재실행 dbt full-refresh·incremental
비용 cluster 고정 warehouse 쿼리 종량
신호
소스 PII를 warehouse에 절대 두면 안 됨 ETL (또는 ingest 시 마스킹)
수십 TB raw를 DW에 매일 full load lake + 선택적 ELT (8편)
BI가 SQL·dbt자급자족 ELT
복잡 ML feature·비정형 Spark ETL → feature store / mart
  • 혼합일반적 — lake bronze (raw) + Spark silver + warehouse gold marts
  • 정본metric 하나당 한 테이블; parquet gold vs Snowflake 이중이면 문서화 필수
  • 스트림 — 6편 update sinkstaging 근실시간 + 일 배치 dbt merge

5. Warehouse layering

한 덩어리 테이블이 아니라 으로 나눠 의존성·재사용을 만든다.

역할 명명 예
Staging 소스 mirror, 타입 cast 최소 stg_orders, raw_events
Intermediate join·비즈니스 규칙 공유 int_orders_enriched
Marts BI·ML 소비용 dims/facts mart_revenue_daily, dim_users
staging  ──►  intermediate  ──►  marts
   ▲              ▲                ▲
 source        shared logic      one KPI definition
  • staging소스1:1에 가깝게 — 디버깅·replay
  • intermediate여러 mart가 쓰는 로직 한 번만 정의
  • martsdashboard·feature직접 SELECTwide·집계 OK
  • 8편 lakehouse bronze/silver/gold — 개념 대응; 파일 vs 테이블 물리만 다름
  • 9편schema evolution·품질 테스트가 층마다 다름

6. dbt 개념

dbt (data build tool) — warehouse 안 SELECT모델관리·의존 그래프·테스트·문서.

개념 설명
Model models/ 아래 SQL 파일 — view 또는 table materialize
ref() 모델 간 의존성컴파일DAG
source staging이 읽는 외부 raw 테이블 선언
test unique·accepted_values·relationships
incremental 대용량 append — merge 키로 증분
# code/dbt_project.example.yaml (발췌)
models:
  analytics:
    staging:
      +materialized: view
    marts:
      +materialized: table
  • Jinja{{ ref('stg_orders') }}환경database/schema 치환
  • dbt ≠ orchestrator실행dbt run 한 번; 언제 돌릴지는 Airflow
  • Spark 출력 — source('lake', 'orders') 또는 external tablestaging 연결
  • lineage — dbt docs + 9편 계보 도구와 연동

7. Orchestration

언제·어떤 순서로 job을 돌릴지 — 스케줄·의존성·재시도·알림.

도구 역할
Airflow DAG task — ingest → dbt → export
Dagster asset 단위 데이터 의존성
dbt Cloud / CI PR마다 test배포 게이트
06:00  ingest_raw_orders
06:20  dbt run --select staging+
06:45  dbt test
07:00  refresh BI extract (optional)
  • idempotency — 같은 logical date 재실행해도 중복 없게 — 10편 신뢰성
  • sensorupstream 파일·partition 도착dbt trigger
  • 실패staging까지는 성공·mart 실패부분 재실행 (dbt run --select mart_revenue+)
  • 5편 Spark batch — orchestrator task 하나; ELTload task dbt
# code/pipeline.dag.example.yaml (발췌)
schedule: "0 6 * * *"
tasks:
  - id: extract_orders
    operator: spark_submit
    conf: s3://jobs/raw_orders_daily.json
  - id: dbt_staging
    operator: dbt
    depends_on: [extract_orders]
    command: run --select staging+
  - id: dbt_marts
    operator: dbt
    depends_on: [dbt_staging]
    command: run --select marts+
  - id: dbt_test
    operator: dbt
    depends_on: [dbt_marts]
    command: test

8. 적재 설계 체크리스트

# 질문
1 ETL vs ELT — transform 위치팀·비용·PII와 맞는가
2 raw어디얼마나 보존되는가
3 staging / intermediate / marts 명명·소유가 정해졌는가
4 KPI 정본 테이블이 하나인가 — lake gold vs warehouse
5 dbt test·orchestrator retrySLA를 커버하는가
6 Spark·스트림·dbt 경계누가 어떤 변환을 소유하는가
  • Incremental partition·merge 키 — full scan 회피
  • Backfill날짜 범위 dbt vars 또는 Spark dt 루프10편
  • 권한 — staging PII role 분리; mart는 masked view
  • 8편Delta/Iceberglakewarehouse 경계 흐림

정리

  • Warehouse loading — process 이후 BI·ML이 쓰는 정본
  • ETLSpark 밖에서 정제 후 load; ELTraw loadSQL/dbt
  • Layering — staging → intermediate → marts — 재사용·디버깅
  • dbt — warehouse SQL DAG·test·docsorchestrator분리
  • Orchestration스케줄·의존성; 5·6편 Spark job과 같은 DAG 안에서 연결

다음에 다룰 것

  • Lakehouse 개요
  • data lake vs warehouse, Delta·Iceberg, object storage ACID

해당 내용은 dbt documentation (What is dbt), Kleppmann — Designing Data-Intensive Applications (Ch 10) 를 기반으로 합니다.

'Data & AI' 카테고리의 다른 글

Lakehouse 개요  (0) 2026.07.18
Spark Structured Streaming  (0) 2026.07.13
Spark 배치 처리  (0) 2026.07.09
Kafka 기초  (0) 2026.07.05
Batch vs Stream  (0) 2026.07.03