본문으로 건너뛰기
snowflake검색
SQL과 데이터

Streams 와 Tasks (변경 추적, 서버리스 태스크, 태스크 그래프)

테이블 변경분을 추적하는 Stream 의 종류와 오프셋, 오래됨(stale) 문제, 일정과 트리거로 SQL 을 돌리는 Task 의 서버리스와 사용자 관리 방식, 태스크 그래프, 실패 처리와 비용을 정리합니다.

StreamTaskCDC서버리스 태스크트리거 태스크태스크 그래프2026-10 기준, 약 9분상태 표시 설명

Stream: 무엇이 바뀌었나

Stream 은 테이블에 오프셋(책갈피) 을 하나 꽂아 두고, 그 뒤로 바뀐 행을 보여 주는 객체입니다. 데이터를 복사해 두는 것이 아니라 Time Travel 의 버전 정보를 이용합니다.

CREATE STREAM raw.orders_stream ON TABLE raw.orders;

SELECT *, METADATA$ACTION, METADATA$ISUPDATE, METADATA$ROW_ID
FROM raw.orders_stream;
메타데이터 열뜻
METADATA$ACTIONINSERT 또는 DELETE
METADATA$ISUPDATEUPDATE 가 DELETE 와 INSERT 쌍으로 표현된 경우 TRUE
METADATA$ROW_ID행의 고유 ID, 같은 행의 변경을 추적

종류

종류대상보여 주는 것
표준(standard)테이블, 뷰, Dynamic TableINSERT, UPDATE, DELETE 의 순 변경
추가 전용(append-only)테이블, 뷰INSERT 만. 변경이 많은 테이블에서 훨씬 가벼움
삽입 전용(insert-only)외부 테이블, Iceberg 테이블새로 추가된 파일의 행

오프셋은 언제 움직이나

스트림을 SELECT 만 해서는 오프셋이 움직이지 않습니다. 스트림을 읽는 DML 이 커밋될 때 오프셋이 앞으로 갑니다. 그래서 보통 아래처럼 MERGE 안에서 소비합니다.

MERGE INTO mart.orders t
USING (SELECT * FROM raw.orders_stream WHERE METADATA$ACTION = 'INSERT') s
  ON t.id = s.id
WHEN MATCHED THEN UPDATE SET t.status = s.status, t.amount = s.amount
WHEN NOT MATCHED THEN INSERT (id, status, amount) VALUES (s.id, s.status, s.amount);

주의 같은 스트림을 두 소비자가 나눠 쓰면 한쪽이 소비할 때 다른 쪽 변경분도 사라집니다. 소비자마다 스트림을 따로 만듭니다.

오래됨(stale)

스트림 오프셋이 원본 테이블의 Time Travel 보존 기간 밖으로 밀려나면 스트림이 stale 이 되어 읽을 수 없습니다. 이를 막기 위해 Snowflake 는 소비되지 않은 스트림이 있으면 보존 기간을 최대 MAX_DATA_EXTENSION_TIME_IN_DAYS(기본 14일)까지 자동으로 늘립니다. 그래도 그 기간 동안 소비하지 않으면 stale 이 됩니다.

SHOW STREAMS IN SCHEMA raw;   -- stale, stale_after 열 확인

2026년 9월에는 계정 전체 스트림을 볼 수 있는 ACCOUNT_USAGE.STREAMS 뷰가 추가되었습니다.

Task: 언제 무엇을 돌리나

Task 는 SQL 문 하나나 프로시저 호출을 일정이나 조건에 따라 실행합니다.

컴퓨트 방식

방식지정과금맞는 경우
서버리스WAREHOUSE 를 빼고 만듦실제 사용량, 서버리스 배수 0.9짧고 규칙적인 작업, 대부분
사용자 관리WAREHOUSE = ...웨어하우스 크레딧 (최소 60초)이미 늘 켜진 웨어하우스, XXLARGE 보다 큰 작업

서버리스 태스크는 Snowflake 가 이전 실행을 보고 크기를 고르고, 최대 크기는 XXLARGE 입니다. SERVERLESS_TASK_MAX_STATEMENT_SIZE 로 상한을, TARGET_COMPLETION_INTERVAL 로 끝나야 하는 시간을 줄 수 있습니다. 서버리스 태스크를 만들려면 계정 수준 EXECUTE MANAGED TASK 권한이, 태스크를 실행하려면 소유 역할에 EXECUTE TASK 권한이 필요합니다.

일정 방식

-- 10분마다
CREATE TASK ops.t_refresh SCHEDULE = '10 MINUTES' AS CALL ops.refresh_marts();

