이 문서를 통해 아래 질문들에 답할 수 있게 됩니다.

  • pipeline dependency는 단순 실행 순서와 어떻게 다른가?
  • checkpoint는 어떤 단위로 저장해야 재실행 범위를 줄일 수 있는가?
  • task 성공과 데이터 검증 성공을 분리하지 않으면 어떤 문제가 생기는가?
  • Airflow나 Spring Batch 없이도 dependency와 checkpoint를 어떻게 기록할 수 있는가?

개요

pipeline은 여러 task의 순서와 의존성으로 이루어진 실행 흐름이다.

checkpoint는 마지막으로 안전하게 처리된 위치다.

dependency가 없으면 task 실행 순서가 사람 기억에 의존한다.

checkpoint가 없으면 실패 후 어디서 다시 시작해야 할지 알 수 없다.

운영 가능한 pipeline은 “무엇이 끝나야 다음 task를 시작할 수 있는가”와 “어디까지 성공했는가”를 기록한다.

원리

dependency는 단순한 선후 관계가 아니다.

앞 task의 산출물이 뒤 task의 입력으로 유효해야 한다.

예를 들어 build_martload_fact가 끝났다는 사실만으로 시작하면 안 된다.

load_fact의 row count와 품질 검증이 통과해야 한다.

checkpoint도 마찬가지다.

task가 종료되었다는 사실과 데이터가 안전하다는 사실을 구분해야 한다.

의존성 예시

extract_orders
  -> load_raw_orders
  -> build_fact_order_payment
  -> validate_fact_order_payment
  -> build_mart_sales_daily
  -> validate_mart_sales_daily
  -> publish_dashboard

이 흐름에서 dashboard 공개는 mart build 성공만으로 하면 안 된다.

mart validation이 통과해야 한다.

Checkpoint 예시

CREATE TABLE pipeline_checkpoint (
    pipeline_name varchar(100) NOT NULL,
    target_partition varchar(100) NOT NULL,
    checkpoint_type varchar(50) NOT NULL,
    checkpoint_value varchar(200) NOT NULL,
    validation_status varchar(20) NOT NULL,
    updated_at timestamp NOT NULL,
    PRIMARY KEY (pipeline_name, target_partition, checkpoint_type)
);

checkpoint에는 target partition과 validation status가 같이 있어야 한다.

ds=2026-06-30의 task가 끝났지만 validation이 실패했다면 성공 checkpoint로 보면 안 된다.

Airflow DAG 예시

extract_orders >> load_raw_orders >> build_fact_order_payment
build_fact_order_payment >> validate_fact_order_payment
validate_fact_order_payment >> build_mart_sales_daily
build_mart_sales_daily >> validate_mart_sales_daily >> publish_dashboard

DAG는 dependency를 코드로 표현한다.

그러나 DAG가 있다고 checkpoint가 자동으로 좋은 것은 아니다.

task별 입력 partition, 출력 partition, 검증 결과를 함께 남겨야 한다.

Spring 기반 단순 구현

public void runPipeline(LocalDate targetDate) {
    if (!checkpoint.isSuccess("load_raw_orders", targetDate)) {
        loadRawOrders(targetDate);
    }
    if (!checkpoint.isSuccess("build_fact_order_payment", targetDate)) {
        buildFactOrderPayment(targetDate);
    }
    validateFactOrderPayment(targetDate);
}

작은 프로젝트에서는 이런 명시적 checkpoint만으로도 시작할 수 있다.

중요한 것은 task를 무조건 처음부터 실행하지 않는 것이다.

판단 축

  • dependency는 산출물과 검증 조건까지 포함한다.
  • checkpoint는 source range 또는 target partition 단위로 저장한다.
  • task 성공과 validation 성공을 다른 상태로 둔다.
  • 재실행은 실패 task부터 할지 upstream부터 할지 기준을 둔다.
  • checkpoint 갱신은 idempotent하게 처리한다.

실패 모델

  • upstream task가 실패했는데 downstream task가 오래된 데이터를 읽는다.
  • checkpoint가 task 시작 시점에 갱신되어 실패를 성공으로 본다.
  • validation 실패인데 dashboard publish task가 실행된다.
  • checkpoint 단위가 너무 커서 하루치 오류에 한 달치를 다시 처리한다.
  • 수동 재실행이 checkpoint를 우회해 상태가 꼬인다.

운영 지표

  • checkpoint_lag: 마지막 성공 partition과 현재 기대 partition의 차이다.
  • dependency_blocked_count: upstream 미완료로 막힌 task 수다.
  • validation_block_count: 검증 실패로 downstream을 막은 횟수다.
  • rerun_from_checkpoint_count: checkpoint 기준 재실행 횟수다.
  • stale_downstream_count: 오래된 upstream을 읽은 downstream 수다.

재처리 기준

실패 위치에 따라 재처리 시작점이 달라진다.

failure: build_mart_sales_daily
target_partition: ds=2026-06-30
safe_start:
  - if fact validation success: rebuild mart only
  - if fact validation failed: rebuild fact from raw
  - if raw missing: extract source again

checkpoint는 이 판단을 빠르게 하려고 남긴다.

개인 프로젝트 기준

Airflow 없이도 dependency와 checkpoint를 연습할 수 있다.

pipeline_step_runpipeline_checkpoint table을 만들고, target date별 상태를 남긴다.

Spring Scheduler가 순서대로 method를 호출하더라도 각 method의 성공과 검증 결과를 기록한다.

기업 운영 기준

기업에서는 dependency가 팀 경계를 넘을 수 있다.

주문 fact는 주문 서비스와 결제 서비스 적재가 모두 끝난 뒤 만들어질 수 있다.

이 경우 upstream owner, SLA, 지연 허용치, 실패 시 downstream 공개 여부를 명시해야 한다.

실전 팁

  • task 이름에 source와 target을 드러낸다.
  • checkpoint는 사람이 읽을 수 있는 partition 값으로 남긴다.
  • validation 실패는 downstream dependency를 막는 상태로 둔다.
  • 수동 재실행도 checkpoint를 갱신하는 동일 경로를 사용한다.
  • checkpoint table을 운영자가 조회할 수 있게 만든다.

위험 신호!

  • pipeline 순서가 wiki 그림에만 있고 코드나 metadata에 없다.
  • checkpoint가 마지막 실행 시각만 저장한다.
  • task 성공을 곧 downstream 공개로 간주한다.
  • 실패 후 항상 전체 pipeline을 처음부터 돌린다.
  • validation 실패가 있어도 checkpoint가 success로 갱신된다.

확인 질문

확인 질문

  • dependency는 단순 실행 순서와 무엇이 다른가?
    • 앞 task의 산출물과 검증 결과가 뒤 task의 입력 조건이라는 점이 다르다.
  • checkpoint에는 어떤 정보가 있어야 하는가?
    • pipeline name, target partition, checkpoint value, validation status, updated time이 필요하다.
  • validation 실패 후 downstream을 막아야 하는 이유는 무엇인가?
    • 잘못된 fact나 mart가 dashboard와 다른 소비자로 전파되는 것을 막기 위해서다.

참고 문서