
1편에서는 Workflow와 Workflow Orchestration의 관계를 살펴보고, Airflow가 Workflow Orchestration을 구현하는 솔루션이라는 것을 정리했다.
이번 글에서는 그다음 단계로 Airflow에서 Workflow를 어떻게 정의하는지 알아본다.
1편에서 Workflow를 다음과 같이 정의했다.
Workflow
= 작업의 흐름
Airflow에서는 이 Workflow를 DAG(Directed Acyclic Graph)라는 형태로 표현한다.
Workflow
↓
DAG

DAG는 Directed Acyclic Graph의 약자다.
각 단어를 나누어 보면 다음과 같다.
| 구성 | 의미 |
|---|---|
| Directed | 방향성이 있음 |
| Acyclic | 순환하지 않음 |
| Graph | 그래프 |
예를 들어 데이터 처리 Workflow가 다음과 같다고 하자.
Extract
↓
Transform
↓
Load
↓
Data Quality Check
이와 같은 작업의 관계를 Airflow에서는 DAG로 정의한다.
즉,
DAG는 "이 Workflow를 어떤 구조로 실행할 것인가"를 정의한 설계도다.
실무에서는 DAG를 하나의 파이프라인이라고 이해해도 큰 문제는 없다.
하지만 정확하게는 Workflow의 정의 또는 설계도에 가깝다.
또한 DAG 안에 들어가는 Task의 개수에는 정해진 기준이 없다.
DAG
├─ Task A
├─ Task B
└─ Task C
처럼 여러 Task를 포함할 수도 있고,
DAG
└─ Task A
처럼 하나의 Task만 가질 수도 있다.
서로 다른 Glue Job도 항상 함께 실행되고 순서가 명확하다면 하나의 DAG로 묶을 수 있다.
따라서 DAG를 정의할 때 중요한 것은 단순히 Task가 몇 개인가가 아니라, 어떤 Workflow를 하나의 단위로 정의할 것인가이다.

여기서 DAG와 DAG Run을 구분해야 한다.
DAG
= Workflow 정의
= 설계도
DAG Run은 이 설계도를 실제로 한 번 실행한 것이다.
DAG
│
├─ DAG Run #1
│ ├─ Task A
│ ├─ Task B
│ └─ Task C
│
├─ DAG Run #2
│ ├─ Task A
│ ├─ Task B
│ └─ Task C
│
└─ DAG Run #3
├─ Task A
├─ Task B
└─ Task C
같은 DAG라도 실행될 때마다 새로운 DAG Run이 생성된다.
따라서 둘의 관계는 다음과 같다.
| 개념 | 의미 |
|---|---|
| DAG | Workflow의 정의 |
| DAG Run | DAG의 한 번의 실행 |
쉽게 비유하면,
DAG
→ 설계도
DAG Run
→ 설계도를 사용해 실제로 만든 한 개의 결과물
이라고 이해할 수 있다.

