Airflow๋ก ๋ฐ์ดํฐ ํ์ดํ๋ผ์ธ ๋ง๋ค๊ธฐ. ๋งค์ผ ์๋ฒฝ ๋์๊ฐ๋ ๋ฐฐ์น๋ค์ด ๋์ด๋๋ฉด, ์์์ ์คํจ ๊ด๋ฆฌ๊ฐ ์ง์ฅ์ด ๋๋ค. Airflow๋ ์ด ์ํฌํ๋ก๋ฅผ ์ฝ๋(DAG)๋ก ์ ์ํ๊ณ ์ค์ผ์ค๋ง·์ฌ์๋·๋ชจ๋ํฐ๋ง๊น์ง ํด์ค๋ค. DAG์ ๊ฐ๋ ๋ถํฐ ์ค์ ์์ฑ๊น์ง ์ฝ๋๋ก ์ ๋ฆฌํ๋ค.
๋ค์ด๊ฐ๋ฉฐ
๋ฐ์ดํฐ ์์ ์ด ํ๋๋ ๋์ด๋๋ฉด ๊ณง ๋ฌธ์ ๊ฐ ์๊ธด๋ค. "๋งค์ผ ์๋ฒฝ 2์์ ๋ฐ์ดํฐ๋ฅผ ์ถ์ถํ๊ณ , ๋๋๋ฉด ๋ณํํ๊ณ , ๊ทธ๊ฒ ๋๋๋ฉด ์ ์ฌํ๊ณ , ์คํจํ๋ฉด ์๋ฆผ์ ๋ณด๋ธ๋ค." ์ด๊ฑธ cron๊ณผ ์ ธ ์คํฌ๋ฆฝํธ๋ก ์ฎ๋ค ๋ณด๋ฉด, ์ด๋ ์๊ฐ ๋ฌด์์ด ์ธ์ ๋๊ณ , ์ด๋์ ์คํจํ๋์ง ์๋ฌด๋ ๋ชจ๋ฅด๋ ์ํ๊ฐ ๋๋ค.
ETL/ELT, ๋ฐฐ์น ์ฒ๋ฆฌ ๊ธ์์ ๋ค๋ฃฌ ๋ฐ์ดํฐ ์์ ๋ค์ ์ฒด๊ณ์ ์ผ๋ก ๊ด๋ฆฌํ๋ ๋๊ตฌ๊ฐ ๋ฐ๋ก Apache Airflow๋ค. ์ํฌํ๋ก๋ฅผ ์ฝ๋๋ก ์ ์ํ๊ณ , ์ค์ผ์ค๋ง·์์กด์ฑ·์ฌ์๋·๋ชจ๋ํฐ๋ง์ ํ๊ณณ์์ ์ฒ๋ฆฌํ๋ค.
Airflow์ ํต์ฌ์ "์ํฌํ๋ก๋ฅผ ์ฝ๋๋ก ๊ด๋ฆฌํ๋ค"๋ ๊ฒ์ด๋ค. ํ์ดํ๋ผ์ธ์ด ์ฝ๋๊ฐ ๋๋ฉด, ๋ฒ์ ๊ด๋ฆฌ๋ ๋ฆฌ๋ทฐ๋ ํ ์คํธ๋ ๊ฐ๋ฅํด์ง๋ค.
์ด ๊ธ์์๋ Airflow์ ํต์ฌ ๊ฐ๋ (DAG, Task, Operator)์ ์ก๊ณ , ์ค์ ํ์ดํ๋ผ์ธ์ ์ฝ๋๋ก ๋ง๋ค์ด๋ณธ๋ค.
Airflow๋
Airflow๋ ์ํฌํ๋ก๋ฅผ ์์ฑ·์ค์ผ์ค๋ง·๋ชจ๋ํฐ๋งํ๋ ํ๋ซํผ์ด๋ค. 2014๋ ์์ด๋น์ค๋น์์ ์์ํด ์ง๊ธ์ ๋ฐ์ดํฐ ์์ง๋์ด๋ง์ ์ฌ์ค์ ํ์ค์ด ๋๋ค.
ํต์ฌ์ "ํ์ดํ๋ผ์ธ์ ํ์ด์ฌ ์ฝ๋๋ก ์ ์ํ๋ค" ๋ ์ ์ด๋ค. GUI๋ก ๋๋๊ทธํ๋ ๊ฒ ์๋๋ผ, ์ฝ๋๋ก ์์ฑํ๊ธฐ ๋๋ฌธ์ ๋ค์์ด ๊ฐ๋ฅํ๋ค.
- ๋ฒ์ ๊ด๋ฆฌ: Git์ผ๋ก ํ์ดํ๋ผ์ธ ๋ณ๊ฒฝ ์ด๋ ฅ์ ์ถ์
- ์ฝ๋ ๋ฆฌ๋ทฐ: ํ์ดํ๋ผ์ธ ๋ณ๊ฒฝ๋ PR๋ก ๊ฒํ
- ๋์ ์์ฑ: ๋ฐ๋ณต๋ฌธ์ผ๋ก ๋น์ทํ ์์ ์ ์๋ ์์ฑ
- ํ ์คํธ: ํ์ดํ๋ผ์ธ ๋ก์ง์ ํ ์คํธ ์ฝ๋๋ก ๊ฒ์ฆ
cron์ด "์๊ฐ์ด ๋๋ฉด ๋ช ๋ น์ด๋ฅผ ์คํ"ํ๋ ๋จ์ ์ค์ผ์ค๋ฌ๋ผ๋ฉด, Airflow๋ ์์ ๊ฐ์ ์์กด์ฑ, ์คํจ ์ ์ฌ์๋, ์งํ ์ํฉ ์๊ฐํ๊น์ง ๊ด๋ฆฌํ๋ ์ค์ผ์คํธ๋ ์ดํฐ๋ค.
ํต์ฌ ๊ฐ๋ — DAG, Task, Operator
Airflow๋ฅผ ์ดํดํ๋ ค๋ฉด ์ธ ๊ฐ๋ ๋ง ์ก์ผ๋ฉด ๋๋ค.
DAG (Directed Acyclic Graph) — ๋ฐฉํฅ์ฑ ๋น์ํ ๊ทธ๋ํ. ์ฝ๊ฒ ๋งํด ์์ ๋ค์ ์คํ ์์๋ฅผ ์ ์ํ ํ๋ฆ๋๋ค. "A ๋๋๋ฉด B, B ๋๋๋ฉด C" ๊ฐ์ ์์กด ๊ด๊ณ๋ฅผ ๋ํ๋ธ๋ค. ์ํ(cycle)์ด ์์ด์, ์์ ์ด ์๊ธฐ ์์ ์ผ๋ก ๋์์ค์ง ์๋๋ค.
Task — DAG๋ฅผ ๊ตฌ์ฑํ๋ ๊ฐ๋ณ ์์ ํ๋. "๋ฐ์ดํฐ ์ถ์ถ", "๋ณํ", "์ ์ฌ" ๊ฐ๊ฐ์ด Task๋ค.
Operator — Task๊ฐ ์ค์ ๋ก ๋ฌด์จ ์ผ์ ํ๋์ง ์ ์ํ๋ ํ ํ๋ฆฟ. ์ข ๋ฅ๊ฐ ๋ค์ํ๋ค.
| Operator | ํ๋ ์ผ |
PythonOperator |
ํ์ด์ฌ ํจ์ ์คํ |
BashOperator |
์ ธ ๋ช ๋ น ์คํ |
SQLExecuteQueryOperator |
SQL ์ฟผ๋ฆฌ ์คํ |
EmailOperator |
์ด๋ฉ์ผ ๋ฐ์ก |

