본문으로 건너뛰기

© 2026 Molayo

Dev.to헤드라인2026. 06. 05. 17:08

자체 호스팅 가능한 오픈 소스 AI 에이전트 런타임을 구축하며 얻은 4가지 뼈아픈 교훈

요약

자체 호스팅 가능한 오픈 소스 AI 에이전트 런타임인 omadia를 구축하며 경험한 설계상의 핵심 교훈을 다룹니다. 모델 성능보다 메모리 격리, 데이터 흐름 제어, UX 설계가 에이전트 시스템 구축의 더 큰 난제임을 강조합니다.

핵심 포인트

  • 에이전트 간 컨텍스트 혼선을 막기 위해 메모리 네임스페이스 격리가 필수적임
  • 도구 출력(tool output)을 신뢰할 수 없는 경계로 취급하여 데이터 유출을 방지해야 함
  • 비엔지니어를 위해 복잡한 설정 대신 단순화된 기본 인터페이스를 제공해야 함
  • 구조에 의한 격리를 기본값으로 설정하고 의도적인 공유를 선택하는 설계가 필요함

플러그인을 통해 AI 에이전트 (AI agents)를 구성할 수 있는 오픈 소스 (MIT), 자체 호스팅 가능한 런타임인 omadia를 구축하기 시작했을 때, 저는 가장 어려운 부분이 모델(model)일 것이라고 가정했습니다. 즉, 프롬프팅 (prompting), 도구 호출 (tool-calling), 신뢰할 수 있는 출력 (reliable output)을 얻는 일 말입니다.

하지만 그렇지 않았습니다. LLM (Large Language Model) 관련 부분은 대부분 이미 해결된 문제들이었습니다. 제 시간을 가장 많이 잡아먹은 부분은 **격리 (isolation), 데이터 흐름 (data flow), 그리고 UX (User Experience)**였습니다. 제가 더 일찍 내면화했더라면 좋았을 네 가지 교훈을 소개합니다.

1. 메모리 격리 (Memory isolation)는 설정의 문제가 아니라 설계의 문제다

단일 에이전트(single agent)를 사용할 때는 전혀 눈치채지 못합니다. 하지만 메모리 저장소 (memory store)를 공유하는 여러 에이전트가 있을 때는 컨텍스트 (context)가 '스며듭니다 (bleeds)'. 에이전트 A가 오직 에이전트 B에게만 전달되었던 사실들을 '기억'하기 시작하는 것입니다. 이는 미묘하고 간헐적으로 발생하며, 특히 서로 다른 에이전트가 서로 다른 사용자나 부서를 담당하게 될 경우 신뢰를 빠르게 무너뜨립니다.

해결책: 각 에이전트(및 각 오케스트레이터 (orchestrator))에 고유한 메모리 네임스페이스 (memory namespace)와 지식 그래프 (knowledge graph)의 개별 슬라이스 (slice)를 부여하고, 채널 바인딩 (channel binding)이 해결되는 시점에 모든 인바운드 메시지를 정확한 에이전트의 네임스페이스로 라우팅하십시오. 에이전트 로직 깊숙한 곳에서 나중에 처리하는 것이 아니라 말입니다.

// 단순화된 예시: 모든 읽기/쓰기의 범위를 해당 턴(turn)을 소유한 에이전트로 제한
const mem = memoryFor(agent.id);      // 격리된 네임스페이스 + KG 슬라이스
await mem.write(turn);
...

트레이드오프 (tradeoff): 의도적인 에이전트 간 공유 (cross-agent sharing)는 명시적으로 설계해야 하는 까다로운 케이스가 됩니다. 하지만 이것이 올바른 기본값입니다. 즉, 구조에 의한 격리 (isolation by construction)를 기본으로 하고, 의도에 의한 공유 (sharing by intent)를 선택하는 것입니다.

2. 데이터는 프롬프트 (prompt)가 아니라 도구 결과 (tool results)를 통해 유출된다

