Apache Iceberg REST Catalog Server — 사양, 구현체, 운영 패턴
Iceberg REST Catalog 사양이 왜 멀티-엔진 Lakehouse의 새 표준이 되었는지, OpenAPI 기반 사양의 구조, 주요 구현체(Polaris·Unity OSS·Lakekeeper·Nessie·Gravitino) 비교, 자체 호스팅 운영 패턴, 엔진 연결 방법을 정리합니다.
Apache Iceberg를 멀티-엔진 환경에서 운영하기로 결정한 순간, 다음 의사결정은 거의 항상 카탈로그로 옮겨갑니다. "어떤 카탈로그를 쓸 것인가"는 단순한 메타스토어 선택이 아니라, 사내 전체 데이터 인프라의 **통제점(control plane)**을 어디에 둘 것인가의 문제입니다.
2023~2024년 사이 합의된 Iceberg REST Catalog 사양과, 그 사양을 구현한 일련의 오픈소스 서버들이 이 문제의 새로운 기준이 되었습니다. 이 글은 사양의 핵심, 주요 구현체의 차이, 자체 호스팅 운영 패턴, 그리고 엔진을 연결하는 실전 방법까지 정리합니다.
1. 왜 REST Catalog인가
1.1 멀티-엔진 시대의 카탈로그 문제
2010년대까지 Iceberg 이전의 사실상 표준은 Hive Metastore(HMS)였습니다. AWS Glue는 HMS의 관리형 변형으로 자리잡았고, 이외에 JDBC 카탈로그, 파일 시스템 카탈로그, Project Nessie 같은 대안도 있었습니다.
이 시기 카탈로그 선택은 곧 다음 문제와 직결됐습니다.
- 카탈로그마다 클라이언트가 다르다. HMS는 Thrift, Glue는 AWS SDK, JDBC는 SQL 드라이버. 엔진은 카탈로그별로 어댑터를 따로 구현해야 했습니다.
- 권한 모델이 카탈로그마다 다르다. HMS Ranger, Glue Lake Formation, Databricks Unity 등이 서로 다른 모델로 권한을 표현했습니다.
- 계산 노드가 직접 스토리지에 접근해야 한다. 카탈로그는 메타데이터 위치만 알려주고, 실제 데이터 접근 자격 증명은 워커가 들고 있어야 했습니다. 멀티 테넌트 환경에서 이는 위험했습니다.
- 카탈로그가 엔진 종속을 강화했다. 한 엔진(예: Databricks)의 카탈로그에 묶이면 다른 엔진에서의 접근이 까다로워졌습니다.
1.2 REST Catalog 사양의 등장
Iceberg 커뮤니티는 2022년부터 모든 엔진이 동일한 HTTP API로 카탈로그를 다루는 사양을 논의했고, 2023년 v1이 정식 합의되었습니다.
핵심 결정:
- OpenAPI 기반의 명세된 HTTP API — 엔진은 카탈로그별 클라이언트를 구현할 필요 없이, REST 클라이언트 하나로 모든 REST Catalog와 통신합니다.
- 메타데이터 트랜잭션을 서버가 책임진다 — 옛 HMS 모델에서 클라이언트가 했던 metadata.json swap을 서버가 원자적으로 처리합니다. 클라이언트의 잠금·재시도 로직이 단순해집니다.
- Vended Credentials — 서버가 카탈로그 권한 검사를 통과한 클라이언트에게 단명(short-lived) 스토리지 자격 증명을 발급합니다. 워커가 영속 자격 증명을 들고 있을 필요가 없어집니다.
- 백엔드 자유 — 서버는 메타데이터를 어디에 저장하든(JDBC, HMS, Glue, 자체 DB 등) 상관없습니다. 외부 인터페이스(REST 사양)만 동일하면 됩니다.
1.3 REST Catalog가 가져온 변화
2022 이전: 2024+ (REST Catalog 표준 후):
Spark ──▶ HMS Client Spark ──┐
Trino ──▶ Glue SDK Trino ──┤
Flink ──▶ JDBC catalog Flink ──┼─▶ REST Catalog ──▶ 백엔드
Snow ──▶ 자체 카탈로그 Snow ──┤ (단일 HTTP API) (HMS/JDBC/Glue/…)
Bricks──▶ Unity Bricks─┘
이 결과로:
- 엔진과 카탈로그가 진정으로 분리됩니다. 한 엔진에서 다른 엔진으로 이동할 때 카탈로그를 그대로 둘 수 있습니다.
- 통제점이 카탈로그로 모입니다. 권한·감사·정책이 한 곳에서 결정되고, 어떤 엔진을 통해 접근하든 같은 결과를 봅니다.
- 워커가 영속 키를 들지 않습니다. vended credentials로 보안 표면이 줄어듭니다.
이 세 가지가 2024년 이후 모든 진영(Snowflake, Databricks, AWS, Google, Trino, Apache)이 REST Catalog 사양 위에 자신의 카탈로그를 다시 설계한 이유입니다.
2. Iceberg REST Catalog 사양
2.1 사양의 위치
Iceberg 공식 저장소의 open-api/rest-catalog-open-api.yaml이 정식 사양입니다. OpenAPI 3.0 형식으로, 다음 영역을 정의합니다.
- 네임스페이스 관리 — 데이터베이스/스키마 격리 단위.
- 테이블 라이프사이클 — 생성·조회·이름변경·삭제.
- 메타데이터 커밋 — 새 metadata.json을 원자적으로 적용.
- 인증·자격 증명 vending — OAuth2/SigV4/JWT 기반 인증, 단명 스토리지 자격 증명 발급.
- 트랜잭션 — 멀티 테이블 커밋(서버 구현체에 따라 선택적).
- 뷰 / 멀티-테이블 트랜잭션 / 머티리얼라이즈드 뷰 — 사양 v1.5+ 이후 점진 도입.
2.2 주요 엔드포인트 (요약)
GET /v1/config 서버 설정 협상 (기본 위치, vended 옵션 등)
GET /v1/{prefix}/namespaces 네임스페이스 목록
POST /v1/{prefix}/namespaces 네임스페이스 생성
GET /v1/{prefix}/namespaces/{ns} 네임스페이스 메타정보
DELETE /v1/{prefix}/namespaces/{ns} 네임스페이스 삭제
GET /v1/{prefix}/namespaces/{ns}/tables 테이블 목록
POST /v1/{prefix}/namespaces/{ns}/tables 테이블 생성
GET /v1/{prefix}/namespaces/{ns}/tables/{table} 현재 metadata 가져오기
POST /v1/{prefix}/namespaces/{ns}/tables/{table} metadata 갱신 (commit)
DELETE /v1/{prefix}/namespaces/{ns}/tables/{table} 테이블 삭제
POST /v1/{prefix}/namespaces/{ns}/register 외부에서 생성된 metadata.json 등록
POST /v1/{prefix}/transactions/commit 멀티 테이블 트랜잭션
GET /v1/oauth/tokens OAuth2 토큰 발급
{prefix}는 카탈로그·워크스페이스 식별자입니다(구현체에 따라 사용 여부 다름).
2.3 메타데이터 커밋의 흐름
REST Catalog의 핵심은 "어떻게 metadata.json 포인터를 원자적으로 바꾸는가" 입니다.
[Client] ─ "현재 metadata 위치 알려줘" ──▶ [REST Server]
│
├ 백엔드(예: Postgres)에서
│ current_metadata_location 조회
▼
[Client] ◀ 현재 metadata.json 위치 ──── [REST Server]
│
│ S3에서 metadata.json 다운로드
│ 새 데이터 파일 쓰기
│ 새 metadata.json 생성·업로드
▼
[Client] ─ "이전 위치 X 였는데, 새 위치 Y 로 갱신해줘" ──▶ [REST Server]
│
├ 백엔드 트랜잭션:
│ UPDATE table
│ SET metadata_location = 'Y'
│ WHERE metadata_location = 'X';
├ 0행 갱신이면 → 409 CONFLICT
└ 1행 갱신이면 → 200 OK
▼
[Client] ◀ 200 OK / 409 CommitFailedException ────── [REST Server]
이 모델의 의미:
- 클라이언트는 잠금을 들지 않는다. 동시 작성 시 마지막 갱신만 성공하고 나머지는 충돌로 거절됩니다.
- 충돌 처리는 클라이언트의 재시도 책임입니다. Iceberg 라이브러리가
commit.retry.*속성으로 자동 재시도합니다. - 백엔드의 트랜잭션 보장이 곧 카탈로그의 정합성 보장입니다. Postgres·MySQL·DynamoDB 같은 트랜잭션 지원 백엔드를 선택하는 것이 표준입니다.
2.4 Vended Credentials — 자격 증명 위임
REST Catalog 사양의 또 다른 핵심 기능입니다.
[Client] ─ "테이블 events 읽기 위해 metadata.json 위치 + 스토리지 자격 줘" ─▶ [REST Server]
│
├ 권한 검사 (events 테이블 read 권한 있나)
├ 통과하면 AssumeRole / GenerateAccessToken
│ 결과 단명 자격 증명 발급 (예: 1시간)
▼
[Client] ◀ {
"metadata-location": "s3://...",
"config": {
"s3.access-key-id": "...",
"s3.secret-access-key": "...",
"s3.session-token": "...",
"s3.signer.endpoint": "..."
}
} ───────────────────────────────────────────────────── [REST Server]
장점:
- 워커는 영속 IAM 키를 보유하지 않습니다. 보안 표면 축소.
- 권한이 카탈로그에서 일관됩니다. "events 테이블 읽을 수 있다 = 그 테이블의 S3 prefix에 한해 단명 자격이 발급된다".
- 클라우드 별 자격 표준을 카탈로그가 흡수합니다. S3·ADLS·GCS 각각의 토큰 발급 차이를 클라이언트가 알 필요 없습니다.
2.5 인증 모델
REST Catalog 자체에 접근하기 위한 인증은 보통 다음 중 하나입니다.
- OAuth2 (Client Credentials Grant) —
/v1/oauth/tokens에서 토큰을 받아Authorization: Bearer ...헤더로 호출. - SigV4 — AWS 호환 카탈로그(예: Glue REST endpoint).
- mTLS — 사내 환경에서 클라이언트 인증서 기반.
- 외부 IdP 통합 — Okta·Entra·Keycloak 같은 OIDC IdP와 연동.
OAuth2는 가장 일반적이며, 거의 모든 구현체가 지원합니다.
# 토큰 발급
curl -X POST https://catalog.example.com/v1/oauth/tokens \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=client_credentials" \
-d "client_id=svc-spark-prod" \
-d "client_secret=..." \
-d "scope=catalog"
# 응답
{ "access_token": "eyJ...", "token_type": "Bearer", "expires_in": 3600 }3. 주요 구현체
REST Catalog 사양을 구현한 오픈소스 서버는 2024년 이후 빠르게 늘었습니다. 주요 후보를 정리합니다.
3.1 Apache Polaris
- 출신 — Snowflake가 2024년 공개, ASF에 기증 → Apache Polaris로 인큐베이션 진행 후 Top-Level.
- 언어 — Java(Dropwizard / Quarkus 기반).
- 백엔드 — JDBC(Postgres 권장), in-memory(테스트용).
- 권한 모델 — RBAC + Principal·Role·Privilege 계층. 카탈로그·네임스페이스·테이블 단위로 세밀.
- 클라우드 — S3·ADLS·GCS 모두 vended credentials 지원.
- 포지셔닝 — Snowflake와 외부 엔진을 같은 카탈로그로 묶기 위해 시작됐지만, Snowflake 의존 없이 독립적으로 사용 가능.
3.2 Unity Catalog OSS
- 출신 — Databricks가 2024년 Unity Catalog를 오픈소스로 공개.
- 언어 — Java + Scala.
- 백엔드 — JDBC.
- 권한 모델 — Databricks Unity와 동일한 3-레벨(catalog.schema.table) 모델 + ABAC 일부.
- 클라우드 — S3·ADLS·GCS.
- 포지셔닝 — Databricks 환경과의 호환을 유지하면서 외부 엔진 공유. UC가 Iceberg와 Delta를 동시에 다룬다는 점이 차별점.
3.3 Lakekeeper
- 출신 — Rust 기반의 경량 REST Catalog. 2024년부터 빠르게 성장.
- 언어 — Rust.
- 백엔드 — Postgres.
- 권한 모델 — OpenFGA 기반 fine-grained 권한(관계 기반 ABAC).
- 장점 — 메모리 footprint가 작고 cold start가 빠름, k8s 배포 친화적.
- 포지셔닝 — JVM 카탈로그 대비 경량성·성능 우위를 강조.
3.4 Project Nessie
- 출신 — Dremio가 2020년 시작.
- 특징 — Git-like 브랜치/머지 의미론을 카탈로그 수준에서 제공. Iceberg V2의 브랜치/태그와 별개로 카탈로그 단위 브랜치를 만들 수 있음.
- 언어 — Java(Quarkus).
- 백엔드 — RocksDB·Postgres·MongoDB.
- REST Catalog 호환 — Iceberg REST 사양을 지원하면서, Nessie 고유 API도 함께 노출.
- 포지셔닝 — 멀티-테이블 트랜잭션·실험 분기에 강점.
3.5 Apache Gravitino
- 출신 — Datastrato가 2024년 ASF에 기증.
- 특징 — Iceberg REST 카탈로그뿐 아니라 다양한 카탈로그·메타스토어를 통합하는 "메타데이터 레이크" 지향(HMS, JDBC, Kafka 스키마 레지스트리 등).
- 언어 — Java.
- 포지셔닝 — Iceberg에 국한되지 않는 사내 메타데이터 통합 플레인.
3.6 Tabular (Iceberg 창립자)
- 출신 — Iceberg 창립자들이 만든 SaaS. 2024년 Databricks 인수.
- 상태 — 인수 후 Databricks 내 Unity Catalog로 흡수. 신규 가입 중단.
- 참고 — 사양·아키텍처 영향이 크지만, 신규 도입 대안에서는 제외.
3.7 클라우드 관리형
- AWS Glue (with Iceberg REST endpoint) — Glue에 REST 호환 endpoint가 추가됨. 운영 부담 없음, AWS 종속.
- Snowflake Polaris (관리형) — Polaris를 Snowflake가 호스팅하는 형태.
- Databricks Unity (관리형) — Databricks가 호스팅하는 Unity.
- Google BigLake — Iceberg REST 사양을 부분 지원.
3.8 구현체 비교 매트릭스 (2026년 5월 기준)
| 항목 | Polaris | Unity OSS | Lakekeeper | Nessie | Gravitino | Glue REST |
|---|---|---|---|---|---|---|
| 라이선스 | Apache 2.0 | Apache 2.0 | Apache 2.0 | Apache 2.0 | Apache 2.0 | (관리형) |
| 언어 | Java | Java | Rust | Java | Java | (관리형) |
| 백엔드 | JDBC | JDBC | Postgres | Rocks/PG/Mongo | JDBC | AWS 관리 |
| REST 사양 호환 | 완전 | 완전 | 완전 | 완전 | 부분~완전 | 부분 |
| Vended credentials | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| RBAC | ✓ | ✓ | ✓ (FGA) | ✓ | ✓ | IAM |
| 멀티 클라우드 | ✓ | ✓ | ✓ | ✓ | ✓ | AWS만 |
| 브랜치/머지(카탈로그) | ✗ | ✗ | ✗ | ✓ | ✗ | ✗ |
| 비-Iceberg 카탈로그 통합 | ✗ | Delta | ✗ | ✗ | ✓ (다중) | Glue 자산 |
| 운영 부담 | 중 | 중 | 낮음 | 중 | 중 | 없음 |
각 구현체는 발전 중이며, 위 표는 일반화된 요약입니다. 도입 시점에는 각 프로젝트의 최신 릴리스 노트를 확인하길 권합니다.
4. 자체 호스팅 vs 관리형
4.1 자체 호스팅을 고려해야 하는 경우
- 멀티 클라우드 / 온프레미스 혼재 — 한 클라우드 관리형에 묶이지 않아야 할 때.
- 권한·감사 모델을 사내 표준에 맞춰야 할 때 — 사내 OIDC IdP·Ranger·OPA와 통합 필요.
- 데이터 거주성(data residency) 요건 — 메타데이터 자체도 특정 리전에 있어야 할 때.
- 카탈로그가 사내 데이터 플랫폼의 통제점이 되어야 할 때 — 외부 SaaS에 위임할 수 없는 정책 결정.
4.2 관리형이 적합한 경우
- 단일 클라우드 중심 환경 + 빠른 도입이 우선 — Glue REST, Snowflake Polaris, Databricks Unity 관리형.
- 운영 인력이 제한적 — 카탈로그 자체를 운영할 여력이 없을 때.
- 사양 진화를 따라가는 부담을 외주화하고 싶을 때 — REST 사양은 빠르게 발전 중이라 자체 호스팅은 지속적 패치가 필요.
4.3 비교 요약
| 측면 | 자체 호스팅 | 관리형 |
|---|---|---|
| 초기 구축 비용 | 높음 | 낮음 |
| 운영 인력 | 필요 | 최소 |
| 권한·정책 유연성 | 매우 높음 | 제한적 (벤더 모델 따름) |
| 멀티 클라우드 | 자유로움 | 보통 단일 클라우드 |
| 데이터 거주성 통제 | 자유로움 | 벤더 정책에 의존 |
| 사양 업데이트 | 직접 따라야 함 | 자동 |
| 비용 모델 | 인프라 + 인력 | 사용량 기반 |
5. 자체 호스팅 운영 패턴
5.1 배포 토폴로지
┌──────────────┐
외부 LB ──▶ │ REST Server │ × N (수평 확장, stateless)
│ (Polaris / │
│ Lakekeeper)│
└──────┬───────┘
│
┌──────────┼──────────┐
▼ ▼
┌─────────┐ ┌────────────┐
│ Postgres│ │ Object │
│ HA │ │ Storage │
│ (Primary│ │ (S3 / ADLS │
│ + Repl) │ │ / GCS) │
└─────────┘ └────────────┘
▲
│ vended credentials
┌─────┴──────┐
│ IAM / KMS │
└────────────┘
핵심 결정 사항:
- REST Server는 stateless로 두고, 메타데이터 상태는 백엔드 DB가 보유합니다.
- 수평 확장 — 부하 증가에 따라 인스턴스를 추가. 보통 2~6대로 시작해 트래픽에 맞춰 조정.
- 백엔드 DB HA — Postgres는 streaming replication + 자동 페일오버(예: Patroni, Cloud SQL).
- 객체 스토리지의 lifecycle 정책을 카탈로그 정리 작업과 정합하게 설정.
5.2 인증·권한 통합
OIDC IdP(예: Okta, Entra, Keycloak)를 카탈로그 앞단에 두는 패턴이 일반적입니다.
Spark/Trino 워커 ─▶ IdP에서 service account 토큰 발급
│
▼
REST Catalog (Bearer 토큰 검증)
│
├ 사내 정책(예: OPA)으로 권한 평가
▼
Vended credentials 발급 (S3/ADLS/GCS)
핵심:
- 사람과 서비스 모두 IdP 발급 토큰만 사용.
- 카탈로그는 토큰 → principal → 권한 매핑만 책임.
- vended credentials는 카탈로그가 발급(테이블 단위 prefix·만료 시각 제한).
5.3 백업·복구
카탈로그의 두 자산을 모두 백업해야 합니다.
- 백엔드 DB — Postgres point-in-time recovery(PITR). 일별 베이스 + WAL 보존. 통상 14~30일.
- 객체 스토리지의 metadata.json·manifest — 객체 스토리지 자체의 버전 관리 + 적절한 lifecycle.
복구 시나리오:
- 카탈로그 DB 손상: DB 복구 → REST Server 재기동 → 카탈로그가 옛 metadata.json 위치를 다시 가리킴.
- 테이블 메타데이터 손상: 객체 스토리지의 옛 metadata.json으로 카탈로그 포인터를 교체(
registerAPI). 시간여행과 동일 메커니즘.
5.4 모니터링 지표
| 지표 | 의미 | 적신호 |
|---|---|---|
| 커밋 RPS | 카탈로그 부하 | 베이스라인 대비 급증 |
| 커밋 p95 지연 | 백엔드 DB 성능 | 500 ms 초과 |
| 충돌(409) 비율 | 동시 작성 압력 | 5% 초과 |
| OAuth 토큰 발급 RPS | 인증 부하 | 베이스라인 대비 급증 |
| 백엔드 DB connections | 풀 사이즈 | 80% 초과 |
| Vended credential 발급 빈도 | 정상 트래픽 | 비정상 패턴 감지 |
| 5xx 비율 | 서비스 건강도 | 0.1% 초과 |
| 평균 metadata.json 크기 | 메타 폭증 신호 | 8 MiB 초과 시 만료 정책 점검 |
5.5 업그레이드 전략
REST 사양은 빠르게 발전합니다. 안전한 업그레이드 패턴:
- 카나리 인스턴스 — 새 버전을 1대만 띄우고 트래픽 5% 라우팅. 1~7일 관찰.
- 호환성 점검 — 사내 사용 엔진들이 새 사양 응답을 정상 해석하는지.
- 백엔드 마이그레이션 — 사양 변경이 DB 스키마를 요구하면 별도 마이그레이션 잡으로 분리.
- 롤백 계획 — DB 마이그레이션 전 스냅샷 보존, 롤백 절차 사전 검증.
6. 엔진 연결 예시
6.1 Apache Spark
spark.conf.set("spark.sql.catalog.lake", "org.apache.iceberg.spark.SparkCatalog")
spark.conf.set("spark.sql.catalog.lake.catalog-impl", "org.apache.iceberg.rest.RESTCatalog")
spark.conf.set("spark.sql.catalog.lake.uri", "https://catalog.example.com/v1")
spark.conf.set("spark.sql.catalog.lake.warehouse", "s3://data-lake/warehouse")
spark.conf.set("spark.sql.catalog.lake.credential",
"svc-spark-prod:SECRET") // OAuth2 client_credentials
spark.conf.set("spark.sql.catalog.lake.scope", "catalog")
spark.conf.set("spark.sql.catalog.lake.token-refresh-enabled", "true")
spark.conf.set("spark.sql.catalog.lake.io-impl", "org.apache.iceberg.aws.s3.S3FileIO")
spark.sql("USE lake.db")
spark.sql("SELECT count(*) FROM events").show()6.2 Trino
catalog/iceberg.properties:
connector.name=iceberg
iceberg.catalog.type=rest
iceberg.rest-catalog.uri=https://catalog.example.com/v1
iceberg.rest-catalog.warehouse=s3://data-lake/warehouse
iceberg.rest-catalog.security=OAUTH2
iceberg.rest-catalog.oauth2.credential=svc-trino-prod:SECRET
iceberg.rest-catalog.oauth2.scope=catalog
iceberg.rest-catalog.vended-credentials-enabled=true
fs.native-s3.enabled=true6.3 Apache Flink
CREATE CATALOG lake WITH (
'type'='iceberg',
'catalog-impl'='org.apache.iceberg.rest.RESTCatalog',
'uri'='https://catalog.example.com/v1',
'warehouse'='s3://data-lake/warehouse',
'credential'='svc-flink-prod:SECRET',
'scope'='catalog',
'io-impl'='org.apache.iceberg.aws.s3.S3FileIO'
);
USE CATALOG lake;
SELECT count(*) FROM db.events;6.4 PyIceberg
from pyiceberg.catalog.rest import RestCatalog
catalog = RestCatalog(
name="lake",
**{
"uri": "https://catalog.example.com/v1",
"warehouse": "s3://data-lake/warehouse",
"credential": "svc-pyiceberg:SECRET",
"scope": "catalog",
},
)
table = catalog.load_table(("db", "events"))
df = table.scan(row_filter="event_ts >= '2026-05-01'").to_arrow()
print(df.num_rows)6.5 Snowflake (Polaris 외부 카탈로그)
CREATE OR REPLACE CATALOG INTEGRATION ext_polaris
CATALOG_SOURCE = POLARIS
TABLE_FORMAT = ICEBERG
REST_CONFIG = (
CATALOG_URI = 'https://catalog.example.com/v1',
CATALOG_NAME = 'lake'
)
REST_AUTHENTICATION = (
TYPE = OAUTH,
OAUTH_CLIENT_ID = 'svc-snowflake-prod',
OAUTH_CLIENT_SECRET = '...',
OAUTH_ALLOWED_SCOPES = ('catalog')
)
ENABLED = TRUE;
CREATE ICEBERG TABLE events
EXTERNAL_VOLUME = 'vol_data_lake'
CATALOG = 'ext_polaris'
CATALOG_TABLE_NAME = 'events'
CATALOG_NAMESPACE = 'db';
SELECT count(*) FROM events;7. HMS / Glue에서 REST Catalog로 마이그레이션
7.1 두 가지 접근
-
백엔드 어댑터 — 기존 HMS/Glue 위에 REST Server를 얹는다.
- Polaris·Lakekeeper 등이 HMS를 백엔드로 둘 수 있음(구현체별 지원 확인).
- 데이터·메타데이터 위치는 그대로 두고, 엔진만 REST endpoint를 보게 함.
- 점진 전환의 표준 패턴.
-
메타데이터 재등록 — 완전히 새 백엔드로 옮긴다.
- 새 REST Catalog(예: Polaris with Postgres)를 별도 구축.
- 기존 테이블의 metadata.json 위치를
registerAPI로 등록. - 옛 카탈로그를 일정 기간 read-only로 유지 → 모든 엔진 전환 확인 후 폐지.
7.2 단계별 체크리스트
0단계 — 인벤토리
- 현재 카탈로그(HMS/Glue) 내 테이블 수, 네임스페이스 구조
- 사내 사용 엔진 목록과 카탈로그 클라이언트 종류
- 현재 권한 모델(Ranger, Lake Formation, Unity 등)을 어떻게 REST Catalog에 매핑할지
1단계 — 그림자(shadow) 카탈로그 구축
- REST Server 인스턴스 N대 배포
- 백엔드 DB(HMS 어댑터 또는 신규 Postgres) 구성
- OIDC IdP / OAuth 통합 검증
- vended credentials의 IAM 역할 설계 및 권한 부여
2단계 — 한 도메인 시범 전환
- 비핵심 도메인 1개를 REST Catalog로 전환
- 두 엔진(예: Spark + Trino)에서 동일 결과 검증
- 운영 자동화(컴팩션·만료) 잡이 새 카탈로그에서 정상 동작 확인
- 권한·감사 정책이 의도대로 적용되는지 검증
3단계 — 핵심 도메인 점진 전환
- 도메인 단위로 전환, 옛 카탈로그를 일정 기간 병행 유지
- 사내 BI·ML 파이프라인을 새 endpoint로 이전
- 모든 워커의 IAM 키를 vended credentials 모델로 교체
4단계 — 옛 카탈로그 폐지
- 새 카탈로그가 단일 진실 원천(SSOT)임을 사내 공지
- 옛 카탈로그 read-only → 폐지
- 옛 카탈로그용 IAM 자격·서비스 계정 정리
8. 흔한 실수와 함정
- 카탈로그 없이 시작 — 파일 시스템 카탈로그로 시작했다가 멀티 엔진 도입 시 마이그레이션 부담이 큼. 처음부터 REST Catalog 권장.
- vended credentials를 꺼두기 — "기존 IAM 키 그대로 쓰자"는 결정은 REST Catalog의 보안 이득을 절반 이상 포기하는 것과 같음.
- 백엔드 DB 단일 장애점 — REST Server는 stateless라 스케일이 쉽지만, 백엔드 DB의 HA가 곧 카탈로그의 HA. 별도 설계 필요.
- 권한 모델을 사양에 끼워 맞추기 — 사내 정책이 REST 사양에 직접 표현되지 않으면 OPA 같은 외부 정책 엔진을 함께 둠. 사양만 보고 무리하게 단순화하지 않음.
- 사양 업데이트를 따라가지 않기 — REST 사양은 빠르게 발전하므로 6~12개월마다 카탈로그를 업그레이드해야 새 기능(예: 멀티 테이블 트랜잭션, MV 사양)을 받을 수 있음.
- 카탈로그 모니터링 부재 — 커밋 지연·충돌·5xx를 보지 않으면, 카탈로그가 데이터 파이프라인 전체의 병목이 된 뒤에야 발견함.
9. 도입 권고
9.1 신규 멀티-엔진 Lakehouse
- Polaris / Unity OSS / Lakekeeper 중 하나를 채택해 처음부터 REST 표준 위에서 시작.
- 백엔드는 Postgres + HA, OAuth2 + 사내 IdP.
- vended credentials 필수.
9.2 단일 클라우드 + 빠른 도입
- AWS 중심 → Glue REST endpoint로 시작, 필요 시 자체 호스팅으로 전환.
- Snowflake 중심 → 관리형 Polaris.
- Databricks 중심 → 관리형 Unity.
9.3 HMS / Glue 자산이 큰 환경
- 어댑터형 REST(HMS를 백엔드로 두는 Polaris/Lakekeeper) → 점진 전환 → 새 백엔드로 이동.
- 한 번에 옮기지 않음. 시범 도메인 → 핵심 도메인 → 폐지의 순서.
9.4 데이터 거주성·보안 요건이 큰 환경
- 자체 호스팅이 사실상 유일한 선택. Lakekeeper(경량) 또는 Polaris(기능 풍부) 검토.
- 사내 IdP·정책 엔진(OPA·Ranger)과의 통합을 우선 설계.
10. 정리
- REST Catalog는 사양이고, 그 사양을 구현한 여러 오픈소스 서버가 존재합니다. "카탈로그를 고른다"는 곧 "어떤 구현체를 고를 것인가"의 문제입니다.
- 핵심 가치는 세 가지입니다 — 엔진과 카탈로그 분리, 카탈로그가 통제점이 됨, vended credentials로 보안 표면 축소.
- 신규 멀티-엔진 환경이라면 REST Catalog로 시작하는 것이 사실상 표준입니다. 단일 클라우드·빠른 도입이 우선이면 관리형, 멀티 클라우드·정책 유연성이 우선이면 자체 호스팅.
- 카탈로그는 stateless REST 서버 + 트랜잭션 백엔드 + IdP + 객체 스토리지의 조합으로 운영합니다. 모니터링·백업·업그레이드 전략을 처음부터 설계에 포함합니다.
REST Catalog는 Iceberg의 사양 그 자체보다도 Lakehouse 운영 모델을 바꾸는 결정적 요소입니다. 카탈로그가 통제점이 되면 권한·감사·정책이 한 곳으로 모이고, 새 엔진을 추가하는 비용이 극적으로 줄어듭니다. 이것이 2026년 시점에서 거의 모든 데이터 플랫폼이 카탈로그를 다시 설계하고 있는 이유입니다.
함께 보면 좋은 글
- Apache Iceberg 백서 — 차세대 Lakehouse 테이블 포맷의 구조와 도입 전략
- Apache Iceberg 사양 버전 비교 — V1·V2·V3
- Delta Lake 완벽 가이드 — Delta Table 개념부터 Iceberg 비교까지
참고 자료
- Iceberg REST Catalog OpenAPI 사양 — Iceberg 저장소
open-api/rest-catalog-open-api.yaml - Apache Polaris — polaris.apache.org
- Unity Catalog OSS — unitycatalog.io
- Lakekeeper — lakekeeper.io
- Project Nessie — projectnessie.org
- Apache Gravitino — gravitino.apache.org
- AWS Glue Iceberg REST endpoint 문서
- Iceberg 공식 사양 — iceberg.apache.org/spec