Bigdata, Iceberg

Jeonghak Cho·2025년 4월 6일

Bigdata

목록 보기
14/30

📗ICEBERG 개요

Iceberg는 대규모 분석 데이터를 위한 오픈 테이블 포맷이다. 원래 Netflix에서 시작되어 현재는 Apache Software Foundation에서 관리하고 있으며, 데이터 레이크에 저장된 파일들을 효율적으로 관리하고 분석 성능을 높이기 위해 만들어졌다.

HDFS + Hive 메타스토어 방식으로 데이터를 관리하는 방식에는 아래와 같은 한계가 있다.

  • 파일 기반 관리의 한계 (성능 저하, 병합 등 문제)
  • 스키마 진화의 어려움
  • 데이터 정합성 보장 어려움 (특히 병렬 처리 시)
  • 타임 트래블이나 버전 관리 불가

Iceberg는 이 한계 극복을 위한 아래와 같은 기능을 가진다.

  • 스키마 진화 (Schema Evolution) - 컬럼 추가/삭제, 타입 변경 등을 무중단으로 수행 가능
  • 타임 트래블 (Time Travel)- 과거 스냅샷으로 되돌아가서 쿼리 가능 (버전 관리)
  • 머지 온 리드 / 쓰기 (Merge-on-read / write)- 데이터 업데이트와 병합을 효율적으로 처리 가능
  • 히든 파티셔닝 (Hidden Partitioning) - 쿼리에서 파티션 컬럼을 몰라도 성능 최적화 자동 적용
  • 메타데이터 계층화 - 스냅샷, 매니페스트, 매니페스트 리스트를 통해 대규모 파일도 빠르게 탐색 가능
항목설명
종류오픈 테이블 포맷 (Apache Iceberg)
목적대규모 분석 데이터를 안정적이고 효율적으로 관리
지원 파일 포맷Parquet, ORC, Avro 등
저장소S3, HDFS, Azure, GCS 등 다양한 오브젝트 스토리지
주요 엔진 연동Spark, Trino, Flink, Hive, Presto 등

🏳️‍🌈 [궁금한점]

  • ICEBERG는 무엇이며 어디에 쓰이는가
  • ICEBERG를 사용하면 기존 방식 대비 어떤 개선점을 기대할 수 있는가

🔗[목차]

활용

  • 데이터 레이크에 저장된 S3 데이터를 Trino로 분석
  • Flink로 실시간 데이터 스트리밍 후 Iceberg 테이블로 저장
  • Spark로 배치 작업 및 데이터 정제 후 버전 관리
  • 시간별 스냅샷을 통해 특정 시점의 데이터 분석
구조 요약
Iceberg Table
├── Metadata (metadata.json, snapshot files)
│   └── 테이블 구조, 스냅샷 이력 등 저장
├── Manifest Lists
│   └── 어떤 매니페스트 파일을 사용할지 정의
├── Manifest Files
│   └── 실제 데이터 파일 경로, 파티션 정보 등
└── Data Files (Parquet 등)
    └── 실제 데이터 저장

오픈 테이블 포맷(Open Table Format)

오픈 테이블 포맷(Open Table Format)은 데이터 레이크에서 대규모 데이터를 표 형태(테이블)로 구조화하여 저장하고 관리하기 위한 표준 방식이다. 즉, 파일 시스템에 저장된 데이터들을 마치 데이터베이스 테이블처럼 다룰 수 있게 해주는 규칙/포맷이다. 데이터 레이크에 저장된 파일(Parquet, ORC 등)을 테이블처럼 관리할 수 있도록 메타데이터와 동작 방식을 표준화한다.

데이터 레이크에 데이터를 저장하면, 보통은 파일 단위(예: .parquet)로만 존재한다. 이걸 분석하려면 일일이 파일 경로를 알아야 하고, 파티션도 직접 지정해줘야 하고 불편한 점이 많다. 마치 RDB의 테이블처럼 쿼리로 쉽게 다룰 수 있게 만드는게 오픈 테이블 포맷이다.

주요 기능

기능설명
스키마 진화테이블 구조 변경 (컬럼 추가/삭제/수정) 가능
타임 트래블이전 시점의 데이터로 쿼리 가능
ACID 트랜잭션데이터 업데이트/삭제 시 충돌 없이 안전하게 처리
파티셔닝 최적화쿼리 성능 향상을 위한 파티션 자동 처리
버전 관리데이터 변경 이력 관리 가능

