반정형 데이터, CDC 파이프라인, 개발자 프레임워크 — Stream/Task부터 Snowpark까지
55 Snowflake Interview Questions Hiring DEs Actually Ask (2026) — 미상 (데이터 엔지니어 인터뷰 준비 블로그, 2026) Core Architecture & Fundamentals Q10 (p.4); Advanced Transformation & Features Q41-Q48 (pp.14-16); [보조] Databricks vs Snowflake - Data Engineering and ETL / Machine Learning and AI Capabilities: Snowflake 절 (pp.8-10)
이 모듈을 다 읽으면
- Stream과 Task가 어떻게 조합되어 증분 ELT 파이프라인을 구성하는지 설명할 수 있다
- UDF와 Stored Procedure의 목적(값 반환 vs 부수효과 수행) 차이를 구분할 수 있다
- External Table과 최신 Iceberg Table의 차이(읽기 전용 vs 정식 쓰기 지원)를 설명할 수 있다
- Dynamic Table이 Stream+Task 수동 조합 대비 어떤 지점에서 대안이 되는지 설명할 수 있다
Snowflake는 VARIANT 타입으로 JSON 등 반정형 데이터를 스키마리스로 받아들여 자동으로 컬럼화하고, Stream(변경 추적)과 Task(스케줄 실행)를 조합해 증분 ELT 파이프라인을 구성할 수 있게 한다. UDF는 값을 반환하는 목적으로, Stored Procedure는 DDL/DML을 포함한 액션을 수행하는 목적으로 쓰이며, Snowpark는 Python/Java/Scala로 이 모든 로직을 DataFrame API 스타일로 작성해 SQL로 변환·실행하게 해준다. 원문이 다룬 External Table(읽기 전용) 이후에는 Snowflake가 쓰기까지 지원하는 네이티브 Iceberg Table을 도입했고, 여러 테이블 조인 결과를 자동 유지하는 Dynamic Table도 등장해 Stream+Task 수동 조합의 대안이 되고 있다.
반정형 데이터: VARIANT와 자동 컬럼화
Snowflake는 JSON, Avro, ORC, Parquet, XML 같은 반정형 포맷을 '1급 시민'으로 지원한다. VARIANT 데이터 타입을 사용하면 사전에 스키마를 정의하지 않고도 이런 포맷을 테이블에 그대로 로드할 수 있으며, Snowflake의 옵티마이저가 내부적으로 데이터를 자동 평탄화(flatten)하고 컬럼화(columnize)해, 구조화된 관계형 데이터에 필적하는 성능으로 표준 SQL 표기법을 사용해 JSON 필드를 조회할 수 있게 한다(모듈 6에서 다룬 VARIANT 16MB 제한과 함께 기억해야 한다).
핵심 포인트
- VARIANT 타입은 스키마를 사전 정의하지 않고 JSON 등 반정형 데이터를 그대로 로드할 수 있게 한다
- 옵티마이저가 내부적으로 데이터를 자동 평탄화·컬럼화해 구조화 데이터와 비슷한 성능을 낸다
- 표준 SQL 표기법으로 VARIANT 안의 JSON 필드를 직접 조회할 수 있다
CDC 파이프라인: Stream과 Task
Stream은 테이블에 대한 변경 데이터 캡처(CDC) 정보를 기록하는 객체다. Stream 자체는 데이터를 담지 않고, 마지막으로 그 Stream이 '소비'된 시점 이후 어떤 행이 삽입·수정·삭제되었는지만 추적한다. 이는 증분 ELT 파이프라인에서 핵심적인데, 원본 테이블 전체를 매번 재처리하는 대신 새로 변경된 데이터만 처리할 수 있게 해주기 때문이다.
Task는 특정 시각 또는 반복 주기(cron과 유사)로 SQL 문이나 Stored Procedure를 실행하는 내장 스케줄러다. SYSTEM$STREAM_HAS_DATA 조건과 결합하면 'Stream에 처리할 데이터가 있을 때만' Task가 실행되도록 만들 수 있고, 여러 Task를 체이닝한 'Task Graph'(DAG)로 한 Task의 성공적 완료가 다음 Task를 트리거하게 만들 수도 있다. 또한 'Streams on Views' 기능을 사용하면 원본 테이블이 아니라 조인·변환된 뷰의 결과 변경까지 추적할 수 있어, 복잡한 로직에 의존하는 증분 파이프라인도 구성할 수 있다.
Task와 외부 오케스트레이터(Airflow 등)의 선택 기준도 명확하다 — 순수 SQL 자동화로 충분한 단순한 시나리오라면 Task가 가볍고 설정이 쉽지만, Python 스크립트·Spark 잡·Snowflake 쿼리를 넘나드는 복잡한 크로스 시스템 의존성과 세밀한 재시도 로직이 필요하다면 외부 오케스트레이터가 더 나은 가시성과 에러 핸들링을 제공한다.
핵심 포인트
- Stream은 데이터를 담지 않고 마지막 소비 시점 이후의 삽입/수정/삭제만 추적하는 CDC 객체다
- Task는 SQL/Stored Procedure를 스케줄 실행하며, SYSTEM$STREAM_HAS_DATA와 결합해 조건부 실행이 가능하고 Task Graph로 체이닝할 수 있다
- 단순 SQL 자동화는 Task로, 크로스 시스템 의존성이 복잡한 파이프라인은 Airflow 같은 외부 오케스트레이터로 처리하는 것이 적합하다
UDF vs Stored Procedure, Snowpark
UDF(User-Defined Function)는 값을 계산해 반환하는 것이 주목적이며, SELECT 문 안에서 호출된다(예: SELECT my_udf(col) FROM table). UDF는 부수효과가 없는(side-effect free) 것을 지향한다.
Stored Procedure는 반대로 테이블 삭제나 ETL 작업 실행 같은 '액션'을 수행하는 것이 주목적이며, CALL 명령으로 독립적으로 호출된다. UDF와 달리 DDL·DML 연산을 수행할 수 있다. 두 객체 모두 JavaScript, SQL, Python, Java, Scala로 절차적 로직(반복문, 분기, 오류 처리)을 작성할 수 있다.
Snowpark는 Python, Java, Scala에 네이티브 지원을 제공하는 개발자 프레임워크다. 개발자는 SQL을 직접 작성하는 대신 PySpark와 유사한 DataFrame API를 사용할 수 있고, 이 코드는 자동으로 SQL로 변환되어 Snowflake의 탄력적 컴퓨트 엔진에서 실행된다. 이는 SQL보다 함수형 프로그래밍을 선호하는 데이터 과학자·엔지니어에게 Snowflake를 매력적인 플랫폼으로 만드는 요소이며, Databricks가 대변하는 '개발자가 파티셔닝·셔플까지 직접 다루는' 방식과 대비되는, Snowflake 특유의 '내부 동작은 감춘 채 익숙한 API만 노출하는' 접근이기도 하다.
핵심 포인트
- UDF는 값을 반환하는 목적으로 SELECT 절에서 호출되며 부수효과가 없는 것을 지향한다
- Stored Procedure는 DDL/DML을 포함한 액션 수행이 목적이며 CALL로 독립 호출된다
- Snowpark는 Python/Java/Scala DataFrame API 코드를 자동으로 SQL로 변환해 Snowflake 엔진에서 실행한다
External Table에서 Iceberg Table로, 그리고 Dynamic Table — 보완(최신 기능)
원문(Q47)은 External Table까지만 설명한다 — 고객 소유 클라우드 스토리지(S3, GCS, Azure Blob)의 파일을 마치 Snowflake 내부 테이블처럼 표준 SQL로 조회하되, 데이터 자체는 Snowflake 스토리지로 로드되지 않는(읽기 전용) 기능이다. 탐색적 분석이나 '레이크하우스' 아키텍처에서 데이터를 원래 있던 위치에 그대로 둔 채 조회하고 싶을 때 유용하다고 설명한다.
보완 — 이후 Snowflake는 Apache Iceberg 포맷을 네이티브로 지원하는 Iceberg Table을 정식 출시했다. Iceberg Table은 고객 소유 클라우드 스토리지에 Iceberg 스펙으로 데이터를 저장하면서도, External Table과 달리 Snowflake에서 직접 쓰기(DML)까지 지원한다. 카탈로그도 Snowflake 자체를 쓰거나 외부 카탈로그(예: AWS Glue)를 선택할 수 있어, 다른 엔진(Spark, Trino 등)과 동일한 물리 데이터를 공유하는 진정한 레이크하우스 구성이 가능해졌다. 이는 다른 문서(모듈 11)에서 언급하는 'Snowflake가 Iceberg 역량을 흡수해 데이터 레이크에 가까워지고 있다'는 흐름과 정확히 일치한다.
또한 모듈 7에서 언급했듯, 여러 테이블을 조인한 결과를 자동으로 유지하고 싶을 때는 Materialized View(단일 테이블 한정)나 수작업 Stream+Task 조합 대신 Dynamic Table을 고려할 수 있다. Dynamic Table은 원하는 최종 결과를 SQL 쿼리로 선언하기만 하면 Snowflake가 내부적으로 증분 새로고침을 자동 관리해주는 선언적 테이블로, 복잡한 변경 추적 로직을 직접 작성해야 했던 Stream+Task 패턴의 대안으로 자리 잡았다.
핵심 포인트
- External Table은 고객 클라우드 스토리지의 파일을 SQL로 조회하는 읽기 전용 기능이다
- 보완: Iceberg Table은 Iceberg 스펙으로 저장된 데이터에 대해 Snowflake에서 쓰기(DML)까지 지원하며 외부 카탈로그도 선택할 수 있다
- 보완: Dynamic Table은 SQL 쿼리 선언만으로 여러 테이블 조인 결과의 증분 새로고침을 자동 관리해, Materialized View의 단일 테이블 제약과 Stream+Task 수작업의 대안이 된다