이 문서를 통해 아래 질문들에 답할 수 있게 됩니다.
- pipeline dependency는 단순 실행 순서와 어떻게 다른가?
- checkpoint는 어떤 단위로 저장해야 재실행 범위를 줄일 수 있는가?
- task 성공과 데이터 검증 성공을 분리하지 않으면 어떤 문제가 생기는가?
- Airflow나 Spring Batch 없이도 dependency와 checkpoint를 어떻게 기록할 수 있는가?
개요
pipeline은 여러 task의 순서와 의존성으로 이루어진 실행 흐름이다.
checkpoint는 마지막으로 안전하게 처리된 위치다.
dependency가 없으면 task 실행 순서가 사람 기억에 의존한다.
checkpoint가 없으면 실패 후 어디서 다시 시작해야 할지 알 수 없다.
운영 가능한 pipeline은 “무엇이 끝나야 다음 task를 시작할 수 있는가”와 “어디까지 성공했는가”를 기록한다.
원리
dependency는 단순한 선후 관계가 아니다.
앞 task의 산출물이 뒤 task의 입력으로 유효해야 한다.
예를 들어 build_mart는 load_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_dashboardDAG는 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 againcheckpoint는 이 판단을 빠르게 하려고 남긴다.
개인 프로젝트 기준
Airflow 없이도 dependency와 checkpoint를 연습할 수 있다.
pipeline_step_run과 pipeline_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와 다른 소비자로 전파되는 것을 막기 위해서다.
참고 문서
- Apache Airflow Documentation
- Spring Batch Reference
- dbt Documentation, DAGs
- Martin Kleppmann, Designing Data-Intensive Applications