950 words
5 minutes
[DE Design Pattern]02-1. Full Load

Pattern Overview#

  • Full Load → 전체 교체, View Switching으로 일관성 확보
  • Incremental Load → Delta Column / Partition 기반 증분, Ingestion Window로 백필 안전성
  • CDC → 커밋 로그 기반 실시간 캡처, Data in Motion 의미론 주의
  • Replication → Passthrough(단순 복사) vs Transformation(PII 처리), Keep It Simple
  • Compaction → Small Files 해결, OPTIMIZE + VACUUM 세트, Kafka는 의미가 다름
  • Readiness & Trigger → Flag File / Convention으로 완성, External Trigger로 이벤트 기반 수집

01. Full Load Pattern#

전체 교체 패턴

Drop-and-Insert의 문제#

  • 클라이언트 관점의 데이터 일관성 : DROP과 INSERT 사이에 쿼리하면 데이터가 없거나 부분적으로만 보임. 트랜잭션을 지원하는 DB일 경우 트랜잭션으로 감쌀 수 있지만, 아닐 경우 별도 전략이 필요
  • 롤백 불가능 — 덮어쓰면 이전 버전으로 되돌릴 수 없음. Delta Lake나 Apache Iceberg 같은 Time Travel 지원 포맷이 아니라면, 직접 버전 관리를 구현해야 함

Single Data Exposition Abstraction#

  • 클라이언트가 보는 것(View)과 실제 데이터가 적재되는 것(물리 테이블)을 분리
  • 물리 테이블 두 개(table_1, table_2)를 번갈아 사용하고, Public View는 항상 둘 중 하나만 가리킴. 새 데이터를 현재 사용하지 않는 테이블에 적재한 뒤, View의 참조를 스위칭함.

->

  • 클라이언트는는 항상 완전한 데이터를 보게됨
  • 이전 버전 테이블도 남아있어 롤백이 가능
import psycopg2
def full_load_with_view_switching(conn, version: str, data_path: str):
"""
Single Data Exposition Abstraction 패턴
"""
versioned_table = f"devices_{version}" # devices_v2
with conn.cursor() as cur:
# 1) 버전 테이블 생성
cur.execute(f"""
CREATE TABLE IF NOT EXISTS {versioned_table} (
device_id VARCHAR(50),
device_type VARCHAR(100),
full_name VARCHAR(200)
)
""")
# 2) 데이터 적재 (COPY : bulk load)
cur.execute(f"""
COPY {versioned_table}
FROM '{data_path}'
WITH (FORMAT csv, HEADER true)
""")
# 3) View 스위칭
cur.execute(f"""
CREATE OR REPLACE VIEW devices
AS SELECT * FROM {versioned_table}
""")
conn.commit()

핵심은 CREATE OR REPLACE VIEWatomic 하다는 것

Time Travel을 통한 버전 관리#

  • Delta Lake나 Apache Iceberg를 사용할 경우 수동 버전 관리가 불필요.
  • 포맷 자체가 커밋 로그를 관리하므로 overwrite 모드로 써도 이전 버전을 조회가능
# Delta Lake — Full Load + 내장 Time Travel
input_data = spark.read.schema(input_data_schema).json(input_path)
input_data.write.format("delta").mode("overwrite").save("s3://master/devices")
# 문제 발생 시 이전 버전 조회
previous_version = (
spark.read.format("delta")
.option("versionAsOf", 0) # 첫 번째 버전
.load("s3://master/devices")
)
  • 이 경우 overwrite를 해도 Delta Lake의 트랜잭션 로그가 이전 스냅샷을 보존
  • View 스위칭 없이도 일관성과 롤백을 모두 확보 가능

Auto-scaling#

  • Full Load는 매번 전체를 가져오므로, 데이터 볼륨이 급증하면 정적 리소스로는 처리가 실패할 수 있음. ex) 하루 만에 데이터가 2배로 늘면 기존 배치 잡이 타임아웃될 수있음.
  • 이를 대비해 데이터 처리 레이어의 auto-scaling 기능을 활용하는 것이 권장됨

Concept

  • Full Load : 매 실행마다 전체 데이터셋을 교체하는 수집 패턴. 변경 감지 컬럼이 없는 소규모 참조 데이터에 적합
  • Single Data Exposition Abstraction : 소비자에게 노출되는 View와 실제 물리 테이블을 분리하여, 적재 중에도 데이터 일관성과 롤백을 보장하는 패턴
  • View Switching : 두 물리 테이블을 번갈아 사용하고 View 참조를 원자적으로 전환하는 기법
  • Time Travel : Delta Lake, Apache Iceberg 등이 제공하는 기능으로, 데이터의 이전 버전을 커밋 로그 기반으로 조회할 수 있는 기능
  • Drop-and-Insert : 기존 테이블을 삭제 후 재삽입하는 방식. 동시성 문제와 롤백 불가 문제를 유발
  • Passthrough Job : 데이터가 변환 없이 소스에서 목적지로 단순 통과하는 EL 작업

[DE Design Pattern]02-1. Full Load
https://yjinheon.netlify.app/posts/02de/de-design-pattern/02-data-ingestion/02-di-01-full_load/
Author
Datamind
Published at
2025-01-31
License
CC BY-NC-SA 4.0