모두가 프롬프트 인젝션 (prompt injection)에 대해 이야기합니다. 하지만 실제로 저를 괴롭혔던 유출은 '나가는' 경로, 즉 도구 결과 (tool results)에서 발생했습니다.

해결책은 모델에 도달하기 전, **레코드별로 도구 출력(tool output)을 확장하고 범위를 제한하는 프라이버시 가드(privacy guard)**를 구축하는 것이었습니다. 이를 통해 각 필드가 통째로 전달되는 대신 개별적으로 제어되도록 했습니다. 여기서 얻은 인식의 전환은 다음과 같습니다. 도구의 _출력(outputs)_을 사용자 입력(user input)과 마찬가지로 신뢰할 수 없는 경계(untrusted boundary)로 취급해야 한다는 것입니다.

3. 대부분의 비엔지니어는 강력한 빌더(builder)를 보고 이탈한다

저는 모든 조절 노브(knob)가 노출된 풀 기능의 에이전트 빌더(agent builder)를 만들었습니다. 하지만 정작 대상이었던 비엔지니어들은 이를 위협적으로 느끼고 떠나버렸습니다.

기능을 대폭 축소한 기본값(stripped-down default) — 에이전트를 평이한 언어로 설명하고, 몇 가지 도구를 연결하며, 이를 나란히 미리 보기(preview) 하는 방식 — 을 출시한 것이 그 어떤 단일 기능보다 더 큰 채택(adoption)을 이끌어냈습니다. 파워 유저를 위한 빌더는 여전히 존재하지만, 더 이상 정문(front door) 역할을 하지는 않습니다.

교훈: 빌더 제품의 경우, 기본 인터페이스(default surface)는 설정(settings)의 문제가 아니라 제품 결정(product decision)의 문제입니다. 당신이 실제로 원하는 가장 기술 수준이 낮은 사용자에 맞춰 최적화하세요.

4. 플러그인 경계(plugin seams)가 게임의 전부다

omadia는 세상을 다음과 같이 나눕니다:

  • 채널(channels) — 에이전트가 대화하는 곳 (Teams, Telegram, 웹 채팅)
  • 통합(integrations) — 에이전트가 동작할 수 있는 대상 (Microsoft 365, Odoo, Confluence, …)
  • 기능 제공자(capability providers) — 메모리(memory), 임베딩(embeddings), 이미지 생성(image generation), 웹 검색(web search)
  • 레퍼런스 에이전트(reference agents) — 시작점으로 포크(fork)할 수 있는 에이전트

이러한 경계(boundaries)를 올바르게 설정하는 것이 시스템을 거대한 단일체(monolith)가 아닌 조합 가능한(composable) 구조로 만드는 핵심입니다. 초기에 이 경계를 _잘못 설정한 것_이 제가 겪은 가장 큰 재작업(rework)의 원인이었습니다. 10개의 플러그인이 서로 충돌하기 전에, 그 경계(seams)를 설정하는 데 시간을 투자하십시오.

솔직한 상태

omadia는 1.0 미만 / 퍼블릭 프리뷰(public preview) 단계입니다. 작동하며 실제 운영 환경(production)에서도 실행 중이지만, 마이너 버전 간에 DB 스키마(DB schemas)가 깨질 수 있으며 업그레이드 경로는 현재 수동으로 구현되어 있습니다. 이 시스템은 싱글 테넌트(single-tenant)이며 자체 호스팅(self-hostable)이 가능합니다. Docker Compose 또는 기타 도커 호스팅 환경에서 실행하고, 본인의 LLM API 키를 가져오며, 모든 데이터를 귀하의 측에 보관하십시오. 기술 스택은 TypeScript/Node + Next.js 빌더 UI입니다.

만약 에이전트 (Agents)를 구축하고 계신다면, 특히 여러 에이전트에 걸친 메모리 격리 (Memory isolation) 및 도구 수준의 데이터 스코핑 (Tool-level data scoping)에 대한 귀하의 의견을 진심으로 듣고 싶습니다. 저장소 및 문서: https://github.com/byte5ai/omadia

AI 자동 생성 콘텐츠

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

원문 바로가기
0

댓글

0