모든 문제의 근원 execution_date

execution_date는 그 이름과는 다르게, Task가 실제로 실행되는 시간이 아니라 **'해당 Task가 실행하고자 하는 Time Window의 시작 지점'**을 의미합니다. 말이 어렵습니다. 예를 들어 설명하면 다음과 같습니다.

아래에 2021년 1월 1일부터 하루에 한번 실행되는 DAG이 있습니다.

DAG(
    dag_id='test_dag',
    # '@daily', '0 0 * * *' or datetime.timedelta(days=1)
    schedule_interval='@daily',
    start_date=datetime.datetime(2021, 1, 1),
    # end_date=datetime.datetime(2021, 12, 31),
    ...
)

DAG의 시작시점(start_date)인 2021-01-01 새벽 0시부터 1일 간격(schedule_interval)으로 task가 실행됩니다. 여기까지는 누구나 쉽게 이해할 수 있는 부분이죠. 하지만 1월 1일 자정에 첫번째 작업이 실행되지 않습니다.

Airflow를 처음 접하시는 분들이 하는 가장 흔한 실수 중 하나입니다. 실제 첫번째 작업은 2021년 1월 2일 자정에 시작됩니다. 분명 start_date를 1월 1일로 했는데 대체 왜 그런걸까요? 이 규칙을 이해하기 위해서는 먼저 **타임 윈도우(Time Window)**의 개념을 이해해야 합니다.

전통적인 배치 데이터 처리 방식은 작업의 대상이 되는 데이터의 기간이 있고, 그 대상 기간이 지나고 나서 해당 기간에 발생한 데이터를 처리하게 됩니다. (우리가 자주 사용하는 base_dt )

2021년 1월 3일의 일일 매출을 계산하고 싶다면, 3일이 끝나고 하루가 넘어가는 1월 4일 자정(0시)에 01/03 00:00:00 ~ 01/03 23:59:59에 발생한 매출을 계산해야 합니다. 여기서 작업 대상이 되는 데이터는 1월 3일자 데이터(=execution_date)가 되고, 실제 작업이 실행되는 시간은 1월 4일 0시가 됩니다.

Untitled

execution_date는 해당 Task가 처리해야 할 데이터 기간의 시작 시점인 2021년 1월 3일을 의미합니다. execution_date라는 이름을 직역하면 실행 날짜가 되기 때문에 그 의미와 실제 의미가 달라 자꾸 혼란이 발생하는 것이죠.

그리고 schedule_intervalCron expressiontimedelta만 사용할 수 있기 때문에 '공휴일을 제외한 영업일에만 작업' 과 같이 복잡한 형태의 스케줄을 정의할 수 없다는 문제도 있습니다.

AIP-39등장!

Airflow Improvement Proposal: AIP-39 Richer scheduler_interval

스케줄 간격타임윈도우라는 각기 다른 2가지의 개념이 섞여 있기 때문에 햇갈리고 복잡한 스케줄링이 어려운 문제가 발생합니다.

지금의 Airflow 구조에서는 시작 시점과 스케줄 간격만을 정할 수 있기 때문에, 작업이 언제 실행될 지를 결정하는 스케줄과 작업의 대상이 되는 데이터의 Time Window를 분리해서 정의할 수 없습니다. schedule_interval이 스케줄 간격과 타임 윈도우 2가지의 역할을 동시에 하고 있기 때문입니다.

AIP-39의 핵심은 작업의 스케줄 간격과 작업의 대상이 되는 타임 윈도우를 분리입니다.

가장 큰 변화는 혼란의 중심에 있는 execution_date을 없애고 좀 더 명확히 타임 윈도우의 개념을 표현하기 위해 date_interval이라는 개념을 도입합니다. 타임 윈도우의 시작은 data_interval_start, 타임 윈도우의 끝은 data_interval_end가 됩니다. 또, 실제로 작업이 실행되는 시점을 표현하기 위해 새로운 변수인 schedule_date을 도입합니다.

Untitled