대표적인 오픈 테이블 포맷

포맷특징대표 사용자
Apache Iceberg메타데이터 계층 구조, Flink/Spark/FastQuery에 강함Netflix, Apple 등
Apache Hudi실시간 데이터 처리에 강함 (UPSERT 중심)Uber
Delta LakeDatabricks 기반, Spark와 최적화Databricks, Microsoft 등

파일 시스템과 비교

항목기존 파일 시스템오픈 테이블 포맷
저장 방식파일 단위 (경로로 접근)테이블 단위 (SQL처럼 접근)
스키마 변경수작업 필요자동 반영
병합/삭제어렵고 오류 가능트랜잭션으로 안정적
쿼리 성능파티션 수동 지정최적화 자동 처리

스키마 진화(Schema Evolution)

스키마 진화(Schema Evolution) 는 Iceberg, Delta Lake, Hudi 같은 오픈 테이블 포맷의 핵심 기능 중 하나이다. 기존 테이블의 구조(스키마)를 변경해도 데이터를 그대로 유지하면서 쿼리나 작업을 계속할 수 있는 기능이다.

Iceberg의 스키마 진화 특징

변화 유형지원 여부설명
컬럼 추가기존 데이터는 null로 처리됨
컬럼 삭제메타데이터에서 제거됨 (데이터는 물리적으로 남을 수 있음)
컬럼 이름 변경내부 ID 기반으로 관리되기 때문에 안전하게 변경 가능
컬럼 순서 변경논리적으로만 변경 가능 (물리 순서와 무관)
컬럼 타입 변경제한적호환 가능한 타입 간에만 변경 가능 (ex. int → long, float → double 등)

예시 (Spark + Iceberg)

-- 기존 테이블에 컬럼 추가
ALTER TABLE users ADD COLUMN email STRING;

-- 기존 컬럼 이름 변경
ALTER TABLE users RENAME COLUMN age TO user_age;

-- 기존 컬럼 삭제
ALTER TABLE users DROP COLUMN deprecated_field;

스키마 진화기능을 이용한 스타 스키마 설계

항목스키마 진화가 미치는 영향
차원 테이블 확장성컬럼 추가/삭제가 유연하게 가능
조인 안정성컬럼 이름 변경 시 쿼리 유지
변경 이력 추적스냅샷으로 스키마 변경 이력 관리
사실 테이블 구조 변경 대응새 지표 추가 등 구조 확장이 쉬움

타임 트래블(Time Travel)

타임 트래블(Time Travel)은 Iceberg, Delta Lake, Apache Hudi 같은 오픈 테이블 포맷의 대표적인 기능 중 하나이다.이 기능은 데이터 분석과 데이터 품질 관리에서 유연성과 안정성을 제공한다.

과거 특정 시점의 데이터 또는 테이블 상태로 되돌아가서 조회할 수 있는 기능이다.

마치 "데이터 타임머신" 같은 개념입니다.
이전 버전의 데이터가 스냅샷(Snapshot) 형태로 저장되어 있어서,
그 시점의 데이터 상태를 그대로 다시 쿼리하거나 복원할 수 있어요.

Iceberg는 각 데이터 변경 시 마다 스냅샷(Snapshot) 을 생성한다.

특징

  • Iceberg는 메타데이터에 모든 변경 이력을 저장
  • 데이터 파일은 immutable(불변) 이라서 이전 상태 유지가 가능
  • 변경된 내용만 추가로 기록 → 효율적인 저장 방식
항목설명
정의과거 특정 시점의 데이터 상태로 되돌아가 조회하는 기능
주요 목적실수 복구, 이력 조회, 시점별 리포트 생성 등
사용 방식TIMESTAMP AS OF, VERSION AS OF, SNAPSHOT ID
Iceberg 방식스냅샷 기반, 메타데이터로 관리, 데이터는 불변성 유지
  • Spark 예시
-- 특정 Snapshot ID 기준으로 조회
SELECT * FROM sales_table.snapshots WHERE snapshot_id = 918273645;

-- 특정 Timestamp 기준으로 조회
SELECT * FROM sales_table TIMESTAMP AS OF '2024-12-31T23:59:59';

