Apache Iceberg 1.11: 삭제 벡터·REST 카탈로그 서버 사이드 플래닝·Variant 타입으로 완성된 V3
V3 table format은 왜 필요했는가
Apache Iceberg는 V1/V2 table format으로 ACID 트랜잭션, snapshot isolation, partition evolution을 데이터 레이크에 가져왔다. 그러나 V2 이후에도 남아 있던 세 가지 운영 부담이 있었다.
첫째, 행 삭제의 비용: V2에서 행 삭제는 positional delete file이나 equality delete file로 구현된다. 이 파일들은 파편화되고 개수가 늘어날수록 읽기 시 merge 비용이 커진다.
둘째, 카탈로그 클라이언트의 metadata 직접 접근: 모든 쿼리 엔진이 직접 object storage를 뒤져 manifest와 data file 목록을 탐색했다. 테이블이 크고 파티션이 많을수록 planning 시간이 길어졌다.
셋째, 반정형 데이터 표현의 한계: JSON 컬럼을 string으로 저장하면 predicate pushdown이 불가능하고, 별도 nested struct로 표현하면 schema evolution이 제한됐다.
2026년 5월 19일 출시된 Apache Iceberg 1.11.0은 이 세 문제 모두에 대한 생산 준비 완료(production-ready) 구현을 담았다. 삭제 벡터(deletion vectors), REST 카탈로그 서버 사이드 scan planning, Variant 타입이 V3 table spec의 핵심이다.
이 장은 2026년 7월 15일 기준으로 작성했다. Iceberg 1.11.0은 2026-05-19에 출시됐다. 90일 recency 기준을 충족한다. 삭제 벡터와 Variant 타입은 V3 table format에서만 사용 가능하다. V3 테이블을 새로 만드는 경우와 기존 V1/V2 테이블을 유지하는 경우를 구분해 읽는다.
1.11.0에서 바뀐 V3 핵심 경계
| 기능 | 1.11 이전 상태 | 1.11에서 | 운영자가 얻는 것 |
|---|---|---|---|
| 행 삭제 | positional/equality delete file | deletion vector (Puffin) | 삭제가 많아도 읽기 overhead 고정 |
| 카탈로그 scan planning | 엔진이 직접 manifest 탐색 | REST 카탈로그 server-side plan | 드라이버가 object storage를 읽지 않음 |
| 반정형 데이터 | string/map으로 저장 | 네이티브 Variant 타입 | predicate pushdown, shredding 최적화 |
| 암호화 | 외부 도구 의존 | 테이블 수준 envelope encryption | KMS 연동, 열 단위 보호 |
| 파일 포맷 API | 엔진별 구현 분산 | 통합 File Format API | Parquet·ORC·Avro 일관된 read/write |
| Java 지원 | Java 11 포함 | Java 17+ 필수 | 최신 JDK 기능 활용, Java 11 제거 |
V3 테이블의 핵심 구조
삭제 벡터: Roaring bitmap으로 행 삭제를 압축하는 방법
V2까지의 Iceberg는 행을 삭제할 때 positional delete file을 만들어 "이 data file의 이 위치에 있는 행은 삭제됐다"고 기록했다. 쿼리 시 엔진은 data file과 delete file을 모두 열어 merge해야 했다. 삭제 연산이 누적되면 delete file도 늘어나 읽기 비용이 선형으로 증가했다.
V3의 deletion vector는 이 구조를 바꾼다.
저장 구조: data file 하나마다 deletion vector 하나가 1:1로 대응한다. deletion vector는 Roaring bitmap으로 삭제된 행의 ordinal position을 압축 저장한다. Puffin 파일 포맷에 담겨 metadata 영역에 보관된다.
비트맵 세부 구조: Iceberg V3 spec은 64-bit 위치를 지원한다. 대부분의 행이 32-bit 범위에 있을 때는 단일 32-bit Roaring bitmap을 쓴다. 64-bit 위치가 필요하면 상위 32-bit를 key로, 하위 32-bit를 해당 key의 32-bit bitmap에 저장하는 계층 구조를 쓴다.
읽기 시 동작: 엔진은 data file을 읽기 전에 해당 deletion vector bitmap을 로드한다. bitmap에 표시된 행을 mask한 채로 data를 스캔한다. 별도 delete file을 열거나 merge하지 않는다.
이 구조가 주는 운영상 이점은 명확하다. 삭제가 얼마나 쌓여도 data file당 bitmap 하나만 읽으면 된다. V2의 positional delete file처럼 삭제 이력이 여러 파일에 파편화되지 않는다.
주의: deletion vector는 V3 table에서만 사용 가능하다. V1/V2 테이블을 V3로 업그레이드하지 않으면 기존 positional delete file 방식을 유지한다.
REST 카탈로그 서버 사이드 scan planning
기존에는 Spark/Trino 같은 엔진이 직접 카탈로그에서 snapshot을 가져온 뒤 manifest list → manifest file → data file 경로를 object storage에서 직접 탐색했다. 테이블이 크고 파티션이 많을수록 드라이버 노드가 수많은 object storage 요청을 보내야 했다.
1.11의 server-side scan planning은 이 작업을 REST 카탈로그 서버로 이전한다.
엔진 측: /v1/{prefix}/namespaces/{namespace}/tables/{table}/plan 엔드포인트에 POST 요청을 보낸다. 요청 본문에 scan 조건(snapshot, filter 등)을 포함한다.
카탈로그 서버 측: manifest 탐색을 서버에서 수행하고 최적화된 FileScanTask 객체 목록을 반환한다.
규모에 따른 처리 방식:
| 규모 | 카탈로그 응답 | 엔진 동작 |
|---|---|---|
| 소규모 | 즉시 FileScanTask 목록 반환 | 한 번의 응답으로 완료 |
| 대규모 | plan-id 반환 | 폴링하여 준비 확인 |
| 초대규모 | plan-id + 병렬 /tasks 엔드포인트 | 병렬 POST로 분할 수신 |
운영자 관점에서 얻는 이점은 두 가지다. 첫째, 드라이버가 object storage를 직접 탐색하지 않으므로 드라이버 메모리 압박과 S3/GCS API 호출 수가 줄어든다. 둘째, 카탈로그 서버가 scan plan을 캐시하고 최적화할 수 있어 반복 쿼리 성능이 향상된다.
제약: 서버 사이드 scan planning을 활용하려면 카탈로그 서버(REST Catalog 구현체)가 이 API를 구현해야 한다. 오픈소스 REST Catalog 구현체마다 지원 여부가 다르다. 1.11.0 기준으로 Iceberg 자체 REST Catalog 구현은 이 API를 지원하지만, Polaris나 Unity Catalog 같은 외부 카탈로그는 별도 확인이 필요하다.
Variant 타입: 반정형 데이터를 이진 인코딩으로 저장한다
로그 이벤트, JSON API 응답, 사용자 activity 같은 데이터는 구조가 일정하지 않다. 지금까지는 이런 데이터를 string 열로 저장하거나 예측 가능한 부분을 별도 struct로 분리해야 했다.
string 저장의 문제: 쿼리 시마다 JSON을 파싱하고 predicate pushdown이 불가능하다.
V3의 Variant 타입은 이 데이터를 위한 네이티브 이진 인코딩이다.
Predicate pushdown: Variant 값 안의 특정 path를 직접 필터링할 수 있다. 엔진이 raw 이진 구조에서 바로 조건을 평가하므로 전체 값을 역직렬화하지 않아도 된다.
Shredding: Variant 데이터에서 자주 접근하는 nested path를 자동으로 별도 sub-column으로 추출한다. event.user_id나 event.type 같은 경로는 독립 컬럼처럼 읽을 수 있어 전체 Variant blob을 읽지 않아도 된다.
-- V3 Variant 컬럼 쿼리 예시
SELECT event_data['user_id'], COUNT(*)
FROM logs
WHERE event_data['event_type'] = 'purchase'
AND event_data['amount'] > 100.0
GROUP BY 1;이 쿼리는 shredding이 설정된 경우 event_type과 amount sub-column만 읽어 전체 JSON blob scan을 건너뛸 수 있다.
테이블 암호화와 File Format API
테이블 암호화: 1.11.0은 envelope encryption을 내장한다. DEK(Data Encryption Key)로 데이터를 암호화하고 KEK(Key Encryption Key)로 DEK를 다시 암호화한다. KEK는 외부 KMS에서 관리한다. 1.11.0 기준으로 Google Cloud KMS 연동을 지원하며, 열 단위 암호화도 가능하다. KMS 접근 권한이 없으면 해당 테이블을 읽거나 쓸 수 없으므로 KMS 가용성이 테이블 SLA에 직접 영향을 준다.
File Format API: V1/V2에서는 엔진마다 Parquet, ORC, Avro를 읽고 쓰는 코드가 제각각이었다. 1.11.0은 이를 통합하는 FileFormat API를 finalize했다. 새 엔진이나 파일 포맷을 추가할 때 일관된 인터페이스를 따르면 된다.
Partition Statistics Scan API: optimizer가 partition별 통계(행 수, null 비율 등)를 query planning 전에 읽는 새 API를 추가했다. CBO(Cost-Based Optimizer)가 partition pruning 결정에 더 정확한 정보를 사용할 수 있게 된다.
Java 17 최소 요구사항과 엔진 호환성
Breaking change: Iceberg 1.11.0은 Java 11 지원을 완전히 제거한다. core library와 모든 엔진 커넥터가 Java 17 또는 Java 21을 요구한다. JDK 11을 쓰는 Spark, Flink, Trino 클러스터라면 반드시 JDK 업그레이드 계획을 먼저 세워야 한다.
신규 엔진 지원:
- Apache Spark 4.1 공식 지원 추가
- Apache Flink 2.1 공식 지원 추가
Spark 3.x나 Flink 1.x를 사용하는 기존 클러스터는 엔진 업그레이드 없이 Iceberg 1.11.0 커넥터를 그대로 쓸 수 없다. Iceberg 1.11.0이 지원하는 Spark와 Flink 버전 매트릭스를 릴리스 노트에서 확인한다.
V3 테이블 마이그레이션 고려사항
1.11 업그레이드 체크리스트
테스트 환경에서 먼저 확인해야 할 사항:
- JDK 버전을 17 또는 21로 업그레이드하고 기존 워크로드가 정상 실행되는지 확인한다.
- Spark/Flink 버전과 Iceberg 1.11.0 커넥터 호환성 매트릭스를 확인한다.
- V3로 전환할 테이블을 선정하고, 읽기/쓰기 smoke test를 진행한다.
- deletion vector 기능 활성화 후 기존 positional delete file이 있는 테이블의 읽기 성능 변화를 측정한다.
- REST Catalog 구현체의
/planAPI 지원 여부와 응답 latency를 확인한다. - 암호화를 도입한다면 KMS 연동과 접근 권한을 검증한다.
점진적 마이그레이션 전략:
V1/V2 테이블과 V3 테이블은 같은 카탈로그에서 공존할 수 있다. 신규 테이블은 V3로 만들고 기존 테이블은 읽기 성능 문제가 실제로 발생한 경우에만 단계적으로 V3로 업그레이드한다.
정리
Apache Iceberg 1.11.0은 V3 table format을 프로덕션 준비 완료 상태로 만든 릴리스다.
삭제 벡터: data file 1개당 Roaring bitmap 하나로 삭제 이력을 압축 저장한다. V2의 positional delete file 파편화 문제를 해소하고 삭제가 많은 테이블의 읽기 overhead를 고정 비용으로 바꾼다.
서버 사이드 scan planning: 엔진이 object storage를 직접 탐색하는 대신 REST 카탈로그 서버에 /plan 요청을 보내고 FileScanTask를 받는다. 드라이버 메모리 압박과 API 호출 비용을 줄인다.
Variant 타입: 반정형 데이터를 이진 인코딩으로 저장해 predicate pushdown과 shredding 최적화를 가능하게 한다. JSON string 저장보다 쿼리 성능과 압축률이 높다.
세 기능 모두 V3 table에서만 사용 가능하다. V3 업그레이드 전에 Java 17 최소 요구사항과 엔진 호환성 매트릭스를 반드시 확인한다. V3로 업그레이드한 테이블은 V1/V2 엔진에서 읽을 수 없으므로 다운그레이드 경로를 미리 설계한다.
References
- Apache Iceberg 1.11.0 릴리스 공지 (Google Open Source Blog)
- Apache Iceberg 1.11 Features: REST Catalog & Encryption (Snowflake)
- What's New in Apache Iceberg 1.11.0 (Dremio)
- Deletion Vectors 스펙 — Apache Iceberg™
- REST Catalog Scan Planning API — Apache Iceberg™
- The Apache Iceberg™ Variant Type (Snowflake Engineering)
- Beyond JSON blobs: Implementing the VARIANT data type in Apache Iceberg V3 (AWS)
- Unlock the power of Apache Iceberg v3 deletion vectors on Amazon EMR (AWS)
- Apache Iceberg releases