Skip to content
Back to skills

Dag Orchestration Patterns

ASecurity

Airflow DAG 설계 패턴, 의존관계 관리, 재시도 전략, 멱등성 보장, 백필 전략 등 데이터 파이프라인 오케스트레이션 가이드. 'Airflow DAG', 'DAG 설계', '의존관계', '재시도 전략', '멱등성', '백필', '파이프라인 오케스트레이션', 'Dagster', 'Prefect' 등 파이프라인 스케줄링 시 이 스킬을 사용한다. scheduler-engineer의 DAG 설계 역량을 강화한다. 단, 데이터 품질 규칙 정의나 모니터링 대시보드는 이 스킬의 범위가 아니다.

  • 1,256 stars
  • 0 votes
  • 0 copies
  • 2 views
  • Added May 29, 2026
datapythonsqlapi

Works with

  • cli
  • api

Security analysis

A100/100

Scanned May 29, 2026

npx -y skills add revfactory/harness-100 --skill dag-orchestration-patterns --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Dag Orchestration Patterns?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Dag Orchestration Patterns
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/revfactory-dag-orchestration-patterns/badge)](https://www.skillsdirectory.com/skills/revfactory-dag-orchestration-patterns)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: dag-orchestration-patterns
description: "Airflow DAG 설계 패턴, 의존관계 관리, 재시도 전략, 멱등성 보장, 백필 전략 등 데이터 파이프라인 오케스트레이션 가이드. 'Airflow DAG', 'DAG 설계', '의존관계', '재시도 전략', '멱등성', '백필', '파이프라인 오케스트레이션', 'Dagster', 'Prefect' 등 파이프라인 스케줄링 시 이 스킬을 사용한다. scheduler-engineer의 DAG 설계 역량을 강화한다. 단, 데이터 품질 규칙 정의나 모니터링 대시보드는 이 스킬의 범위가 아니다."
---

# DAG Orchestration Patterns — 파이프라인 오케스트레이션 패턴 가이드

Airflow 중심의 DAG 설계 패턴과 운영 전략.

## DAG 설계 패턴

### 1. Extract-Load-Transform (ELT) 패턴

```python
with DAG("elt_orders", schedule="0 2 * * *", catchup=False) as dag:
    extract = PythonOperator(task_id="extract", python_callable=extract_orders)
    load_raw = PythonOperator(task_id="load_raw", python_callable=load_to_raw)
    transform = DbtOperator(task_id="transform", select="orders")
    quality = PythonOperator(task_id="quality_check", python_callable=run_checks)
    notify = SlackOperator(task_id="notify", trigger_rule="all_done")

    extract >> load_raw >> transform >> quality >> notify
```

### 2. Fan-out/Fan-in 패턴

```python
# 다중 소스 병렬 추출 → 통합 변환
sources = ["mysql", "postgres", "api"]
extract_tasks = [
    PythonOperator(task_id=f"extract_{src}", python_callable=extract, op_args=[src])
    for src in sources
]
merge = PythonOperator(task_id="merge_all", python_callable=merge_sources)
transform = PythonOperator(task_id="transform", python_callable=transform_data)

extract_tasks >> merge >> transform
```

### 3. 센서 기반 이벤트 대기

```python
wait_for_data = S3KeySensor(
    task_id="wait_for_file",
    bucket_name="data-lake",
    bucket_key="raw/orders/{{ ds }}/data.parquet",
    timeout=3600,  # 1시간 대기
    poke_interval=60,
    mode="reschedule"  # 대기 중 워커 해제
)
```

## 멱등성 보장 패턴

### 파티션 교체 (가장 권장)

```sql
-- 날짜 파티션 전체 교체 (멱등적)
DELETE FROM analytics.orders WHERE date_partition = '{{ ds }}';
INSERT INTO analytics.orders
SELECT * FROM staging.orders WHERE date_partition = '{{ ds }}';
```

### MERGE/UPSERT

```sql
MERGE INTO target AS t
USING source AS s ON t.id = s.id
WHEN MATCHED THEN UPDATE SET t.amount = s.amount, t.updated_at = CURRENT_TIMESTAMP
WHEN NOT MATCHED THEN INSERT (id, amount, created_at) VALUES (s.id, s.amount, CURRENT_TIMESTAMP);
```

### 멱등성 체크리스트

- [ ] 같은 DAG를 2번 실행해도 결과가 동일한가?
- [ ] 날짜 파라미터(`{{ ds }}`)를 사용하여 범위를 제한하는가?
- [ ] INSERT 전에 기존 데이터를 정리하는가?
- [ ] 외부 API 호출에 고유 요청 ID를 사용하는가?

## 재시도 전략

```python
default_args = {
    "retries": 3,
    "retry_delay": timedelta(minutes=5),
    "retry_exponential_backoff": True,
    "max_retry_delay": timedelta(minutes=60),
    "execution_timeout": timedelta(hours=2),
}
```

### 작업별 재시도 설정

| 작업 유형 | 재시도 횟수 | 대기 시간 | 이유 |
|----------|-----------|----------|------|
| DB 추출 | 3회 | 5분 지수 백오프 | 일시적 연결 문제 |
| API 호출 | 5회 | 30초 지수 백오프 | Rate limit, 네트워크 |
| 변환 (SQL) | 1회 | 즉시 | 로직 오류는 재시도 무의미 |
| 파일 업로드 | 3회 | 1분 | 네트워크 불안정 |

## 백필 전략

```python
# 안전한 백필 설정
dag = DAG(
    "daily_orders",
    schedule="0 2 * * *",
    start_date=datetime(2024, 1, 1),
    catchup=False,  # 자동 백필 비활성
    max_active_runs=1,  # 동시 실행 방지
)

# CLI로 수동 백필
# airflow dags backfill daily_orders -s 2024-01-01 -e 2024-01-31
```

### 백필 주의사항

| 주의 | 설명 | 대응 |
|------|------|------|
| 동시 실행 | 같은 데이터 범위 중복 처리 | `max_active_runs=1` |
| API Rate Limit | 대량 과거 데이터 요청 | 배치 크기 제한, 슬립 삽입 |
| 리소스 경합 | DB/클러스터 과부하 | 병렬도 제한, 시간 분산 |
| 데이터 정합성 | 과거 데이터 구조 변경 | 스키마 진화 처리 로직 |

## 의존관계 패턴

### Cross-DAG 의존

```python
# DAG A의 완료를 대기
wait_for_upstream = ExternalTaskSensor(
    task_id="wait_for_dag_a",
    external_dag_id="dag_a",
    external_task_id="final_task",
    execution_delta=timedelta(hours=0),
    timeout=3600,
    mode="reschedule"
)
```

### Dataset 기반 의존 (Airflow 2.4+)

```python
# Producer DAG
orders_dataset = Dataset("s3://datalake/orders/")

with DAG("produce_orders", schedule="0 2 * * *") as dag:
    produce = PythonOperator(
        task_id="produce", outlets=[orders_dataset]
    )

# Consumer DAG — 자동 트리거
with DAG("consume_orders", schedule=[orders_dataset]) as dag:
    consume = PythonOperator(task_id="consume", ...)
```

## 알림 전략

```python
def failure_callback(context):
    task = context["task_instance"]
    dag_id = context["dag"].dag_id
    execution_date = context["execution_date"]
    message = f"FAILED: {dag_id}/{task.task_id} at {execution_date}"
    send_slack(message)

default_args = {
    "on_failure_callback": failure_callback,
    "on_retry_callback": retry_callback,
}
```

| 이벤트 | 채널 | 대상 |
|--------|------|------|
| P0 작업 실패 | Slack + PagerDuty | 온콜 엔지니어 |
| SLA 미달 | Slack | 데이터 팀 |
| 재시도 발생 | Slack (정보) | 모니터링 채널 |
| 백필 완료 | Slack | 요청자 |

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…