안녕하세요! 데이터 기반의 프로젝트를 진행하다 보면, 우리는 필연적으로 거대한 '작업의 교향곡'을 지휘해야 하는 과제에 직면하게 됩니다.
"A 작업이 끝나면 B를 실행하고, B가 성공하면 C와 D를 동시에 시작해 줘."
"만약 새벽에 작업이 실패하면, 누가 좀 알아서 재시도해주고 나에겐 알림만 보내주면 안 될까?"
"지금 수백 개의 작업 중에 도대체 어디서 병목이 생기는 거지? 전체 흐름을 한눈에 보고 싶어."과거의 개발자들은 이 복잡하게 얽힌 작업들을 'Cron'과 쉘 스크립트에 의존해 위태롭게 관리해야 했습니다. 이는 마치 악보도, 지휘자도 없이 각자의 감에 의존해 연주하는 오케스트라와 같았죠. 사소한 실수 하나가 전체 연주를 망가뜨리는 것은 시간 문제였습니다.
이 '스파게티 지옥'을 해결하기 위해, 2014년 에어비앤비에서 하나의 솔루션이 탄생했습니다. 바로 오늘 우리가 깊이 파헤쳐 볼 아파치 에어플로우(Apache Airflow)입니다. 이 글에서는 에어플로우가 무엇인지, 왜 필요했는지, 그리고 어떻게 데이터 파이프라인의 '사실상의 표준'이자 '클래식'으로 자리 잡게 되었는지, 그 핵심 개념부터 작동 원리, 실용적인 조언까지 모든 것을 상세히 공유하고자 합니다.
에어플로우란? 복잡한 작업들의 실행 순서와 스케줄을 코드로 정의하고, 자동으로 실행하며, 모든 과정을 한눈에 모니터링하는 플랫폼입니다.
이 정의를 이해하는 가장 좋은 방법은 에어플로우를 '거대한 오케스트라와 그 지휘자'에 비유하는 것입니다.
아름다운 비유를 넘어, 이제 '악보'와 '연주자'의 실체를 기술적으로 파헤쳐 보겠습니다.
DAG는 Directed Acyclic Graph (방향성이 있는 비순환 그래프)의 약자입니다. 이름 그대로, 모든 작업은 정해진 방향(Directed)으로 흐르며, 작업이 무한 반복되는 순환(Acyclic) 구조는 허용하지 않는 그래프(Graph)입니다.
for
루프를 사용해 동적으로 Task를 생성하거나, 외부 라이브러리를 가져와 사용하는 등 파이썬의 모든 가능성을 활용할 수 있다는 엄청난 장점을 가집니다.dag_id
(고유 이름), start_date
(언제부터 스케줄링을 시작할지), schedule_interval
(얼마나 자주 실행할지, 예: @daily
, @hourly
, Cron 표현식) 등의 핵심 속성을 가집니다.Operator는 특정 작업을 수행하는 방법을 정의한 '클래스' 또는 '템플릿'입니다. 그리고 이 Operator를 실제로 사용하기 위해 객체로 만든 것이 바로 Task입니다.
BashOperator
: 특정 쉘 명령어를 실행합니다.PythonOperator
: 정의된 파이썬 함수를 실행합니다. 데이터 처리 로직처럼 복잡한 작업을 수행할 때 가장 많이 사용됩니다.PostgresOperator
: PostgreSQL 데이터베이스에 직접 SQL 쿼리를 실행합니다.EmailOperator
: 지정된 주소로 이메일을 보냅니다. 작업 성공/실패 알림에 유용합니다.이 외에도 수많은 공식/커뮤니티 Operator가 있어, 거의 모든 종류의 작업을 '레고 블록'처럼 조립하여 파이프라인을 만들 수 있습니다.
# 간단한 DAG 파일 예시 (example_dag.py)
from airflow import DAG
from airflow.operators.bash import BashOperator
from datetime import datetime
with DAG(
dag_id='daily_report_pipeline',
start_date=datetime(2023, 1, 1),
schedule_interval='@daily',
catchup=False
) as dag:
# Task 1: 데이터를 추출하는 스크립트 실행
extract_data = BashOperator(
task_id='extract_data',
bash_command='python /scripts/extract.py'
)
# Task 2: 추출된 데이터를 처리하는 스크립트 실행
process_data = BashOperator(
task_id='process_data',
bash_command='python /scripts/process.py'
)
# Task 1이 성공해야 Task 2가 실행되도록 의존성 설정
extract_data >> process_data
위 코드에서 >>
기호 하나로 extract_data
Task가 끝난 후 process_data
Task가 실행되어야 한다는 명확한 의존 관계가 정의됩니다. 이것이 바로 '코드로 관리하는 워크플로우'의 강력함입니다.
이 오케스트라는 어떻게 조화롭게 움직일까요? 무대 뒤 네 명의 핵심 스태프와 그들의 상호작용을 살펴보겠습니다.
[전체 작동 흐름 상세 요약]
① 스케줄러가 깨어나 DAG 폴더를 스캔하고, 파이썬 파일을 파싱하여 DAG 구조를 파악합니다.
② 스케줄러는 메타데이터 DB를 보며 각 DAG의 다음 실행 시간을 계산합니다.
③ 실행 시간이 된 DAG Run이 생기면, 스케줄러는 그 안의 Task들의 의존성을 확인합니다. 실행 조건이 만족된 Task가 있다면, 그 Task의 상태를 'queued'(대기열)로 변경하고 실행 대기열에 넣습니다.
④ 엑세큐터가 대기열에서 Task를 꺼내 워커에게 할당합니다.
⑤ 워커는 Task를 실행하며, 실행 상태(running, success, failed 등)를 주기적으로 메타데이터 DB에 보고합니다.
⑥ 사용자는 웹 서버를 통해 메타데이터 DB에 기록된 최신 상태를 실시간으로 확인합니다.
에어플로우는 단순히 '좋은 툴'을 넘어, 기존 방식의 근본적인 문제들을 해결하기 위해 탄생했습니다.
문제 1: 암묵적인 의존성 → 해결: 명시적인 코드로 관리
과거에는 스크립트 A가 1시간 걸리니, 스크립트 B를 1시간 10분 뒤에 실행하는 식으로 시간을 '어림짐작'했습니다. 에어플로우는 task_a >> task_b
와 같이 의존성을 코드로 명확하게 선언하여, A가 얼마나 걸리든 상관없이 성공적으로 끝나야만 B가 시작되도록 보장합니다.
문제 2: 파편화된 관리 → 해결: 중앙 집중형 모니터링
수십 개의 Cron 작업이 여러 서버에 흩어져 있던 상황에서, 에어플로우는 모든 워크플로우를 하나의 UI에서 통합 관리하고 시각화해 줍니다. 전체 파이프라인의 건강 상태를 한눈에 파악할 수 있게 된 것이죠.
문제 3: 수동적인 실패 처리 → 해결: 자동화된 복구 및 알림
더 이상 새벽에 실패한 작업을 아침에 와서 수동으로 재시작할 필요가 없습니다. Task 정의 시 retries=3
과 같이 재시도 횟수를 지정하면 알아서 다시 실행하고, 그래도 실패하면 이메일이나 슬랙으로 알림을 보내도록 자동화할 수 있습니다.
모든 도구가 그렇듯, 에어플로우는 만병통치약이 아닙니다. 어떤 상황에 강력하고, 어떤 상황에 부적합할까요?
지금까지의 긴 여정을 한 문단으로 요약해 보겠습니다.
아파치 에어플로우는 오케스트라의 지휘자처럼, 파이썬 코드로 작성된 악보(DAG)에 따라 복잡하게 얽힌 데이터 작업(Task)들을 정해진 스케줄에 맞춰 자동으로 실행하고, 전체 연주 과정을 한눈에 볼 수 있는 대시보드(UI)를 제공하는 강력한 워크플로우 자동화 플랫폼입니다. 단순한 스크립트의 나열을 넘어, 데이터 파이프라인에 생명력과 질서, 그리고 신뢰성을 불어넣는 현대 데이터 엔지니어링의 필수 도구이자, 시대를 초월한 클래식이라 할 수 있습니다.
혹시 여러분도 팀의 데이터 파이프라인이 제멋대로 연주되는 혼돈을 겪고 계신가요? 그렇다면, 이 노련한 마에스트로, 에어플로우를 여러분의 팀에 초청하여 데이터 교향곡에 아름다운 질서를 부여해 보시는 것은 어떨까요?