Airflow๋กœ ๋ฐ์ดํ„ฐ ํŒŒ์ดํ”„๋ผ์ธ ๋งŒ๋“ค๊ธฐ

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 ์ด๋ฉ”์ผ ๋ฐœ์†ก

 

Airflow

์ •๋ฆฌํ•˜๋ฉด, 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๋Š” ๊ทธ ์ •์˜๋ฅผ ์ฝ”๋“œ๋กœ ๋ช…ํ™•ํ•˜๊ฒŒ ๋งŒ๋“ค์–ด์ค€๋‹ค.


์ฐธ๊ณ  ์ถœ์ฒ˜