์ ๋ฆฌํ๋ฉด, DAG๋ผ๋ ํ๋ฆ๋ ์์ ์ฌ๋ฌ Task๊ฐ ์๊ณ , ๊ฐ Task๋ Operator๋ก ์ค์ ๋์์ ์ํํ๋ค.
์ฒซ DAG ๋ง๋ค๊ธฐ
์ถ์ถ → ๋ณํ → ์ ์ฌ๋ก ์ด์ด์ง๋ ๊ฐ๋จํ ETL ํ์ดํ๋ผ์ธ์ DAG๋ก ๋ง๋ค์ด๋ณด์.
from airflow import DAG
from airflow.operators.python import PythonOperator
from datetime import datetime, timedelta
# 1. ๊ธฐ๋ณธ ์ค์ (์คํจ ์ ์ฌ์๋ ๋ฑ)
default_args = {
"owner": "jinoism",
"retries": 2, # ์คํจํ๋ฉด 2๋ฒ ์ฌ์๋
"retry_delay": timedelta(minutes=5), # 5๋ถ ๊ฐ๊ฒฉ์ผ๋ก
}
# 2. ๊ฐ Task๊ฐ ์คํํ ํจ์
def extract():
print("์์ค์์ ๋ฐ์ดํฐ ์ถ์ถ")
return "raw_data"
def transform():
print("๋ฐ์ดํฐ ๋ณํ·๊ฐ๊ณต")
return "clean_data"
def load():
print("์จ์ดํ์ฐ์ค์ ์ ์ฌ")
# 3. DAG ์ ์
with DAG(
dag_id="daily_etl",
default_args=default_args,
description="๋งค์ผ ๋๋ ETL ํ์ดํ๋ผ์ธ",
schedule="0 2 * * *", # ๋งค์ผ ์๋ฒฝ 2์ (cron ํํ์)
start_date=datetime(2026, 1, 1),
catchup=False, # ๊ณผ๊ฑฐ ๋ฏธ์คํ๋ถ ๊ฑด๋๋ฐ๊ธฐ
tags=["etl", "daily"],
) as dag:
# 4. Task ์ ์ (๊ฐ๊ฐ Operator๋ก)
extract_task = PythonOperator(
task_id="extract",
python_callable=extract,
)
transform_task = PythonOperator(
task_id="transform",
python_callable=transform,
)
load_task = PythonOperator(
task_id="load",
python_callable=load,
)
# 5. ์คํ ์์(์์กด์ฑ) ์ ์ — ์ด๊ฒ DAG์ ํต์ฌ
extract_task >> transform_task >> load_task
๋ง์ง๋ง ์ค extract_task >> transform_task >> load_task๊ฐ Airflow์ ์ ์๋ค. >> ์ฐ์ฐ์๋ก "์ถ์ถ → ๋ณํ → ์ ์ฌ" ์์๋ฅผ ์ ์ธํ๋ค. transform์ extract๊ฐ ์ฑ๊ณตํด์ผ ์์๋๊ณ , load๋ transform์ด ๋๋์ผ ์์๋๋ค.
์์กด์ฑ — ๋ณต์กํ ํ๋ฆ ๋ง๋ค๊ธฐ
์ค์ ํ์ดํ๋ผ์ธ์ ์ผ์ง์ ์ด ์๋๋ค. ์ฌ๋ฌ ์์ ์ด ๊ฐ๋ผ์ง๊ณ ํฉ์ณ์ง๋ค. Airflow๋ ์ด๋ฐ ํ๋ฆ๋ ์ง๊ด์ ์ผ๋ก ํํํ๋ค.
# ์ฌ๋ฌ ์์ค์์ ๋์์ ์ถ์ถ → ๋ชจ๋ ๋๋๋ฉด ๋ณํฉ
extract_db >> merge
extract_api >> merge
merge >> transform >> load
# ๋๋ ๋ฆฌ์คํธ๋ก ํ ๋ฒ์
[extract_db, extract_api] >> merge >> transform >> load
extract_db์ extract_api๋ ๋์์(๋ณ๋ ฌ๋ก) ์คํ๋๊ณ , ๋ ๋ค ๋๋์ผ merge๊ฐ ์์๋๋ค. ์ด๋ ๊ฒ "์ฌ๋ฌ ์์
์ ๋ณ๋ ฌ๋ก ๋๋ฆฌ๊ณ , ๋ค ๋ชจ์ด๋ฉด ๋ค์์ผ๋ก" ๊ฐ์ ํ๋ฆ์ ์ฝ๋ ๋ช ์ค๋ก ํํํ๋ค.
# ์ ์ฌ ํ ๊ฐ๋ผ์ง๊ธฐ: ์ฑ๊ณตํ๋ฉด ์๋ฆผ + ํต๊ณ ๋์ ์คํ
load >> [send_notification, update_stats]
์คํจ ์ฒ๋ฆฌ์ ์ฌ์๋
Airflow๊ฐ cron๋ณด๋ค ๊ฐ๋ ฅํ ๊ฒฐ์ ์ ์ด์ ๋ค. ์์ ์ด ์คํจํ์ ๋์ ์ฒ๋ฆฌ๋ฅผ ์ธ๋ฐํ๊ฒ ์ ์ดํ๋ค.
default_args = {
"retries": 3, # 3๋ฒ๊น์ง ์ฌ์๋
"retry_delay": timedelta(minutes=5), # 5๋ถ ๊ฐ๊ฒฉ
"retry_exponential_backoff": True, # ์ฌ์๋ ๊ฐ๊ฒฉ์ ์ ์ ๋๋ฆผ
"email_on_failure": True, # ์คํจ ์ ์ด๋ฉ์ผ
"execution_timeout": timedelta(hours=1), # 1์๊ฐ ๋์ผ๋ฉด ์คํจ ์ฒ๋ฆฌ
}
ํน์ Task๋ง ๋ค๋ฅด๊ฒ ์ค์ ํ ์๋ ์๋ค.
critical_task = PythonOperator(
task_id="critical_load",
python_callable=load,
retries=5, # ์ด ์์
๋ง 5๋ฒ ์ฌ์๋
retry_delay=timedelta(minutes=10),
)
์ผ์์ ์ธ ๋คํธ์ํฌ ์ค๋ฅ๋ก ์คํจํ๋ค๋ฉด ๋ช ๋ถ ๋ค ์ฌ์๋๋ก ์๋ ๋ณต๊ตฌ๋๊ณ , ๊ทธ๋๋ ์ ๋๋ฉด ์๋ฆผ์ด ์จ๋ค. ์๋ฒฝ์ ์กฐ์ฉํ ์คํจํด์ ์์นจ์ ๋ฐ๊ฒฌํ๋ cron์ ์ ๋ชฝ์ด ์ฌ๋ผ์ง๋ค.
์น UI — ํ๋์ ๋ณด๋ ํ์ดํ๋ผ์ธ
Airflow์ ๋ ๋ค๋ฅธ ๊ฐ์ ์ ์น UI๋ค. ๋ชจ๋ DAG์ ์คํ ์ํ๋ฅผ ์๊ฐ์ ์ผ๋ก ๋ณด์ฌ์ค๋ค.
- Graph View: DAG์ ํ๋ฆ๋์ ๊ฐ Task์ ์ํ(์ฑ๊ณต=์ด๋ก, ์คํจ=๋นจ๊ฐ, ์คํ์ค=๋ ธ๋)
- Grid View: ๋ ์ง๋ณ ์คํ ์ด๋ ฅ์ ๊ฒฉ์๋ก — ์ธ์ ๋ฌด์์ด ์คํจํ๋์ง ํ๋์
- Logs: ๊ฐ Task์ ์คํ ๋ก๊ทธ๋ฅผ ํด๋ฆญ ํ ๋ฒ์ผ๋ก ํ์ธ
- ์๋ ์คํ·์ฌ์คํ: ์คํจํ Task๋ง ๊ณจ๋ผ ๋ค์ ๋๋ฆฌ๊ธฐ
cron์ "๋์๋์ง ์ ๋์๋์ง"์กฐ์ฐจ ๋ก๊ทธ๋ฅผ ๋ค์ ธ์ผ ์์ง๋ง, Airflow๋ ๋์๋ณด๋์์ ์ ์ฒด ํ์ดํ๋ผ์ธ์ ๊ฑด๊ฐ ์ํ๋ฅผ ๋ฐ๋ก ๋ณธ๋ค. ์ด ๊ฐ์์ฑ์ด ์ด์์ ์์ ํ ๋ฐ๊พผ๋ค.
cron๊ณผ ๋ฌด์์ด ๋ค๋ฅธ๊ฐ
| cron | Airflow | |
| ์ ์ ๋ฐฉ์ | ์ ธ ์คํฌ๋ฆฝํธ | ํ์ด์ฌ ์ฝ๋ (DAG) |
| ์์กด์ฑ | ์๋ ๊ด๋ฆฌ (์ง์ฅ) | >>๋ก ๋ช
์ |
| ์คํจ ์ฒ๋ฆฌ | ์ง์ ๊ตฌํ | ์ฌ์๋·์๋ฆผ ๋ด์ฅ |
| ๋ชจ๋ํฐ๋ง | ๋ก๊ทธ ๋ค์ง๊ธฐ | ์น UI ๋์๋ณด๋ |
| ์ฌ์คํ | ์๋ | ์คํจ๋ถ๋ง ์ ํ ์ฌ์คํ |
| ๋ฒ์ ๊ด๋ฆฌ | ์ด๋ ค์ | Git์ผ๋ก ๊ด๋ฆฌ |
cron์ด ๋์ ๊ฑด ์๋๋ค. ๋จ์ํ ๋จ์ผ ์์ ์ด๋ฉด cron์ผ๋ก ์ถฉ๋ถํ๋ค. ํ์ง๋ง ์์ ์ด ์ฌ๋ฌ ๊ฐ๋ก ์ฝํ๊ณ , ์์์ ์คํจ ๊ด๋ฆฌ๊ฐ ์ค์ํด์ง๋ ์๊ฐ Airflow์ ๊ฐ์น๊ฐ ํญ๋ฐํ๋ค.
๋ง์น๋ฉฐ
Airflow๋ "๋ฐ์ดํฐ ํ์ดํ๋ผ์ธ์ ์ฝ๋๋ก ๊ด๋ฆฌํ๋ค"๋ ๋ฐ์์ ๋๊ตฌ๋ค. ํฉ์ด์ง ๋ฐฐ์น ์์ ๋ค์ DAG๋ผ๋ ํ๋ฆ๋๋ก ๋ฌถ๊ณ , ์์กด์ฑ·์ค์ผ์ค·์ฌ์๋·๋ชจ๋ํฐ๋ง์ ํ๊ณณ์์ ์ฒ๋ฆฌํ๋ค. cron๊ณผ ์ ธ ์คํฌ๋ฆฝํธ๋ก ๋ฒํฐ๋ ์ํฌํ๋ก๊ฐ ์ปค์ก๋ค๋ฉด, Airflow ๋์ ์ ๊ณ ๋ฏผํ ๋๋ค.
ํต์ฌ๋ง ๋ค์ ์ง์ผ๋ฉด, DAG(ํ๋ฆ๋) ์์ Task(์์
)๋ค์ด ์๊ณ , ๊ฐ Task๋ Operator๋ก ๋์ํ๋ฉฐ, >>๋ก ์์๋ฅผ ์๋๋ค. ์ด ๋จ์ํ ๋ชจ๋ธ ์์ ์ฌ์๋·์๋ฆผ·์๊ฐํ๊ฐ ์นํ ์๋ค. ์ฒ์์ ๊ฐ๋
์ด ๋ฏ์ค์ง๋ง, ํ ๋ฒ DAG๋ฅผ ์ง๋ณด๋ฉด "์ ์ง์ ์ ์ผ์ง" ์ถ์ด์ง ๊ฒ์ด๋ค.
๋ฐ์ดํฐ๊ฐ ํ๋ฅด๋ ํ์ดํ๋ผ์ธ์ ๋ง๋๋ ์ผ์ ๊ฒฐ๊ตญ "๋ฌด์์, ์ธ์ , ์ด๋ค ์์๋ก, ์คํจํ๋ฉด ์ด๋ป๊ฒ"๋ฅผ ์ ์ํ๋ ์ผ์ด๋ค. Airflow๋ ๊ทธ ์ ์๋ฅผ ์ฝ๋๋ก ๋ช ํํ๊ฒ ๋ง๋ค์ด์ค๋ค.
์ฐธ๊ณ ์ถ์ฒ
- Apache Airflow ๊ณต์ ๋ฌธ์ — https://airflow.apache.org/docs/
- Airflow: Core Concepts (DAGs) — https://airflow.apache.org/docs/apache-airflow/stable/core-concepts/dags.html
- Astronomer: Airflow Guides — https://www.astronomer.io/docs/learn/
'๐ Data Science & AI > Data Engineering' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
| Kafka ์ ๋ฌธ (1) | 2026.06.25 |
|---|---|
| ETL, ELT ๋ฐ์ดํฐ ํ์ดํ๋ผ์ธ์ ๋ ๋ฐฉ์, ๋ญ๊ฐ ๋ค๋ฅผ๊น (0) | 2026.06.16 |
| Spark๋ฅผ Kubernetes ์์ ์ฌ๋ฆฌ๋ฉด ๋ฌด์์ด ๋ฌ๋ผ์ง๋๊ฐ (0) | 2026.04.20 |
| ๋ฐ์ดํฐ ์ข ๋ฅ์ ์ดํด์ ๋ถ์ ํ๋ก์ธ์ค (0) | 2026.02.27 |