DAG 안에는 실제 작업을 의미하는 Task가 존재한다.
예를 들어:
DAG
│
├─ Extract
├─ Transform
└─ Load
여기서 Extract, Transform, Load가 각각 Task다.
하지만 Task 자체는 논리적인 작업의 정의다.
실제로 DAG Run이 실행되면 해당 Task에 대한 Task Instance가 생성된다.
DAG
└─ Task A
이 DAG가 세 번 실행된다면:
DAG Run #1 → Task Instance A-1
DAG Run #2 → Task Instance A-2
DAG Run #3 → Task Instance A-3
즉,
| 개념 | 의미 |
|---|---|
| Task | DAG에 정의된 논리적 작업 |
| Task Instance | 특정 DAG Run에서 실제 실행된 Task |
이를 전체 관계로 연결하면 다음과 같다.
Workflow
↓
DAG
↓
DAG Run
↓
Task Instance
여기서 Task는 DAG의 정의에 포함된 작업이고, Task Instance는 실제 실행 과정에서 만들어지는 실행 단위라는 점을 기억하면 된다.
Task는 단순히 "실행한다"라고만 정의하는 것이 아니다.
Task가 무엇을 수행할지, 어떤 조건을 기다릴지, 다른 Task와 어떤 순서를 가질지를 함께 정의해야 한다.
대표적인 요소가 다음 세 가지다.
Task
├─ Operator
├─ Sensor
└─ Dependency
Operator는 Task가 수행할 동작을 정의한다.
| Operator | 역할 |
|---|---|
| PythonOperator | Python 함수 실행 |
| BashOperator | Shell 명령 실행 |
| SQL 계열 Operator | SQL 실행 |
| AWS 관련 Operator | AWS 서비스 호출 |
| Kubernetes 관련 Operator | Kubernetes 작업 실행 |
구조적으로 보면:
Task
↓
Operator
↓
수행할 동작
예를 들어 PythonOperator를 사용하면 Python 함수를 실행하는 Task를 정의할 수 있다.
Sensor는 특정 조건이 만족될 때까지 대기하는 Task다.
예를 들어 S3에 파일이 도착해야 다음 작업을 수행한다고 하자.
S3 파일 도착?
↓
NO
↓
대기
↓
YES
↓
다음 Task 실행
대표적인 활용 사례는 다음과 같다.
즉,
Sensor는 "조건이 만족되었는가?"를 확인하면서 다음 단계로 넘어갈 시점을 제어한다.
Dependency는 Task 사이의 실행 순서와 의존관계를 정의한다.
예를 들어:
Extract
↓
Transform
↓
Load
Airflow에서는 다음과 같이 표현할 수 있다.
extract >> transform >> load
이는 다음 관계를 의미한다.
Extract
↓
Transform
↓
Load
즉, 앞의 Task가 완료되어야 뒤의 Task가 실행될 수 있도록 관계를 정의하는 것이다.
Task의 구성 요소를 하나의 문장으로 정리하면 다음과 같다.
Operator
→ 실제로 수행할 작업을 정의
Sensor
→ 특정 조건이 만족될 때까지 대기하는 Task
Dependency
→ Task 간 실행 순서와 의존관계를 정의
따라서 Workflow를 DAG로 정의할 때는 단순히 Task만 나열하는 것이 아니라,
무엇을 실행할지
+ 어떤 조건에서 실행할지
+ 어떤 순서로 실행할지
까지 함께 표현하게 된다.
DAG
│
┌────────┴────────┐
↓ ↓
Operator Sensor
│ │
"무엇을?" "조건이?"
│ │
└────────┬────────┘
↓
Dependency
│
"순서?"
지금까지의 내용을 하나의 구조로 연결하면 다음과 같다.
Workflow
↓
DAG
│
├─ Task A
│ └─ Operator
│
├─ Task B
│ └─ Sensor
│
└─ Task C
└─ Operator
그리고 Task 사이에는 Dependency가 존재한다.
Task A
↓
Task B
↓
Task C
DAG가 실행되면 DAG Run이 생성되고, 각 Task는 해당 실행에 대한 Task Instance로 동작한다.
DAG
↓ 실행
DAG Run
├─ Task Instance A
├─ Task Instance B
└─ Task Instance C
즉, Airflow에서 Workflow를 정의하는 핵심 구조는 다음과 같다.
Workflow
↓
DAG
↓
Task
├─ Operator
├─ Sensor
└─ Dependency
↓
DAG Run
↓
Task Instance
이 구조를 이해하면 이후에 나오는 Scheduler, Executor, Worker는 "정의된 DAG를 실제로 어떻게 실행하는가"라는 다음 문제로 자연스럽게 이어진다.
이번 글에서는 Airflow에서 Workflow를 정의하는 구조를 살펴봤다.
가장 중요한 관계만 정리하면:
DAG
→ Workflow의 설계도
DAG Run
→ DAG의 한 번의 실행
Task
→ 논리적인 작업
Task Instance
→ 특정 실행에서 실제 수행된 Task
그리고 Task를 정의할 때:
Operator
→ 무엇을 수행할지
Sensor
→ 어떤 조건을 기다릴지
Dependency
→ 어떤 순서로 실행할지
를 결정한다.
Airflow에서는 Workflow를 DAG로 정의하고, DAG 안에 Task와 Task 간 Dependency를 구성한다.
DAG가 실행되면 DAG Run이 생성되고, 실제 실행되는 Task는 Task Instance가 된다.