안녕하세요! 지난 글에서 우리는 데이터 파이프라인의 클래식, 아파치 에어플로우(Airflow)에 대해 깊이 알아보았습니다. 에어플로우는 의심할 여지 없이 강력하고 안정적인 도구이지만, 일부 개발자들은 그의 방식에 몇 가지 불편함을 느끼기 시작했습니다.
"워크플로우를 좀 더 파이썬 코드처럼 자연스럽게 짤 수는 없을까?"
"로컬에서 테스트하는 과정이 너무 번거로워. 실제 배포 환경과 너무 다르잖아."
"실패는 언제나 일어날 수 있는 일인데, 단순히 재시도하는 것 이상의 스마트한 대처는 불가능할까?"이러한 '불편함(Pain Points)' 속에서, 데이터 파이프라인을 바라보는 새로운 관점을 제시하는 도구가 등장했습니다. 바로 오늘 우리가 깊이 파헤쳐 볼 프리펙트(Prefect)입니다. 프리펙트는 '성공'을 넘어 '실패'를 다루는 방식에 집중하며, 데이터 파이프라인에 '회복탄력성'이라는 새로운 가치를 불어넣습니다. 이 글에서는 프리펙트가 에어플로우와 어떻게 다른 철학을 가졌는지, 그리고 어떤 혁신적인 기능으로 개발자들의 마음을 사로잡고 있는지 상세히 공유하고자 합니다.
프리펙트란? 예상치 못한 실패를 당연한 것으로 간주하고, 데이터 파이프라인이 어떤 상황에서도 살아남도록 만드는 '회복탄력성'에 초점을 맞춘 현대적인 워크플로우 플랫폼입니다.
에어플로우의 핵심 철학이 "워크플로우를 코드로(Workflows as Code)"였다면, 프리펙트의 핵심 철학은 "네거티브 엔지니어링(Negative Engineering)"입니다. 쉽게 말해, "일이 잘될 때가 아니라, 잘못될 때를 대비하여 시스템을 설계한다"는 뜻입니다.
이 철학을 이해하기 위해, 프리펙트를 '최첨단 스마트 물류 및 배송 시스템'에 비유해 봅시다.
@flow
라는 파이썬 데코레이터 하나로 매우 간단하게 정의됩니다.@task
데코레이터로 정의됩니다.이 비유처럼, 프리펙트는 정적인 계획을 실행하는 것을 넘어, 예상치 못한 변수로 가득한 현실 세계에서 계획이 끝까지 완수되도록 돕는 동적이고 지능적인 시스템에 가깝습니다.
프리펙트의 코드는 놀라울 정도로 파이썬 본연의 모습에 가깝습니다. 에어플로우의 복잡한 객체 선언 대신, '데코레이터'를 활용하여 매우 직관적으로 워크플로우를 구성합니다.
프리펙트에서는 일반 파이썬 함수에 데코레이터만 붙이면 바로 워크플로우의 구성 요소가 됩니다.
@flow
: 워크플로우 전체를 감싸는 컨테이너입니다. 이 데코레이터가 붙은 함수 안에서 Task나 다른 Flow(Subflow)를 호출하여 전체 흐름을 만듭니다.@task
: 워크플로우를 구성하는 개별 작업 단위입니다. 재시도, 타임아웃, 캐싱 등의 복잡한 기능을 @task(retries=3, retry_delay_seconds=10, cache_key_fn=...)
와 같이 데코레이터의 인자(argument)로 매우 간단하게 설정할 수 있습니다.# 간단한 Flow 파일 예시 (my_flow.py)
from prefect import flow, task
from typing import List
import httpx # 외부 라이브러리
@task(retries=3, retry_delay_seconds=5)
def fetch_data(url: str) -> dict:
# API 호출 실패 시 5초 간격으로 3번 재시도
response = httpx.get(url)
response.raise_for_status()
return response.json()
@task
def process_data(data: dict) -> List[int]:
# 데이터 처리 로직
return [item['id'] for item in data['items']]
@flow(name="My First Prefect Flow")
def my_data_pipeline(url: str = "http://example.com/api/data"):
# 일반 파이썬 함수처럼 Task를 호출
raw_data = fetch_data(url)
processed_ids = process_data(raw_data)
print(f"Processed {len(processed_ids)} items.")
if __name__ == "__main__":
# 일반 파이썬 스크립트처럼 바로 실행해서 테스트 가능!
my_data_pipeline()
이 코드는 python my_flow.py
명령어로 즉시 실행하고 테스트할 수 있습니다. 이는 에어플로우의 복잡한 로컬 테스트 환경과 비교했을 때, 개발자 경험(Developer Experience)을 극적으로 향상시키는 프리펙트의 가장 큰 장점 중 하나입니다.
프리펙트의 아키텍처는 에어플로우와 근본적으로 다른, 매우 중요한 특징을 가집니다. 바로 '하이브리드 실행 모델'입니다.
이 모델 덕분에, 코드와 데이터는 항상 여러분의 안전한 환경 안에 머물러 있게 되어 보안과 유연성이 크게 향상됩니다.
프리펙트 2.0의 가장 혁신적인 개념 중 하나는 '배포'입니다. 이는 단순히 코드를 의미하는 것이 아니라, "어떻게, 언제, 어디서 이 플로우를 실행할 것인가"에 대한 모든 정보를 담은 '레시피'입니다.
하나의 배포에는 다음과 같은 정보가 포함됩니다.
flow
함수를 실행할지.이 덕분에 똑같은 my_flow.py
코드 하나를 가지고, '개발용 배포(로컬 실행)', '스테이징용 배포(Docker 실행)', '운영용 배포(Kubernetes 실행)'를 각각 만들어 관리할 수 있습니다. 코드와 실행 환경이 완벽하게 분리되는 것이죠.
프리펙트는 에어플로우가 남긴 몇 가지 아쉬운 점들을 정면으로 돌파하며 탄생했습니다.
문제 1: 경직된 워크플로우 → 해결: 동적인 파이썬 네이티브 워크플로우
에어플로우의 DAG는 한번 정의되면 실행 중에 구조를 바꾸기 어렵습니다. 반면 프리펙트는 일반 파이썬 코드처럼 if/else
나 for
루프를 자유롭게 사용하여, 실행 시점의 조건에 따라 Task의 실행 경로를 동적으로 바꿀 수 있습니다.
문제 2: 개발과 운영의 간극 → 해결: 극도로 쉬운 로컬 테스트
프리펙트는 개발자가 로컬 환경에서 작성한 코드를 거의 그대로 운영 환경에 배포할 수 있도록 설계되었습니다. 일반 파이썬 스크립트처럼 실행하고 디버깅할 수 있어, 개발과 실험의 사이클이 매우 빠릅니다.
문제 3: 코드와 인프라의 결합 → 해결: 안전한 하이브리드 실행 모델
앞서 설명한 'Pull' 방식의 하이브리드 모델은 코드와 데이터의 보안을 강화하고, 다양한 실행 환경에 유연하게 대응할 수 있는 기반을 마련했습니다.
프리펙트는 똑똑한 스마트 물류 시스템처럼, 단순히 배송 계획서(Flow)를 따르는 것을 넘어, 실시간 교통체증이나 차량 고장(실패)과 같은 온갖 예외 상황에 동적으로 대처하여 어떻게든 물건(데이터)을 목적지까지 안전하게 배송하는 것을 최우선 목표로 하는 현대적인 워크플로우 오케스트레이션 플랫폼입니다.
특히 개발자 친화적인 환경과 파이프라인의 회복탄력성을 중시하며, 복잡하고 예측 불가능한 현대 데이터 세계의 문제들을 해결하기 위해 탄생한 세련된 도구라고 할 수 있습니다.
만약 여러분의 팀이 빠른 실험과 잦은 변경을 필요로 하거나, 개발자의 생산성을 극대화하여 더 창의적인 일에 집중하고 싶다면, 이 똑똑한 파일럿, 프리펙트에게 조종간을 맡겨보는 것은 어떨까요?