목록전체 글 (115)
ㅅㅇ
— 복잡하게 얽힌 600만 건 데이터 처리 경험을 기반으로 정리한 설계 원칙600만 건 규모의 상품 데이터를 처리하는 배치를 운영하면서 workload 구조의 한계를 명확히 경험했습니다.이 데이터는 여러 RDB에 흩어진 상품 정보를 수집·가공하여 하나의 모델로 통합해야 하는 구조였습니다. 단순히 데이터 양이 많은 것을 넘어, 데이터 간 의존성과 정합성을 함께 고려해야 했습니다.특히 LLM 임베딩처럼 처리 시간이 긴 작업은 실패 한 번이 수 시간의 손실로 이어졌습니다.초기에는 단순히 Retry 횟수를 늘리는 방식으로 대응했습니다.하지만 재시도가 누적될수록 중복 데이터, 리소스 고갈, queued 병목이 발생했고, 장애 복구 시간도 점점 길어졌습니다.문제의 본질은 실패가 아니라 “재실행을 전제로 하지 않은 ..
— LocalExecutor 환경에서 정립한 Airflow 구조 설계 원칙온프레미스 환경에서 LocalExecutor를 사용하고 있었습니다.VM 자원은 제한적이었고, 분산 환경으로 확장하기는 현실적으로 어려웠습니다. 운영이 안정적이던 시점 이후, 특정 DAG들이 점점 무거워지기 시작했습니다.그에 따라 Scheduler 부하가 증가했고, 일부 DAG는 queued 상태에서 지연되는 현상이 발생했습니다. 처음에는 태스크 내부 로직의 문제라고 생각했습니다.하지만 실제 병목은 실행 단계가 아니라 DAG 로딩(파싱) 단계에 있었습니다. Airflow Scheduler는 DAG 파일을 주기적으로 재파싱합니다.즉, DAG는 한 번 실행되는 코드가 아니라, Scheduler에 의해 반복적으로 해석되는 대상입니다. 이 ..
Airflow를 운영 시스템으로 사용하다 보면 자연스럽게 이런 문제가 발생합니다.DAG 안에서 찍은 로그는 Airflow UI에서 잘 보입니다.하지만 외부 Python 모듈(wheel 패키지)에서 찍은 로그는 따로 분리되거나, 아예 Task Log에 나오지 않습니다.결국 장애가 발생하면 DAG 로그와 비즈니스 로직 로그를 번갈아 보면서 추적해야 하는 상황이 됩니다.이 글에서는 Airflow 3.x 기준으로, Custom Module 로그를 Airflow Task Log로 완전히 통합하는 구조를 정리하고자 합니다.목표DAG 로그와 외부 Python App 모듈 로그를 Airflow UI의 “하나의 Task Log 화면”에서 함께 확인할 수 있도록 구성하기 핵심 원칙Airflow 3.x에서 logging_..
운영 환경에서 특정 DAG가 장시간 실행되며 CPU와 메모리를 과도하게 점유하면서,다른 도메인의 DAG까지 queued 상태로 밀리는 문제가 발생했습니다. Airflow는 Executor가 허용하는 범위 내에서 가능한 많은 Task를 병렬 실행합니다. 이 과정에서 리소스를 많이 사용하는 Task가 Executor 자리를 선점하면,상대적으로 가벼운 Task도 실행 기회를 얻지 못하는 문제가 발생합니다. 이 문제를 해결하기 위해 Pool을 활용한 논리적 격리 전략을 도입했습니다.Pool 이란 ?Pool은 CPU/RAM과 같은 물리 자원을 격리하는 기능이 아닙니다.대신, Task 실행 개수를 논리적으로 제한하는 제어 장치입니다.“물리적 격리”가 아니라 “논리적 실행 제어”모든 Pool은 동일한 VM 자원을 공..
기존에는 Docker Compose만을 이용하여 로컬에서 Airflow를 실행하고 테스트했습니다.통합 테스트 관점에서는 충분했지만, 실제 로직을 추적하며 디버깅하기에는 불편함이 있었습니다. 특히,breakpoint 사용 불가step-through 디버깅 불가태스크 단위 검증의 번거로움이 문제로 인해 IDE 기반 디버깅 환경의 필요성을 느끼게 되었습니다.그래서 다음과 같이 개발 환경을 이원화하였습니다. 로컬 개발 환경 전략에 대해서 설명 드리고, Airflow Debug 환경 구축 방법에 대해 공유하고자 합니다.Airflow 로컬 실행 환경 전략1. Airflow Debug Test로컬 개발/디버깅 용IDE 디버깅(PyCharm) 사용로컬 Python venv (uv 기반)의 airflow 사용dags t..
List 를 만드는 두 가지 방법 new ArrayList()와 Arrays.asList() 의 차이 1. new ArrayList() ArrayList를 리턴 2. Arrays.asList() Arrays의 정적 클래스인 ArrayList를 리턴 Arrays.asList() 만의 특징 Arrays.asList()는 고정된 List이기 때문에 원소를 추가, 삭제 할 수 없다. list.add() 가 불가능한 것. 변경은 가능하다. import java.util.ArrayList; // new ArrayList() import java.util.Arrays; // Arrays.asList() String[] str = {"1", "2", "3"}; List list = Arrays.asList(str); ..