본문으로 건너뛰기

© 2026 Molayo

Dev.to헤드라인2026. 06. 17. 03:11

Rust로 구축한 셀프 호스팅형 AI 네이티브 워크플로우 엔진 (180개 노드 타입, SDK 비대화 없음)

요약

Rust로 구축된 오픈 소스 셀프 호스팅 워크플로우 자동화 플랫폼 Trigix를 소개합니다. 180개 이상의 노드를 지원하며, 시스템 의존성을 최소화하기 위해 순수 Rust 구현체를 사용하여 높은 이식성을 제공합니다.

핵심 포인트

  • Rust 기반의 비동기 DAG 스케줄링 엔진 구현
  • 시스템 라이브러리 의존성 없는 'cargo build' 중심의 설계
  • AWS SigV4 직접 구현을 통한 SDK 의존성 제거
  • russh를 활용한 순수 Rust 기반 SSH/SFTP 지원

저는 지난 시간 동안 **Trigix**를 구축하는 데 시간을 보냈습니다. 이는 오픈 소스(MIT)이며 셀프 호스팅이 가능한 워크플로우 자동화 플랫폼입니다. n8n을 떠올리시면 되지만, 실행 엔진은 Rust로 작성되었으며 AI 노드는 완전히 로컬 모델을 대상으로 실행될 수 있습니다. 이 포스트는 기능 소개가 아니라, 공유할 가치가 있다고 생각하는 몇 가지 엔지니어링 결정에 관한 것입니다.

노드 모델: 하나의 트레이트(trait), 약 180개의 구현체

워크플로우는 타입이 지정된 노드들의 DAG(Directed Acyclic Graph, 방향성 비순환 그래프)입니다. 모든 노드는 NodeType 열거형(enum)의 하나의 변체(variant)이자 하나의 비동기(async) 함수입니다:

