“이 Task는 예전 코드로 실행됐던 거였나?”
Airflow를 운영하다 보면 한 번쯤은 이런 고민을 해보신 경험이 있으실 겁니다.
그런데 반가운 소식!
Airflow 3.x 버전에서 DAG Versioning 기능이 도입되었습니다ㅎㅎ ![]()
이제 Airflow UI 상에서 DAG의 변경 이력을 추적하고, 각 task가 어떤 DAG 버전으로 실행되었는지 확인할 수 있게 되었습니다.
이 글에서는 DAG Versioning이 무엇인지, 그리고 어떻게 사용하는지를 정리해 보려고 합니다.
앞으로 DAG 관리를 훨씬 체계적으로 관리할 수 있으실 거예요!
왜 DAG Vesioning이 필요할까?
Airflow 2.x까지는 DAG 실행과 UI 모두 항상 로컬의 최신 DAG 코드를 기준으로 작동했습니다.
이로 인해 다음과 같은 두 가지 문제점이 발생하곤 했습니다:
- DAG 수정 시, 삭제된 태스크가 Airflow UI에서 사라짐
- DAG 실행 중 코드가 바뀌면, 일부 태스크는 이전 코드, 나머지는 수정된 코드로 실행됨
이러한 문제를 해결하기 위해, Airflow 3.x 버전에서는 DAG Bundles와 DAG Versioning 이 도입되었습니다.
DAG Bundles 란?
Airflow 3.x 에서는 기존의 dags/ 폴더에 파일을 두는 구조 대신, DAG 코드를 하나의 단위로 묶는 DAG Bundle이라는 개념이 도입되었습니다.
DAG Bundle에는 두가지 종류가 있습니다.
| 종류 | 설명 | 버전 관리 |
|---|---|---|
| LocalDagBundle | 기존처럼 dags/ 폴더에서 로딩 |
안됨 |
| GitDagBundle | Git 저장소에서 DAG 코드를 불러옴 | 가능 |
DAG Bundle 구조 덕분에 Airflow는 DAG 실행 시 해당 시점의 DAG 코드 상태를 버전(v1, v2, …)으로 고정할 수 있게 되었습니다.
DAG Versioning 실습
이제 직접 실습을 통해 DAG Versioning을 어떻게 사용하는지 알아보겠습니다.
1. 실습 환경 구성(with Astro CLI)
Airflow 3.x 환경이 이미 구성되어 있다면 바로 사용해보실 수 있지만, 이 글에서는 더 간편한 방법으로 Astro CLI를 활용하겠습니다.
Astro CLI 설치와 사용법은 아래의 공식 문서와 글을 통해서 알아보실 수 있습니다.
설치 후, 버전을 확인합니다:
$ astro version
Astro CLI Version: 1.34.0
Astro CLI의 버전이 1.34.0 이라면 Airflow 3 버전을 지원하므로 이 글의 내용을 그대로 따라 하실 수 있습니다. 만약 버전이 더 낮다면, 최신 버전으로 업그레이드해 주세요.
2. 예제 프로젝트 Fork & Clone
이제 실습을 위한 예제 프로젝트를 포크하고 클론해줍니다.
https://github.com/AirflowKorea/dag-versioning-example
git clone https://github.com/{username}/dag-versioning-example.git
cd dag-versioning-example
3. 간단한 예제 DAG 작성 (LocalDagBundle 사용)
간단한 dag_versioning_example라는 이름의 DAG를 작성해보았습니다.
from airflow.sdk import dag, task, chain
from pendulum import datetime
@dag(
schedule="@daily",
start_date=datetime(2025, 5, 1),
tags=["example", "dag_versioning"],
default_args={
"owner": "Airflow Korea",
"retries": 3,
},
)
def dag_versioning_example():
@task
def task_1():
print("Hello! task_1")
@task
def task_2():
print("Hello! tast_2")
chain(
task_1(),
task_2(),
)
dag_versioning_example()
이 상태에서 astro dev start 명령어로 Airflow를 실행하면
http://localhost:8080에서 Airflow 3의 새 UI를 볼 수 있어요.
4. DAG 실행 및 버전 확인
왼쪽 사이드바의 Dags를 통해서 현재 DAG들을 볼 수 있는데요.
저희가 만든 dag_versioning_example DAG가 있는 것을 확인할 수 있습니다.
DAG를 선택해서 보면, 자세한 DAG에 대한 정보를 볼 수 있습니다.
DAG의 버전과 관련된 내용은 우측 상단의 Latest Dag Version을 통해서 확인할 수 있습니다.
현재 버전은 v1버전으로 되어있는 것을 볼 수 있습니다.
DAG버전은 Trigger를 기점으로 지정이 되므로 Trigger를 해봅시다.
이렇게 DAG가 한 번 실행되면 v1으로 고정됩니다.
그럼 DAG를 수정을 해봅시다. 아래의 코드 처럼 task_3을 추가했습니다.
from airflow.sdk import dag, task, chain
from pendulum import datetime
@dag(
schedule="@daily",
start_date=datetime(2025, 5, 1),
tags=["example", "dag_versioning"],
default_args={
"owner": "Airflow Korea",
"retries": 3,
},
)
def dag_versioning_example():
@task
def task_1():
print("Hello! task_1")
@task
def task_2():
print("Hello! tast_2")
@task
def task_3():
print("Hello! tast_3")
chain(
task_1(),
task_2(),
task_3(),
)
dag_versioning_example()
변경 후 저장하고 UI에서 다시 DAG를 Trigger하면,
이제 새로운 실행은 v2로 관리됩니다.
그래프 뷰에서 각 버전별로 task가 어떻게 구성되어있는지도 확인가능합니다.
LocalDagBundle의 한계
앞선 설명에서 LocalDagBundle은 버전관리가 안된다고 했었는데, v1, v2로 잘되는 것으로 보입니다.
하지만 이는 UI상에서만 DAG가 수정되었다는 사실만 확인이 가능한 것입니다.
간단하게 이 사실을 확인가능 한 것이 v1으로 실행된 DAG를 재실행하면 아래와 같이 최신 DAG코드로 실행이 된 것을 확인할 수 있습니다.
LocalDagBundle와 GitDagBundle을 비교하면 아래와 같습니다.
| LocalDagBundle | GitDagBundle | |
|---|---|---|
| 과거 DAG 재실행 | 최신 DAG 코드 사용 | 당시 DAG 버전 코드 사용 |
| 개별 task 재실행 | 최신 DAG 코드 사용 | 당시 DAG 버전의 task 코드 사용 |
| DAG 실행 중 코드 변경 | 새 코드로 계속 실행 | 기존 DAG 버전 코드로 끝까지 실행 |
그래서 LocalDagBundle은 개발환경에서는 적합하지만, DAG의 버전 관리가 되지 않는다고 볼 수 있습니다.
예를 들어 v1 실행을 다시 Run하면 v2 코드가 사용되는 등, 버전 고정이 되지 않습니다.
5. GitDagBundle을 활용한 버전 관리
앞서 설명한 LocalDagBundle은 버전을 만들 수는 있지만, 관리할 수는 없습니다.
버전을 관리하기 위해서는 GitDagBundle을 사용해야하는데요.
6. apache-airflow-provider-git Provider 와 git 설치
필요한 설정
requirements.txt에apache-airflow-provider-git를 추가해줍니다.
provider의 최신버전은 아래의 링크에서 확인하실 수 있습니다.
-
packages.txt에도 git을 추가해줍니다.
-
.env수정
GitHub에서 Personal Access Token을 발급받고,.env에 host부분에는 저장소의 레포지토리 주소와 password부분에는 발급받은 토큰을 설정해줍니다.
AIRFLOW_CONN_GIT_DEFAULT='{
"conn_type": "git",
"host": "https://github.com/<account>/<repo>.git",
"password": "github_token"
}'
AIRFLOW__DAG_PROCESSOR__DAG_BUNDLE_CONFIG_LIST='[
{
"name": "git-dags-bundle",
"classpath": "airflow.providers.git.bundles.git.GitDagBundle",
"kwargs": {
"git_conn_id": "my_git_conn",
"subdir": "dags",
"tracking_ref": "main",
"refresh_interval": 10
}
}
]'
7. DAG Versioning
깔끔하게 정리하고 싶다면, 아래의 명령어로 컨테이너를 지우고 다시 시작해줍니다.
astro dev stop && astro dev kill
astro dev start
그럼 아래와 같이 Git 저장소에서 DAG를 불러오고, DAG를 트리거하면 v1 버전으로 실행되는 것을 확인할 수 있습니다.
그럼 DAG를 수정해봅시다. 이번에는 이전에 추가했던 task_3를 삭제해보겠습니다.
수정하고 trigger를 해봅니다.
task_3를 삭제했는데 task_3가 실행되는 것을 확인해볼 수 있습니다.
이는 DAG를 깃허브 저장소에서 가져오기 때문입니다. 반드시 Git에 커밋되어야 새로운 버전이 적용됩니다.
커밋을 하고 다시 trigger해줍니다.
task_3가 사라지고 버전이 v2로 고정된 것을 확인할 수 있습니다.
그리드 뷰에서도 버전을 잘 확인할 수 있습니다.
그리고 task_3를 다시 돌려놓고 다시 커밋을 하면 v3로 정상적으로 버전이 잘 올라가는 것을 확인할 수 있습니다.
그럼 지금 task_3가 없었던 v2 DAG를 트리거 할 수 있는지 볼까요?
DAG를 Clear Run을 해봅시다.
정상적으로 잘 되는 것을 확인할 수 있습니다.
v1 버전도 진행해봅시다.
정상적으로 잘 실행되는 것을 확인 할 수 있습니다.
8. DAG 버전 자세히 확인하기
DAG Versioning의 진가를 느낄 수 있는 부분은 바로 각 DAG run에서 정확히 어떤 코드가 사용되었는지 확인할 수 있다는 점입니다.
각 DAG run의 Details 을 확인해보면 DAG의 버전에 어떤 Bundle에 대한 자세한 설명과 어떤 코드가 사용되었는지 확인해볼 수 있습니다.
마무리
Airflow 3.x에 도입된 DAG Versioning 기능은 정말 반가운 변화입니다.
이제는 “어..? 이 실행이 코드가 바뀌기 전이었나?” 같은 고민 없이,
정확히 어떤 DAG 코드로 실행되었는지 추적할 수 있게 됐어요.
그리고 과거 버전의 DAG도 안정적으로 재실행할 수 있어서 운영 환경에서의 신뢰성도 훨씬 올라갑니다.
이제 DAG도 코드처럼 버전 관리하고, 과거로 돌아가며 실험하고, 변경 이력을 체계적으로 추적하는 것이 가능해졌습니다.
궁금한 점이나 더 다뤄줬으면 하는 내용이 있다면 댓글로 알려주세요 ![]()
