-- Snapshot 버전 넘버로 조회
SELECT * FROM sales_table VERSION AS OF 3;

ACID 트랜잭션

Merge-on-read와 Merge-on-write는 Apache Iceberg, Hudi, Delta Lake 같은 오픈 테이블 포맷에서 업데이트(Update)나 삭제(Delete) 같은 변경 작업을 어떻게 처리할지에 대한 전략이다. Iceberg는 기본적으로 Merge-on-Write를 따른다. 하지만 Flink나 일부 엔진에서는 Merge-on-Read도 지원하며, 상황에 따라 전략을 선택할 수 있다.

항목Merge-on-WriteMerge-on-Read
병합 시점쓰기 시점에서 병합읽기 시점에서 병합
쓰기 성능느림 (병합 비용 발생)빠름 (로그만 저장)
읽기 성능빠름 (병합 완료된 파일만 읽음)느림 (파일 + 로그 병합 필요)
적합한 환경읽기 많은 배치 분석 환경변경이 잦은 실시간 스트리밍 환경
예시 포맷 적용Iceberg (기본), Delta LakeHudi, Flink on Iceberg (옵션에 따라)

Merge-on-Write (MOW)

  • 변경 요청 시 즉시 병합된 새로운 데이터 파일을 생성
  • 델타 파일 없음 → 읽을 때 빠름
  • 읽기 성능 우선, 쓰기 성능은 낮아질 수 있음
  • 읽기 성능이 뛰어남
  • 데이터 일관성이 좋음 (즉시 반영)
  • UPDATE/DELETE가 많을 경우 쓰기 부담 증가

예시 흐름:

  • 원본 파일: data-file-1.parquet
  • UPDATE 수행 → 새로운 병합 파일 생성: data-file-2.parquet
  • 읽을 때 data-file-2만 읽으면 됨

Merge-on-Read (MOR)

  • 변경 내용은 별도 로그 파일(delta log) 로 저장
  • 읽을 때 기존 데이터와 로그를 병합하여 최종 결과 생성
  • 쓰기 속도가 빠름
  • 변경이 잦은 실시간 환경에 적합
  • 읽기 성능 저하 가능 (병합 비용)

    예시 흐름:

  • 원본 파일: data-file-1.parquet
  • UPDATE 수행 → delta-log-1.log에 변경 내용만 저장
  • 읽을 때 data-file-1 + delta-log-1을 병합해서 조회

파티셔닝 최적화(Partitioning Optimization)

파티셔닝 최적화(Partitioning Optimization) 는 대규모 데이터 처리에서 쿼리 성능 향상을 위한 핵심 전략 중 하나이다. 특히 Iceberg 같은 오픈 테이블 포맷은 기존 방식의 단점을 개선한 스마트한 파티셔닝 기능을 제공한다.

파티셔닝이란 데이터를 특정 컬럼 값 기준으로 나누어 저장하는 것이다.

예: event_date 기준으로 하루 단위 파티션을 만들면

  • → .../event_date=2025-04-06/ 같은 구조가 됨
  • → 쿼리 시 원하는 파티션만 읽어 속도와 비용 절감
항목기존 방식 (예: Hive)Iceberg 방식
파티션 방식디렉터리 기반메타데이터 기반 (숨겨진 파티션)
컬럼 변경 시 대응전체 재생성 필요스키마 진화 가능
쿼리 최적화명시적 필터 필요자동 파티션 필터 적용
파티션 전략정적 (col=value)Identity, Bucket, Truncate 등 지원
성능 및 유연성제한적고성능, 높은 유연성

기존 파티셔닝 방식의 한계 (Hive 스타일 등)

  • 디렉터리 기반 (/col=value/)
  • 변경 어려움: 컬럼 변경 시 전체 테이블 재생성 필요
  • 파티션이 너무 많거나 적으면 성능 저하
    • 너무 많으면 small file 문제
    • 너무 적으면 쿼리 성능 저하
  • 파티션 컬럼을 명시적으로 쿼리해야 필터가 적용됨

Iceberg의 파티셔닝 최적화

Iceberg는 기존의 단점을 해결하고, 더 유연하고 똑똑한 방식을 사용한다

Hidden Partitioning (숨겨진 파티셔닝)

  • 사용자는 파티션 컬럼을 따로 고려하지 않아도 됨
  • Iceberg가 자동으로 파티션 필터를 쿼리에 적용

