이 문서는 레이크하우스 아키텍처 섹션의 일부입니다.
이 문서에서 다루는 내용
Delta Lake의 핵심 개념을 이해하셨다면, 이제 실무에서 자주 사용하는 고급 조작법 을 살펴보겠습니다. 이 기능들은 데이터 파이프라인을 안정적이고 효율적으로 운영하는 데 필수적입니다.MERGE (Upsert)
개념
💡 MERGE 는 “있으면 업데이트하고(UPDATE), 없으면 삽입한다(INSERT)“를 하나의 명령으로 수행하는 작업입니다. 이를 Upsert(Update + Insert) 라고도 부릅니다.전통적인 데이터 레이크에서는 UPDATE가 불가능하여, 전체 테이블을 다시 써야 했습니다. Delta Lake의 MERGE는 이 문제를 우아하게 해결합니다.
MERGE는 어떻게 “우아하게” 해결하는가?
전통적인 데이터 레이크(Parquet/ORC)에서 1건의 고객 주소를 변경하려면 어떤 일이 벌어지는지 비교해 보겠습니다. 기존 데이터 레이크의 UPDATE 방식 (비참한 현실):
이것이 가능한 핵심 메커니즘은 Copy-on-Write + 트랜잭션 로그 입니다.
- Copy-on-Write: 기존 파일을 직접 수정하지 않고, 변경이 필요한 파일을 통째로 복사하여 수정본을 새로 씁니다. 원본은 그대로 남아 있으므로 타임 트래블이 가능합니다.
- 트랜잭션 로그(_delta_log): JSON/Parquet 형태의 로그 파일이 모든 변경 사항을 순서대로 기록합니다. “어떤 파일이 추가되고 제거되었는지”를 원자적(Atomic)으로 커밋하므로, 중간에 실패해도 데이터가 손상되지 않습니다.
- Data Skipping: 트랜잭션 로그에 각 파일의 min/max 통계가 저장되어 있어, MERGE 조건에 해당하지 않는 파일은 아예 읽지 않습니다. 이것이 “전체 테이블 스캔” 대신 “필요한 파일만 스캔”을 가능하게 합니다.
참고 비유로 이해하기: 전통적인 데이터 레이크의 UPDATE는 “책 한 글자를 고치려고 책 전체를 다시 인쇄하는 것”과 같습니다. Delta Lake의 MERGE는 “해당 페이지만 교체하고, 목차(트랜잭션 로그)에 ‘3페이지가 새 버전으로 교체됨’이라고 기록하는 것”입니다. 다른 독자는 교체 작업이 완료되기 전까지 이전 페이지를 계속 읽을 수 있습니다.
문법
실습 예제: 고객 정보 동기화
MERGE의 활용 패턴
💡 SCD(Slowly Changing Dimension, 완만하게 변하는 차원)란? 데이터 웨어하우스에서 시간에 따라 변하는 데이터(예: 고객 주소, 상품 가격)를 어떻게 관리할지에 대한 전략입니다.
- Type 1: 변경 시 이전 값을 덮어씁니다. 이력을 보존하지 않습니다.
- Type 2: 변경 시 이전 레코드를 만료 처리하고 새 레코드를 추가합니다. 전체 이력을 보존합니다.
OPTIMIZE (데이터 압축)
개념
💡 OPTIMIZE 는 Delta 테이블의 작은 파일들을 큰 파일로 합치는(Compaction) 작업입니다. 데이터를 지속적으로 추가하다 보면 작은 파일이 매우 많아지는데, 이를 적절한 크기로 합치면 쿼리 성능이 크게 향상됩니다.
왜 필요한가요?
작은 파일이 많으면 읽기 성능이 저하됩니다. OPTIMIZE로 적절한 크기(128MB~1GB)로 병합합니다.
💡 Small File Problem(작은 파일 문제)이란? 스트리밍 수집이나 빈번한 INSERT로 인해 테이블에 수천~수만 개의 작은 파일이 쌓이는 현상입니다. 쿼리 시 각 파일을 열고 닫는 오버헤드가 누적되어 성능이 크게 저하됩니다. OPTIMIZE는 이 문제를 해결합니다.
사용 방법
Liquid Clustering
🆕 Liquid Clustering 은 Databricks가 최근 도입한 차세대 데이터 배치 최적화 기술입니다. 기존의 Z-Order와 파티셔닝을 대체하며, 데이터를 자동으로 최적의 레이아웃으로 재배치합니다.
💡 파티셔닝(Partitioning)이란? 데이터를 특정 컬럼 값(예: 날짜)에 따라 물리적으로 다른 디렉토리에 저장하는 방식입니다.order_date = 2025-03-15데이터는/order_date=2025-03-15/디렉토리에 저장되므로, 특정 날짜만 조회할 때 해당 디렉토리만 읽으면 됩니다. 다만 카디널리티(고유값 수)가 높은 컬럼으로 파티셔닝하면 오히려 작은 파일이 많아지는 문제가 생깁니다.
VACUUM (오래된 파일 정리)
개념
💡 VACUUM 은 Delta 테이블에서 더 이상 사용되지 않는 오래된 데이터 파일 을 삭제하여 스토리지 비용을 절약하는 작업입니다.Delta Lake에서 UPDATE나 DELETE를 실행하면, 기존 파일이 즉시 삭제되지 않고 새 파일이 추가됩니다 (타임 트래블을 위해). VACUUM은 일정 기간이 지난 오래된 파일을 정리합니다.
사용 방법
⚠️ 주의사항: VACUUM을 실행하면 해당 기간 이전의 타임 트래블이 불가능해집니다. 예를 들어, RETAIN 168 HOURS로 VACUUM을 실행하면 7일 이전의 데이터는 더 이상 타임 트래블로 조회할 수 없습니다. 규정 준수 요건에 따라 보존 기간을 적절히 설정하시기 바랍니다.
DELETE와 UPDATE
DELETE
UPDATE
💡 일반 데이터 레이크(Parquet 파일)에서는 DELETE/UPDATE가 불가능합니다. Delta Lake이기에 가능한 기능이며, 내부적으로는 해당 데이터를 포함하는 파일을 새로 쓰는 방식(Copy-on-Write)으로 동작합니다.
테이블 정보 확인 명령어
운영 모범 사례
🆕 최신 기능: Databricks는 Predictive Optimization 을 통해 OPTIMIZE와 VACUUM을 자동으로 실행하는 기능을 제공하고 있습니다. Unity Catalog가 활성화된 관리형(Managed) 테이블에서는 Databricks가 테이블의 상태를 모니터링하고, 최적의 시점에 자동으로 최적화를 수행합니다.
현업 사례: MERGE 성능이 갑자기 10배 느려진 원인 분석
현업에서 MERGE는 가장 많이 사용하는 Delta Lake 명령어이면서, 동시에 가장 많은 성능 이슈를 일으키는 명령어입니다. 실제 사례를 통해 MERGE의 내부 동작을 깊이 이해하겠습니다.사례: 전자상거래 회사의 주문 테이블
주문 상태를 업데이트하는 MERGE가 평소 5분 걸리다가, 어느 날 갑자기 50분으로 늘어났습니다.MERGE의 내부 동작 이해
MERGE는 내부적으로 3단계로 동작합니다. 각 단계를 이해하면 성능 문제의 원인을 찾을 수 있습니다.원인 분석: 왜 10배 느려졌는가
대규모 MERGE 최적화 전략
UPSERT 패턴의 현실적 고려사항
⚠️ 현업에서는 이렇게 합니다: MERGE의 성능은 “얼마나 많은 파일을 재작성하느냐”에 달려있습니다. Liquid Clustering으로 MERGE 키 기준 데이터를 모아두면, 변경 대상 파일만 재작성하므로 10~100배 빨라집니다. 이것을 안 하면 500GB 테이블에서 1건만 UPDATE해도 수십 GB의 파일을 재작성하게 됩니다.
💡 숫자로 이해하기: 10억 건 테이블(500GB, 파일 5,000개)에서 50만 건 MERGE 시:
- 클러스터링 없음: 5,000개 파일 중 4,800개 재작성 (96%) → 50분
- Liquid Clustering(order_id): 5,000개 파일 중 250개 재작성 (5%) → 3분
MERGE 운영 시 반드시 모니터링해야 할 지표
현업에서 MERGE 파이프라인을 안정적으로 운영하려면 다음 지표를 모니터링해야 합니다.정리
다음 문서에서는 Delta Lake와 Apache Iceberg 의 관계 및 상호 운용성을 살펴보겠습니다.