안녕하세요! 최근 오픈소스 AI 및 에이전트 생태계가 급격히 확장되면서, 단일 LLM을 넘어 여러 에이전트가 협력하는 ‘멀티 에이전트 시스템’에 대한 관심이 뜨겁습니다. 이전 포스트에서 ZeroClaw 프로젝트의 아키텍처 설계를 다루었는데요, 이번에는 실제 ZeroClaw 런타임이 내부적으로 어떻게 에이전트 간의 통신을 처리하고, Rust의 강력한 비동기 런타임을 활용해 고성능을 달성하는지 그 구체적인 구현 방법을 소개하고자 합니다.
기존 통신의 문제점과 ZeroClaw의 접근
일반적인 MCP(Model Context Protocol)나 기초적인 에이전트 시스템은 주로 단일 프로세스 내의 메모리 공유나 간단한 로컬 함수 호출로 통신을 처리합니다. 하지만 시스템이 복잡해지고 에이전트가 분산되면서 다음과 같은 문제가 발생합니다.
- 확장성의 한계: 단일 프로세스 메모리 버퍼는 한정되어 있으며, 수백 개의 에이전트가 동시에 메시지를 주고받을 때 병목이 발생합니다.
- 결합도(Coupling) 증가: 에이전트 간의 통신이 로직에 강하게 결합되어, 특정 에이전트를 교체하거나 업데이트하기 어렵습니다.
- 네트워크 분리: 로컬 개발 환경과 클라우드 배포 환경 간의 통신 방식이 달라지면 코드를 수정해야 하는 불편함이 있습니다.
ZeroClaw는 이를 해결하기 위해 **‘파일 기반 아키텍처 설계’**와 **‘TCP/IP 네트워킹 계층’**을 결합한 하이브리드 방식을 채택했습니다. 에이전트는 자신의 상태를 파일 시스템에 선언적으로(Declarative) 기록하며, 실제 메시지 전송은 비동기 TCP 소켓을 통해 처리합니다.
Rust Tokio를 활용한 비동기 서버 구조
ZeroClaw의 핵심은 Rust의 tokio 런타임 위에서 구축된 고성능 네트워크 계층입니다. 각 에이전트는 독립적인 태스크(Task)로 실행되며, 채널(Channel)을 통해 안전하게 메시지를 교환합니다.
다음은 ZeroClaw 런타임의 핵심인 메시지 브로커(Message Broker)의 간소화된 구현 예제입니다.
1. 기본 메시지 구조 정의
먼저, 에이전트 간 주고받을 데이터 구조를 정의합니다. serde를 사용하여 직렬화를 자동화합니다.
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AgentMessage {
pub source: String, // 송신 에이전트 ID
pub target: String, // 수신 에이전트 ID (혹은 "broadcast")
pub payload: PayloadType,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum PayloadType {
Text(String),
Data(HashMap<String, String>), // 유연한 데이터 전달을 위한 Map
Control(ControlSignal),
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum ControlSignal {
Start,
Stop,
HeartBeat,
}
2. 비동기 TCP 핸들러 구현
실제 통신은 tokio::net::TcpListener를 통해 이루어집니다. 각 연결은 별도의 태스크로 분리되어 처리되므로, 특정 에이전트의 느린 응답이 전체 시스템을 멈추게 하지 않습니다.
use tokio::net::{TcpListener, TcpStream};
use tokio::io::{AsyncReadExt, AsyncWriteExt};
use tokio::sync::mpsc;
#[derive(Clone)]
struct AgentConfig {
id: String,
}
pub async fn run_agent_server(config: AgentConfig) -> Result<(), Box<dyn std::error::Error>> {
let listener = TcpListener::bind("127.0.0.1:8080").await?;
println!("[{}] Agent Server listening on 127.0.0.1:8080", config.id);
// 메시지 라우팅을 위한 채널 (실제 구현에서는 더 복잡한 라우터 사용)
let (tx, mut rx) = mpsc::channel::<AgentMessage>(1000);
// 수신 태스크 (스폰)
let config_clone = config.clone();
tokio::spawn(async move {
while let Ok((mut socket, addr)) = listener.accept().await {
println!("[{}] Connection from {}", config_clone.id, addr);
let tx_clone = tx.clone();
tokio::spawn(async move {
let mut buf = [0; 1024];
loop {
let n = match socket.read(&mut buf).await {
Ok(n) if n == 0 => return, // 연결 종료
Ok(n) => n,
Err(e) => {
eprintln!("Failed to read from socket; err = {:?}", e);
return;
}
};
// 메시지 파싱 (간소화된 로직)
let received_data = &buf[..n];
// 실제로는 여기서 역직렬화 수행
println!("Received: {:?}", String::from_utf8_lossy(received_data));
// ... (비즈니스 로직 처리) ...
}
});
}
});
// 송신 태스크 예시 (주기적 하트비트)
tokio::spawn(async move {
let mut interval = tokio::time::interval(tokio::time::Duration::from_secs(5));
loop {
interval.tick().await {
let hb = AgentMessage {
source: config.id.clone(),
target: "broadcast".to_string(),
payload: PayloadType::Control(ControlSignal::HeartBeat),
};
// 실제로는 소켓에 쓰거나 외부로 전송
println!("[{}] Sending Heartbeat...", config.id);
}
}
});
Ok(())
}
이 코드는 ZeroClaw 에이전트가 다른 에이전트의 요청을 비동기적으로 수신하고, 자신의 상태를 주기적으로 보고하는 기본 뼈대를 보여줍니다. tokio::spawn을 통해 각 연결이 독립적으로 실행되므로, 수천 개의 동시 연결도 효율적으로 처리할 수 있습니다.
팀 에이전트 통신과 프로토콜 설계
단순한 1:1 통신을 넘어, ZeroClaw는 팀(Team) 단위의 통신을 지향합니다. 이는 이전에 논의된 ‘팀 에이전트 통신 아키텍처’와 연결됩니다.
- Pub/Sub 패턴: 특정 주제(Topic)를 구독한 에이전트 그룹에게 메시지를 일괄 전달합니다.
- 피어 투 피어 (P2P): 중앙 서버를 거치지 않고 에이전트 간 직접 통신하여 대기 시간(Latency)을 최소화합니다.
ZeroClaw의 프로토콜은 TCP 계층 위에서 JSON 또는 바이너리 포맷(성능이 중요할 경우 MessagePack 등)으로 캡슐화되어 전송됩니다. 이를 통해 네트워크 추상화 계층(Network Abstraction Layer)을 형성하여, 상위 비즈니스 로직은 통신이 로컬인지 원격인지 신경 쓰지 않고 로직을 작성할 수 있습니다.
결론: 확장 가능한 에이전트 시스템을 향하여
ZeroClaw는 단순한 LLM 래퍼(Wrapper)를 넘어, 진정한 분산 시스템으로 설계되고 있습니다. Rust의 메모리 안전성과 Zero-cost 추상화, 그리고 tokio의 강력한 비동기 처리 능력을 결합하여, 안정적이고 빠른 에이전트 런타임을 구축하고 있습니다.
다음 포스트에서는 이러한 통신 아키텍처 위에서 LLM이 어떻게 자신의 의사를 결정(Decision)하고, MCP 도구를 통해 실제 행동을 수행하는지 그 플로우를 디버깅해보겠습니다.
참고 코드 및 리소스
- ZeroClaw GitHub Repository (오픈소스 준비 중)
- The Garbage Collection Handbook: The Art of Automatic Memory Management (2nd Ed) - 최근 뉴스에서 언급되었던 메모리 관리의 고전이자 바이블입니다.
읽어주셔서 감사합니다!