match node.node_type {
    NodeType::Http     => execute_http(node, ctx, &client).await,
    NodeType::Agent    => execute_agent(node, ctx, &client, ai_url).await,
...

노드 타입을 추가하려면 정해진 위치들(열거형 변체, 실행기 구현(executor impl), 디스패치 암(dispatch arm), node_type → str 맵, 그리고 프론트엔드 팔레트/설정 패널)을 수정해야 합니다. 이는 기계적인 작업이며, 이것이 핵심입니다. 즉, 새로운 통합(integration)의 비용이 제한적이고 검토 가능하며, 컴파일러가 수정해야 할 지점을 놓쳤을 때 알려줍니다.

엔진 자체는 병렬 팬아웃/팬인(fan-out/fan-in), 재시도(retries), 타임아웃(timeouts), 취소(cancellation), 그리고 서브 워크플로우(sub-workflows)를 포함하는 비동기 DAG 스케줄링이라는 흥미로운 부분을 담당하지만, 노드 카탈로그는 대부분의 표면적이 존재하는 곳이므로, 저는 "추가하기 쉽고 미묘하게 틀리기 어렵게" 만드는 데 집중하여 최적화했습니다.

HTTP 우선 방식, 따라서 대부분의 "통합"은 단순한 설정 + 인증일 뿐입니다

대부분의 SaaS/DB/벡터 스토어(vector-store)/클라우드 노드는 { status, body }를 반환하는 얇은 HTTP 클라이언트입니다.

셀프 호스팅형 도구는 "먼저 이 시스템 라이브러리들을 설치하세요"라는 각주 없이 cargo build만으로 어디서든 빌드될 수 있어야 합니다. 이러한 제약 조건이 몇 가지 선택을 이끌어냈습니다.

AWS (SQS/SNS/Bedrock). AWS SDK를 가져오는 대신, 이미 트리에 포함된 암호화 크레이트(sha2/hmac/hex)를 사용하여 Signature V4를 처음부터 직접 구현했습니다. 안심할 수 있는 부분은 AWS가 SigV4 테스트 스위트를 공개하고 있어, 서명기(signer)가 표준 get-vanilla 벡터에 대해 단위 테스트(unit-test)를 거쳤다는 점입니다:

// 서명기는 AWS가 공개한 서명을 정확히 재현해야 합니다.
assert!(auth.ends_with(
  "Signature=5fa00fa31553b73ebf1942676e86291e8372ff2a2260956d9b8aae1d763fbf31"
...

이 단 하나의 테스트는 수백 번의 왕복 모킹(round-trip mocks)보다 가치 있습니다. 이는 표준 요청(canonical-request)과 서명 키(signing-key) 유도 과정을 검증된 정답에 고정(pin)시켜 줍니다.

SSH/SFTP. 명백한 크레이트인 ssh2는 libssh2에 바인딩되는데, 이는 개발용 헤더(및 cmake)가 없는 사용자에게는 빌드를 깨뜨리는 시스템 의존성입니다. 그래서 저는 순수 Rust 구현체인 russh + russh-sftp를 사용했습니다. 덕분에 cargo build는 자기 완결적(self-contained)인 상태를 유지하며, 비밀번호 및 개인 키 인증(private-key auth) 모두 작동합니다.

SQL Server. 동일한 논리로, tiberius는 순수 Rust TDS 드라이버이므로 MSSQL 노드에 네이티브 클라이언트가 필요하지 않습니다.

OCR. 이 부분은 무거운 네이티브 의존성 없이 순수 Rust로 유지할 수 없었기에, 빌드 시점에 libtesseract를 링크하는 대신 노드가 런타임(runtime)에 tesseract CLI를 셸 명령(shell out)으로 호출하도록 했습니다. 워크스페이스는 여전히 어디서든 빌드됩니다. 다만 OCR은 해당 노드가 실제로 실행될 때 바이너리가 존재해야 합니다. 이러한 경계를 명확히 하는 것이 깨끗한 환경(clean machine)에서 빌드가 실패하는 것보다 훨씬 낫습니다.

핵심 테마는 이것입니다: 빌드(build) 시점의 시스템 의존성은 모든 기여자(contributor)와 CI 실행에 부과되는 세금이지만, 런타임(runtime) 시점의 의존성은 선택 사항(opt-in)이며 해당 기능을 사용하는 사람들만이 지불하면 됩니다.

로컬 우선 AI (Local-first AI)

LLM/agent/RAG 노드들은 OpenAI 호환 와이어 포맷 (wire format)을 사용하므로, 로컬의 Ollama 또는 vLLM을 가리켜 전체 AI 측면을 오프라인으로 실행할 수 있습니다. RAG 검색 (retrieval)은 하이브리드 (벡터 + 전체 텍스트) 검색, 선택적 재순위화 (reranking), 그리고 HNSW 인덱스를 갖춘 자체 Postgres/pgvector에서 실행됩니다. 클라우드 제공업체는 선택 사항이며 필수 사항이 아닙니다. 이는 데이터를 외부로 전송하는 것을 피하기 위해 정확히 셀프 호스팅을 하는 경우 매우 중요합니다.

사용해 보기

docker compose -f docker-compose.poc.yml up -d --build

이 명령은 콘솔/API, Postgres+pgvector, Redis, 그리고 선택적인 AI 런타임 (runtime)을 실행합니다. 또한 VM을 할당하기 전에 살펴보고 싶다면 GHCR에 있는 Helm 차트와 클릭 한 번으로 실행 가능한 GitHub Codespaces devcontainer도 제공됩니다.

솔직한 상태 보고: 이 프로젝트는 아직 초기 단계이며 제가 주요 저자입니다. 600개 이상의 테스트와 v1.3.0 릴리스가 있지만, 그에 맞춰 적절히 다뤄주시기 바랍니다. 그리고 이 플랫폼에서 관련이 있는 내용이기에 투명하게 말씀드리자면, 저는 이를 구축하는 동안 AI 코딩 어시스턴트 (coding assistants)를 사용했습니다. 하지만 이는 단 한 번의 생성으로 만들어진 저장소가 아니라, 실제로 작동하고 테스트된 코드베이스입니다.

저장소: https://github.com/bj-qizhi/trigix — 특히 엔진 설계와 노드 모델에 대한 피드백을 환영합니다.

AI 자동 생성 콘텐츠

본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.

원문 바로가기
0

댓글

0