E | ngineering

Airflow Design Patterns

덞웖이 2025. 3. 25. 05:31
댁을 작성하면서 반성하면서 생각한 주제

에어플로 센서와 DAG 작성에 관한 이야기
이하 DAG는 에어플로 DAG를 칭함

Deferrable Operator

기존의 오퍼레이터는, 실행되면 CPU와 리소스를 끝날 때까지 점유.

👉🏿 Polling을 하는 등 대기하는 작업에는 쥐약...

👉🏿 Deferrable Operator는 작업이 바로 끝나지 않더라도, Triggerer 프로세스로 제어권 넘기고, 리소스 반환.

👉🏿 특정 이벤트가 발생하거나 polling 결과가 변화했을 때 컨티뉴.

👉🏿 HttpSensor, S3KeySensor, SQLSensor 요런거.

👉🏿 비동기 방식으로 리소스 사용을 최적화.

👉🏿 커스텀 트리거를 만들어서, 커스텀 오퍼레이터에서 사용하면 커스텀 센서를 만들 수 잇다. execute 메소드를 활용하는/안하는 방법이 있는데, 그건 똑큐먼트를 찾아보자...


Operator Pattern과 Event-driven 패턴

🍕 Operator Pattern

👉🏿 모든 작업은 Operator의 인스턴스가 정의하고, 각각의 Operator는 하나의 작업만을 수행해야 함.

👉🏿 즉, DAG 안에서 복잡한 비즈니스 로직을 작성하거나, if-else 문으로 흐름을 분기하면 ❌.

👉🏿 그런 건 따로 분리하고, 인자값과 함께 Operator를 호출만 하는 식으로 설계해야 함.

🍔 Event-driven Pattern

👉🏿 S3에 파일이 생기면 시작하는, Kafka 토픽에 메시지가 들어오면 트리거 되는 파이프라인 등.

👉🏿 시점에서 볼 떄, Deferrable Operator나 External Trigger등은 이걸 따라가려고 도입함.

👉🏿 그래도 Schedule 기반! 완전한 이벤트 드리븐 패러다임으로 구현하기엔 무리.

👉🏿 는 polling 등으로 체크하는 pull-base 라는 점과 카프카, 람다 등은 이벤트에 반응하는 push-base라는 점.


그래도 로직이 넣구싶어요

DAG는 워크플로우를 정의하는 블루프린트임.

여기에 빋닏 로직을 직접 넣기 시작하면...🤪

☝🏿 테스트: 로직에 대해서 유닛 테스트 어터게 할거임?

🤞🏿 재사용성: 로직이랑 댁이 결합도가 높은식으로 만들면, 오퍼레이터 날마다 맹글어야겟네?

🤟🏿 가독성: 스압... ctrl + f 로 찾는것도 한계가 잇찌 🤮

로직은 별도의 Python 모듈로 작성하고 DAG에서 모듈 import하고... 그렇게는 하지 맙시다 😇

하지마 제발 (나한테)


구럼 쏀써 사용은 철학에 어긋나니 쓰면 안되나

센서 사용 자체가 잘못된 것은 아니지만,

가능하면 Deferrable Sensor를 써서 리소스 아끼기

한 DAG가 다른 DAG 실행 여부를 감시/기다리는 구조 피하기

디자인 철학 중 하나인 DAG 간의 독립성을 고려했을 때,
DAG가 다른 DAG의 상태나 결과를 알아야 한다면,
DAG간 결합도가 높음을 의미,
전체 시스템 복잡도가 높아짐.

API 호출로 다른 DAG를 트리거하거나, 메시지 브로커를 사용해서 트리거할 수 있다면 (일적으로 오버헤드가 증가하긴 하지만...) 더 자연스러워지지 않을까유💤


TL;DR

설계와 운영 원칙

  1. 워크플로우와 비즈니스 로직의 분리.
  2. Deferrable Operator로 리소스 최적화. reschedule!!
  3. 센서 사용은 필요할 때만, 가능하면 이벤트 기반으로.
  4. DAG간의 의존(결합)을 최소화, 시스템 확장성과 유지보수 고려.

👿 안 그러면 복잡해진 DAG를 보면서 울고 리뷰어의 철퇴를 맞을것임. 🔨

👋🏿