요약
2026년 2월, Snowflake는 Horizon Catalog의 Iceberg REST Catalog API를 정식 공개(GA)했다. 같은 해 5월 7일에는 Apache Iceberg V3 지원이 GA로 전환됐다. 이 두 이정표가 합쳐지면서 단일 Snowflake 계정에 저장된 Iceberg 테이블을 Spark·Trino·Flink·DuckDB 등 외부 엔진이 표준 REST 프로토콜로 읽고 쓸 수 있는 아키텍처가 완성됐다.
시점 주의: Horizon Catalog GA는 90일 창(2026-05-29 기준)을 벗어난 180일 이내 릴리스다. 90일 이내에 동일 운영 범주에서 더 최신 주제가 없어 다루기로 했다.
핵심은 세 가지다.
- 삭제 벡터(Deletion Vector): V2의 positional delete 파일보다 삭제 처리가 빠르고 쓰기가 가볍다.
- VARIANT 타입: 반정형 데이터를 문자열 없이 컬럼형으로 저장한다.
- Horizon Catalog REST API: 단일 Polaris 엔드포인트로 외부 엔진이 접속하며 거버넌스가 따라온다.
- 공식 문서: https://docs.snowflake.com/en/release-notes/2026/other/2026-05-07-iceberg-v3-ga
- Snowflake 블로그: https://www.snowflake.com/en/blog/apache-iceberg-v3-support/
배경: Iceberg V2에서 V3로 왜 이동하는가
Apache Iceberg V2는 행 수준 삭제를 positional delete 파일로 구현했다. 이 파일은 삭제된 행의 데이터 파일 경로와 행 번호를 열거한다. 읽기 시점에 엔진은 delete 파일을 병렬로 조인해 삭제를 적용한다.
V3의 핵심 차이는 삭제 정보를 별도 파일이 아니라 데이터 파일에 연결된 Puffin 블롭(Roaring bitmap)으로 표현한다는 점이다. 읽기 엔진은 별도 조인 없이 비트마스크만 적용하면 된다.
Iceberg V3 주요 기능 (Snowflake GA 기준)
1. 삭제 벡터(Deletion Vector)
# Snowflake SQL: V3 테이블에서의 DELETE 동작
DELETE FROM orders WHERE status = 'cancelled' AND order_date < '2026-01-01';이 DELETE는 데이터 파일을 재작성하지 않는다. 삭제된 행의 행 번호가 Puffin 파일 내 Roaring Bitmap에 기록된다. 이후 읽기에서 엔진이 마스크를 적용한다.
장점: 쓰기 증폭이 줄어든다. 단점: 삭제가 누적되면 읽기 시 마스크 평가 비용이 오른다. Snowflake의 자동 compaction이 이를 주기적으로 정리한다.
2. VARIANT 타입
-- V2에서 반정형 데이터를 저장하던 방식
CREATE TABLE events_v2 (
id BIGINT,
payload STRING -- JSON을 문자열로 저장
);
-- V3: VARIANT 타입 직접 지원
CREATE TABLE events_v3 (
id BIGINT,
payload VARIANT -- 컬럼형으로 저장, 경로 기반 접근
) AS ICEBERG;
-- 접근 예시
SELECT payload:user_id::STRING, payload:action FROM events_v3;VARIANT는 JSON을 문자열로 파싱하지 않는다. Iceberg 스냅샷에 shredded(분해된) 컬럼형으로 저장돼 경로 기반 프레디케이트 푸시다운이 가능하다.
3. 행 수준 계보(Row Lineage)
V3는 각 행에 삽입 시점의 스냅샷 ID를 메타데이터로 유지한다. 이 정보는 CDC(Change Data Capture)와 감사에 사용된다.
-- 언제 삽입됐는지 추적
SELECT *, _row_commit_snapshot_id
FROM orders
WHERE _row_commit_snapshot_id > 1234567890;Snowflake는 이 계보 정보를 Streams와 통합해 V3 Iceberg 테이블에서 변경 피드를 생성할 수 있도록 했다.
4. 그 외 V3 기능
| 기능 | 내용 |
|---|---|
| 기본 컬럼 값 | 스키마 추가 시 기존 행에 논리적 기본값 적용 (파일 재작성 없이) |
| 지오메트리/지리 타입 | ST_GeomFromText 등 공간 함수 연동 |
| 나노초 타임스탬프 | 이벤트 시간 정밀도 향상 (마이크로초 → 나노초) |
Horizon Catalog: Polaris가 REST로 노출되는 방식
Snowflake의 Horizon Catalog는 내부적으로 Apache Polaris 위에서 동작한다. 외부 엔진은 Iceberg REST Catalog 표준 엔드포인트를 통해 접속한다.
외부 엔진 연결 예시
# Apache Spark에서 Snowflake Iceberg 테이블 읽기
spark = SparkSession.builder \
.config("spark.sql.extensions",
"org.apache.iceberg.spark.extensions.IcebergSparkSessionExtensions") \
.config("spark.sql.catalog.snowflake_catalog",
"org.apache.iceberg.spark.SparkCatalog") \
.config("spark.sql.catalog.snowflake_catalog.catalog-impl",
"org.apache.iceberg.rest.RESTCatalog") \
.config("spark.sql.catalog.snowflake_catalog.uri",
"https://<account>.snowflakecomputing.com/polaris/api/catalog") \
.config("spark.sql.catalog.snowflake_catalog.token",
"<oauth_token>") # Snowflake OAuth
.getOrCreate()
# 일반 Iceberg 테이블처럼 접근
df = spark.table("snowflake_catalog.my_db.orders")
df.createOrReplaceTempView("orders_external")인증은 Snowflake OAuth 토큰을 사용한다. 토큰은 Snowflake의 RBAC 규칙을 그대로 반영한다. SELECT 권한이 없는 테이블은 외부 엔진에서도 접근이 차단된다.
Snowflake Open Catalog: 관리형 Apache Polaris
Snowflake는 Apache Polaris의 관리형 버전인 Snowflake Open Catalog를 별도로 제공한다. Snowflake 계정과 독립적으로 사용할 수 있고, Snowflake에서 관리하지 않는 외부 S3/GCS의 Iceberg 테이블도 등록해 다중 엔진 접근이 가능하다.
| 항목 | Horizon Catalog | Snowflake Open Catalog |
|---|---|---|
| 위치 | Snowflake 계정 내 내장 | 별도 서비스 |
| 데이터 소유 | Snowflake Managed Storage | 사용자 제공 S3/GCS/Azure |
| 비용 | Snowflake 스토리지/컴퓨팅 요금 | 현재 무료 (향후 요청당 과금 예정) |
| 거버넌스 | Snowflake RBAC 연동 | Polaris 자체 역할 |
운영 고려사항
V2 → V3 마이그레이션 경계
V2 테이블은 V3 기능을 즉시 사용할 수 없다. Snowflake가 자동으로 V2 표에 V3 포맷을 적용하지 않는다.
-- 테이블을 V3 포맷으로 전환 (새 쓰기부터 V3 적용)
ALTER ICEBERG TABLE orders SET FORMAT VERSION = 3;전환 후에는 V3를 지원하지 않는 엔진(예: 구버전 Spark Iceberg 커넥터)이 이 테이블을 읽지 못할 수 있다. 엔진 호환성 체크리스트:
| 엔진 | 최소 Iceberg 라이브러리 버전 |
|---|---|
| Apache Spark | iceberg-spark-runtime 1.7.0+ |
| Trino | Trino 482+ (built-in 지원) |
| Apache Flink | iceberg-flink 1.7.0+ |
| DuckDB | 1.5.0+ (iceberg extension 포함) |
| PyIceberg | 0.7.0+ |
Deletion Vector와 compaction
DV는 쓰기 증폭을 줄이지만, 누적된 삭제는 읽기 성능을 저하시킨다. Snowflake는 백그라운드 compaction을 자동으로 실행한다. 수동 compaction이 필요한 경우:
ALTER ICEBERG TABLE orders EXECUTE OPTIMIZE;이 명령은 DV가 표시한 삭제 행을 실제로 제거하고 파일을 재작성한다. 컴퓨팅 비용이 발생한다.
거버넌스 포터빌리티의 한계
Horizon Catalog를 통해 외부 엔진이 접근할 때 Snowflake RBAC 규칙이 테이블·컬럼 수준까지 적용된다. 단, 행 수준 보안(Row Access Policy)은 외부 엔진에 전달되지 않는다. Snowflake 내부 쿼리에서만 적용된다.
거버넌스 이식성 범위 (Horizon Catalog, 2026-05 기준)
✅ 테이블 접근 권한 (GRANT SELECT)
✅ 열 접근 권한 (Column Masking Policy)
✅ 데이터베이스·스키마 접근 권한
❌ 행 접근 정책 (Row Access Policy) — Snowflake 쿼리에만 적용
❌ 동적 데이터 마스킹 일부 정책 — 엔진별 구현 차이 가능Open question: 행 수준 보안의 외부 엔진 적용 경로가 언제 추가될지 공식 로드맵에 명시되지 않았다.
언제 이 아키텍처를 선택하는가
Snowflake Horizon Catalog + Iceberg V3 아키텍처는 다음 조건에서 강점을 갖는다.
- Snowflake가 주 쿼리 엔진이지만 Spark 배치·Flink 스트리밍도 동일 데이터 접근이 필요한 경우 — 복제 없이 단일 스토리지를 공유한다.
- 삭제·업데이트가 빈번한 테이블 — DV가 쓰기 증폭을 제한한다.
- 반정형 데이터(JSON 이벤트, 로그 페이로드) 분석 — VARIANT 타입이 파싱 오버헤드 없이 컬럼형 스캔을 지원한다.
선택하지 않는 경우:
- 행 수준 보안이 외부 엔진에서도 강제돼야 할 때 (현재 미지원)
- Snowflake 외부에 데이터를 두고 싶은 경우 (Snowflake Open Catalog가 대안이지만 다른 거버넌스 모델)
References
- Snowflake: Iceberg V3 GA 릴리스 노트: https://docs.snowflake.com/en/release-notes/2026/other/2026-05-07-iceberg-v3-ga
- Snowflake 블로그 Iceberg V3: https://www.snowflake.com/en/blog/apache-iceberg-v3-support/
- Atlan: Apache Iceberg V3 Snowflake 2026 가이드: https://atlan.com/know/snowflake/apache-iceberg-v3/
- Atlan: Apache Iceberg in Snowflake (실용 가이드): https://atlan.com/know/iceberg/apache-iceberg-snowflake/
- Snowflake Polaris Catalog 블로그: https://www.snowflake.com/en/blog/engineering/apache-polaris-iceberg-rest-catalog/
- Apache Iceberg Catalog 현황 (2026-06): https://dev.to/alexmercedcoder/the-state-of-apache-iceberg-catalogs-in-june-2026-265e
- Snowflake Interoperable Lakehouse: https://www.snowflake.com/en/developers/guides/interoperable/