예:
쿼리에서 단순히 WHERE event_time = '2025-04-06'이라 해도
→ Iceberg는 내부적으로 event_date 파티션만 읽음

Flexible Transform (변환 기반 파티셔닝)

컬럼 값을 기반으로 다양한 방식으로 파티셔닝 가능해서 사용자가 쿼리 패턴에 맞게 파티션 전략을 설계할 수 있다.

파티션 타입예시
Identitycountry → 그대로 사용
Truncatezipcode → 앞 3자리만 저장
Bucketuser_id → 해시로 N개의 버킷으로
Year/Month/Dayevent_time → 연/월/일 추출

파티션 스키마 변경 가능

Iceberg는 파티션 전략도 진화할 수 있음 (스키마 진화처럼)

예: 기존 day 단위 → month 단위로 변경 가능
→ 데이터 재작성 없이도 쿼리 가능

예시

-- Iceberg 테이블 생성 시 파티셔닝 설정
CREATE TABLE logs (
  id BIGINT,
  user_id STRING,
  event_time TIMESTAMP,
  action STRING
)
PARTITIONED BY (days(event_time), bucket(16, user_id));
  • 날짜와 user_id 기준으로 파티셔닝
  • 쿼리 시 자동으로 필터 적용되어 성능 향상

메타데이터 계층화(Metadata Layering)

Apache Iceberg에서 말하는 메타데이터 계층화(Metadata Layering)
기존 Hive 스타일 테이블과는 완전히 다른 고급 관리 체계를 의미한다. Iceberg는 테이블의 구조와 상태를 계층적인 메타데이터 파일로 관리함으로써
데이터 변경 이력, 스냅샷, 파티션, 스키마 등을 효율적이고 안전하게 추적할 수 있게 해준다. Iceberg의 메타데이터 계층화는
단순한 파일 목록을 넘어서 스냅샷, 통계, 파티션, 스키마, 변경 이력 등을
정교하게 관리할 수 있도록 설계된 구조이다. 덕분에 Iceberg는 신뢰성 있는 분석, 안전한 변경, 고성능 쿼리를 모두 만족시킬 수 있다.

계층 구조 구성요소

Iceberg는 아래와 같은 다단계 메타데이터 파일 구조로 구성되어 있다:

계층설명
Manifest List스냅샷에 포함된 manifest 파일들의 목록 (즉, 한 번의 쿼리에 필요한 데이터 목록)
Manifest여러 data file(Parquet 등)의 목록과 관련 메타 정보 (파티션, 통계 등)
Data File실제 사용자 데이터 (Parquet, ORC 등)
  • Snapshot: 테이블의 하나의 시점을 나타내는 논리적 단위
  • Metadata.json: 테이블의 전체 스냅샷 목록, 현재 활성 스냅샷 정보, 스키마, 파티션 전략 등을 포함

구조

Iceberg Table
├── metadata/
│   ├── v1.metadata.json          ← 스키마, 파티션 전략, 최신 스냅샷 ID 등
│   └── snapshots/
│       ├── snapshot-001
│       └── snapshot-002
│           ├── manifest-list.avro
│               └── manifest-1.avro
│                   └── data-file-1.parquet
│                   └── data-file-2.parquet

왜 계층화가 중요한가?

항목설명
변경 추적각 변경 시점마다 스냅샷 생성. 변경 이력 추적 가능
타임 트래블이전 스냅샷으로 복원하거나 조회 가능
쿼리 성능 향상Manifest에 파티션 및 통계 정보가 있어서 Pruning 가능
동시성 제어 (ACID)메타데이터 파일을 원자적으로 교체하는 방식으로 충돌 방지
Garbage Collection오래된 snapshot과 관련된 data file을 안전하게 정리 가능

Hive 스타일과의 차이

항목Hive 스타일 테이블Iceberg (메타데이터 계층화)
메타데이터 저장Hive Metastore에 저장테이블 내부에 JSON/AVRO 파일로 저장
스냅샷 지원없음있음 (버전 관리 가능)
성능 최적화파티션 디렉터리 기반Manifest 통한 정밀한 pruning
트랜잭션외부 도구 필요 (e.g. Hive ACID)기본 제공 (ACID 지원)

0개의 댓글