
Rust로 만든 무료 로컬 우선 ETL 도구 — 영어로 파이프라인을 설명하고 SQL 또는 Python으로 전환하기
요약
Rust와 Apache DataFusion 기반의 로컬 우선 ETL 도구인 Odara를 소개합니다. 자연어 설명을 통해 파이프라인 노드를 생성하고, 시각적 캔버스와 SQL/Python 코드를 자유롭게 오가며 데이터 워크플로우를 설계할 수 있습니다.
핵심 포인트
- Rust 기반의 가볍고 빠른 로컬 실행 환경 제공
- 자연어 입력을 통한 AI 기반 파이프라인 초안 생성
- 시각적 UI와 SQL/Python 코드 간의 유연한 전환 지원
- DeepSeek, Claude, OpenAI 등 다양한 LLM 호환 가능
제가 사용해 온 모든 ETL 도구는 하나를 얻으면 하나를 포기해야 하는 트레이드오프(trade-off)를 강요했습니다.
시각적 도구들(Talend, Informatica, NiFi)은 접근하기 쉽지만 무겁습니다. JVM이 필요하고, 라이선스 협의가 필요하며, UI가 예상하지 못한 로직이 필요한 순간 거대한 벽에 부딪히게 됩니다. 코드 우선(code-first) 방식은 그 반대입니다. 완전한 제어가 가능하지만, 단 한 줄의 데이터를 옮기기도 전에 보일러플레이트(boilerplate) 코드를 작성하고 커넥터를 연결해야 합니다.
저는 그 중간을 원했습니다. 파이프라인의 형태를 시각적으로 스케치하고, 실제 로직이 필요한 즉시 동일한 캔버스 내에서 SQL이나 Python으로 전환하는 것 — 컨텍스트 스위칭(context switch)도, 코드로의 내보내기(export-to-code)도, JVM도 필요 없는 방식 말입니다. 그래서 직접 만들었습니다.
이 도구의 이름은 Odara입니다. 무료이며, 사용자의 로컬 머신에서 실행되고, 엔진은 Rust와 Apache DataFusion으로 구성되어 있습니다. 실제로 어떤 기능을 하는지 소개하겠습니다.
파이프라인을 설명하고 노드(node)를 생성하기
제가 가장 많이 사용하는 부분은 이렇습니다. 목표를 평이한 영어로 입력하면 AI 어시스턴트가 타입이 지정된 노드(typed nodes)의 순서 목록을 초안으로 작성해 줍니다. 이는 블랙박스를 생성하는 것이 아니라, 캔버스에 배치하기 전에 사용자가 검토할 수 있는 실제 편집 가능한 노드들을 제안합니다.
"PostgreSQL에서 주문을 읽어오고, 완료된 주문만 유지하며, 카테고리 및 월별 총 매출을 계산하여 Snowflake에 기록하라"
...이 명령은 Postgres 소스(source) → 필터(filter) → SQL 집계(aggregation) → Snowflake 타겟(target)으로 변환됩니다. 사용자는 이를 검토하고, 수정하고, 실행합니다. 어시스턴트는 DeepSeek, Anthropic/Claude, Gemini 또는 모든 OpenAI 호환 제공업체와 함께 작동합니다. 사용자가 직접 키를 가져오며, 특정 벤더에 하드코딩되어 있지 않습니다.
AI는 시작점일 뿐, 감옥이 아닙니다. 이는 매우 중요한데, 그 다음에 당신이 하고 싶어 할 일은 바로 '편집'이기 때문입니다.
원할 때는 시각적으로, 필요할 때는 코드로
각 노드는 소스(source), 변환(transform), 타겟(target)과 같은 하나의 작고 단일 목적을 가진 블록입니다. 사용자는 이를 React Flow 캔버스 위에서 연결합니다.
변환(transforms) 단계는 "다국어(polyglot)" 개념이 빛을 발하는 지점입니다:
- **SQL 변환 (SQL transforms)**은 DataFusion에서 실행됩니다. 이는 Apache Arrow 네이티브이자 Rust 네이티브로, 조인(join)이나 집계(aggregation)를 계산하기 위해 외부 데이터베이스가 필요하지 않습니다.
- **Python 변환 (Python transforms)**은 데이터 전달을 위해 PyArrow를 사용하는 서브프로세스(subprocess) 내에서 실행되므로, 엔진이 Rust를 벗어나지 않고도 pandas, numpy 또는 필요한 무엇이든 사용할 수 있습니다.
하나의 파이프라인 내에서 이 두 가지를 혼합할 수 있습니다. 집계를 위한 SQL 블록, SQL로 표현할 수 없는 특정 라이브러리를 호출하기 위한 Python 블록, 그리고 출력을 구성하기 위한 또 다른 SQL 블록을 사용할 수 있습니다. 데이터는 단계 사이에서 전체 과정 동안 Arrow RecordBatch로 이동하므로, 단계 간에 CSV로 변환하여 왕복하는 과정이 없습니다.
실제로 자주 사용하게 될 커넥터(connectors)
기본적으로 지원되는 소스(sources) 및 타겟(targets)은 다음과 같습니다:
- 데이터베이스 (Databases): PostgreSQL, MySQL, Oracle, SQL Server, MongoDB, Snowflake, DB2, 일반 ODBC
- 파일 (Files): CSV, Excel, XML, 그리고 형식을 자동 감지하는 "Magic File" 노드
- 클라우드 스토리지 (Cloud storage): S3, Google Drive, Azure Blob
- 전송 (Transfer): FTP / SFTP / FTPS
- API: REST 소스 (페이지네이션, 인증, 재시도가 포함된 GET) 및 REST 타겟 (배칭(batching)이 포함된 POST/PUT/PATCH)
- 스트리밍 (Streaming): 윈도우(window)/집계(aggregate)/조인(join) 연산자를 포함한 Kafka, RabbitMQ, NATS, MQTT
또한 Talend의 tMap 스타일인 매퍼 (Mapper) 노드도 있습니다. N개의 입력, M개의 출력, 조인, 그리고 필드별 표현식(per-field expressions)을 지원하여, 다른 방식으로 표현하기 까다로운 매핑 중심의 작업을 처리할 수 있습니다.
실행 및 모니터링
파이프라인은 SSE를 통해 실시간 진행 상황을 보여주며 실행됩니다. 모니터는 실행당 상태, 소요 시간, 행 수(row counts)를 표시하며, 실패를 숨기지 않습니다. 실패한 커넥터나 끊어진 조건부 분기(conditional branch)는 실제 오류 메시지와 함께 빨간색으로 표시됩니다.
단일 파이프라인보다 큰 규모를 다룰 때는 오케스트레이션 레이어(Maestro)가 파이프라인을 병렬(parallel), 직렬(series), 또는 조건부(conditionally)로 실행합니다. 그리고 모든 것은 Git으로 버전 관리가 됩니다. 파이프라인은 단순한 정의(definition)일 뿐이므로, 코드처럼 브랜치(branch)를 나누고 차이점(diff)을 비교할 수 있습니다.
왜 Rust인가
지루한 답변이 사실이기 때문입니다. JVM이 없다는 것은 수백 MB에 달하는 런타임(runtime)과 로드 도중 발생하는 GC(Garbage Collection) 일시 정지(pause)가 없음을 의미합니다. 전체 시스템은 빠르게 시작되고 가볍게 유지되는 네이티브 바이너리(native binary)입니다. 실행 시 CancellationToken을 통한 적절한 취소(cancellation)를 지원하며, 작업(job)은 SQLite(WAL 모드)에 영구 저장되고, 연결 자격 증명(connection credentials)은 AES-GCM으로 저장 시 암호화됩니다.
기본적으로 로컬 우선(local-first) 방식입니다. 여러분의 데이터와 파이프라인은 여러분의 머신에 머뭅니다. 여러분이 선택하지 않은 클라우드로 아무것도 전송되지 않습니다.
솔직한 현재 상황
JVM 비용과 라이선스 문제 없이 시각적 ETL 도구의 접근성을 원했거나, 혹은 단지 문장 하나로 파이프라인을 설명하고 실제로 편집 가능한 SQL을 얻고 싶었다면, 여러분의 피드백을 진심으로 기다리고 있습니다.
직접 체험해 보세요: https://odara.rs
이런 도구가 가장 먼저 해결해주길 바라는 ETL의 고충(pain point)은 무엇인가요? 댓글로 남겨주세요. 저는 진공 상태의 로드맵이 아니라, 실제 워크플로(workflow)를 바탕으로 구축하고 있습니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기
