Pinterest, 자동화된 스키마 변경 관리로 데이터 일관성 확보
분산 CDC 파이프라인에서 스키마 변경(Schema Change)은 코드, 메타데이터, 스토리지 전반에 걸쳐 일관성을 유지해야 하는 복잡한 문제임
자동화된 스키마 변경 프레임워크를 구축하여 Kafka, Flink, Spark, Iceberg 전반에 걸쳐 변경 사항을 안전하고 반복 가능하게 전파함
단계적 수렴 모델(Phased Convergence Model)을 통해 파이프라인 가용성을 유지하며 점진적으로 스키마 및 데이터 정합성을 복구함
SLA 기반의 최종 일관성(Eventual Consistency)을 제공하며, 제로갭 스키마 변경(Zero-Gap Schema Evolution)을 목표로 함
스키마 변경의 복잡성과 자동화 필요성
Pinterest의 데이터 수집 파이프라인은 CDC 소스 설정부터 Kafka 프로비저닝, Flink/Spark 코드 생성, Iceberg 테이블 생성, 히스토리 부트스트랩까지 여러 단계가 스키마(Schema)에 긴밀하게 의존함. 이러한 환경에서 스키마 변경은 단순히 DDL 업데이트를 넘어, 코드, 메타데이터, 스토리지 전반에 걸친 통제되고 감사 가능한 방식으로 반영되어야 함. 수동 업데이트는 데이터 드리프트(Data Drift) 및 불일치(Inconsistency) 위험을 증가시키므로, 안전하고 확장 가능한 자동화 프레임워크 구축이 필수적이었음.
SLA 기반 자동화된 스키마 변경 워크플로우
Pinterest는 SLA(Service Level Agreement) 기반의 자동화된 스키마 변경 프레임워크를 통해 문제를 해결함. 이 프레임워크는 Kafka, Flink, Spark, Iceberg 전반에 걸쳐 지원되는 스키마 변경의 자동 전파, PR 기반 롤아웃(Rollout)과 감사 기능, 온라인/오프라인 스키마 간 최종 일관성(Eventual Consistency)을 보장함. 핵심은 스키마 변경을 원자적(Atomic) 연산이 아닌, 다단계 수렴 프로세스(Multi-stage Convergence Process)로 취급하여 파이프라인 가용성을 유지하면서 점진적으로 데이터 정합성을 복구하는 것임.
단계적 수렴 모델(Phased Convergence Model)의 작동 방식
스키마 변경은 3단계 수렴 모델을 따름. 1단계(스키마 발산)에서는 Iceberg 스키마를 먼저 업데이트하고, 생성된 Flink/Spark 코드는 컬럼 이름으로 접근하므로 기존 작업은 null을 반환하며 계속 실행됨. 2단계(코드 수렴)에서는 Spark 코드를 먼저 업데이트하여 백필(Backfill)을 시작하고, 이후 Flink 코드를 업데이트하여 새로운 레코드를 올바르게 파싱함. 3단계(데이터 수렴)에서는 Spark가 히스토리 데이터를 백필하고 Flink가 새 데이터를 처리하여 최종적으로 온라인/오프라인 스키마 및 데이터 일관성을 복구함. 이 방식은 스키마 전파와 데이터 정합성 복구를 분리하여 시스템의 안정성을 높임.
지원되는 스키마 변경 유형 및 제약 조건
안정성과 운영 관리 용이성을 위해 자동화된 스키마 변경은 명시적으로 추가적인 변경(Additive Changes)으로 제한됨. 이는 기존 소비자 호환성을 유지하고 히스토리 재처리 복잡성을 최소화하기 위한 의도적인 트레이드오프임. 숫자 타입의 정밀도 확장과 같이 의미론적 변경이 없는 제한적인 타입 변경만 허용되며, 다른 모든 타입 변경이나 기본값(Default Value)이 있는 새 컬럼 추가 등은 수동 마이그레이션 또는 전체 백필이 필요함. PR 체크를 통한 자동화된 검증으로 지원되지 않는 변경이 파이프라인에 유입되는 것을 방지함.
스키마 변경 감지 및 PR 기반 워크플로우
스키마 변경은 푸시(Push) 기반 DDL CDC 메시지 또는 일일 비교(Pull) 작업으로 감지됨. 감지 시 Iceberg 스키마 업데이트, Flink/Spark 코드 재생성, 메타데이터 업데이트, PR 생성이 자동화됨. 모든 변경 사항은 PR 기반 워크플로우를 거치므로 감사 추적성(Auditability), 버전 관리(Versioning), 안전한 운영 모델을 확보할 수 있음. 원시 소비자 테이블은 변경되지 않으며, 스키마 인식 부분은 변환 및 오프라인 스토리지 계층부터 시작됨.
미지원 및 엣지 케이스 처리 전략
기본값이 있는 컬럼, 민감 데이터 변경, 기본 키 변경 등 지원되지 않거나 모호한 스키마 변경은 수동 개입 또는 별도 복구 절차를 따름. 특히 MySQL의 CREATE TABLE 문법 차이로 인한 모호성은 빌드 타임의 Skeema 활용 및 배포 시점의 감사 메커니즘을 통해 해결함. 동시 스키마 변경은 직렬화된 큐를 통해 처리하여 경합 조건을 방지하며, Spark 실패 시에는 워터마크 기반으로 재시도하고 Flink 파싱 실패 시에는 CI/CD에서 롤아웃을 차단하여 복구함. 심각한 실패 시에는 온보딩 시스템을 통한 전체 복구(Full Recovery) 절차를 수행함.