-- 매일 서울 시간 오전 6시
CREATE TASK ops.t_daily
  SCHEDULE = 'USING CRON 0 6 * * * Asia/Seoul'
  USER_TASK_MANAGED_INITIAL_WAREHOUSE_SIZE = 'SMALL'
  AS CALL ops.daily_job();

-- 트리거 태스크: 일정 없이 스트림에 데이터가 들어오면 실행
CREATE TASK ops.t_on_new_orders
  TARGET_COMPLETION_INTERVAL = '5 MINUTES'
  WHEN SYSTEM$STREAM_HAS_DATA('raw.orders_stream')
  AS MERGE INTO mart.orders ...;

ALTER TASK ops.t_on_new_orders RESUME;   -- 만들면 일시 중지 상태

WHEN 조건은 클라우드 서비스에서 평가되어, 조건이 거짓이면 웨어하우스를 깨우지 않습니다. 서버리스 트리거 태스크는 TARGET_COMPLETION_INTERVAL 이 필요합니다.

태스크 그래프 (DAG)

CREATE TASK ops.root SCHEDULE = 'USING CRON 0 * * * * UTC' AS SELECT 1;
CREATE TASK ops.load_a AFTER ops.root AS CALL ops.load('a');
CREATE TASK ops.load_b AFTER ops.root AS CALL ops.load('b');
CREATE TASK ops.build  AFTER ops.load_a, ops.load_b AS CALL ops.build_marts();
CREATE TASK ops.done   FINALIZE = ops.root AS CALL ops.notify();  -- 성공, 실패와 관계없이 마지막에

SELECT SYSTEM$TASK_DEPENDENTS_ENABLE('ops.root');   -- 그래프 전체 재개
  • 루트 태스크에만 일정이 있고, 하위는 AFTER 로 연결합니다.
  • 파이널라이저 태스크는 정리와 알림용입니다.
  • 2026년 3월에 이전 실행이 끝나지 않았을 때의 동작을 정하는 OVERLAP_POLICY 매개변수가 그래프에 추가되었습니다.
  • 태스크 사이에 값을 넘길 때는 SYSTEM$SET_RETURN_VALUE 와 SYSTEM$GET_PREDECESSOR_RETURN_VALUE 를 씁니다.

실패 처리

설정하는 일
SUSPEND_TASK_AFTER_NUM_FAILURES연속 실패 n 번이면 자동 일시 중지
TASK_AUTO_RETRY_ATTEMPTS실패한 그래프 실행을 자동 재시도 (기본 꺼짐)
ERROR_INTEGRATION실패 알림을 SNS, Event Grid, Pub/Sub 로
USER_TASK_TIMEOUT_MS한 번 실행의 제한 시간
SELECT name, state, error_code, error_message, scheduled_time, completed_time
FROM TABLE(INFORMATION_SCHEMA.TASK_HISTORY(RESULT_LIMIT => 100))
WHERE state = 'FAILED'
ORDER BY scheduled_time DESC;

Serverless Tasks Flex

일정 시각에 딱 맞춰 돌 필요가 없는 작업을 정해진 창(window) 안에서 Snowflake 가 고른 시각에 돌리는 방식입니다. SCHEDULING_MODE = 'FLEXIBLE' 과 TARGET_COMPLETION_INTERVAL 을 주고, 둘 다 최소 60분입니다. Service Consumption Table 에서 서버리스 배수가 일반 서버리스 태스크(0.9)보다 낮은 0.5 입니다. 2026-10 기준 PrPr 라 신청한 계정에서만 씁니다.

언제 Dynamic Tables 로 바꾸나

단순한 "변경분 읽어서 MERGE" 파이프라인이라면 Dynamic Tables 가 코드와 운영 부담이 훨씬 적습니다. 태스크는 프로시저 호출, 외부 알림, 조건 분기, 관리 작업에 남겨 둡니다.

트러블슈팅

  • 증상: 태스크를 만들었는데 한 번도 돌지 않습니다.

  • 원인: 태스크는 만들면 일시 중지 상태입니다. 또는 소유 역할에 EXECUTE TASK 권한이 없습니다.

  • 해결: ALTER TASK ... RESUME (그래프는 SYSTEM$TASK_DEPENDENTS_ENABLE) 하고 권한을 확인합니다.

  • 증상: "Stream ... has become stale" 오류가 납니다.

  • 원인: 보존 기간과 연장 기간이 지나도록 스트림을 소비하지 않았습니다.

  • 해결: 스트림을 다시 만들고 빠진 구간은 Time Travel 이나 원본 비교로 보정합니다. 소비 주기를 보존 기간보다 충분히 짧게 잡습니다.

공식 문서

이 문서에서