온톨로지와 메모리 시스템 (2/13) — 멀티 에이전트 온톨로지 실전 구현
다수의 에이전트가 실제로 협업하는 구조를 만드는 법
핵심 요약
- 에이전트 간 통신에는 가벼운 인사이트 전달과 확인이 필요한 작업 요청, 두 경로가 필요하다
- 컨텍스트 격리(1 에이전트 = 1 역할 = 최소 컨텍스트)가 시스템 품질을 유지하는 열쇠
- 글로벌 CLAUDE.md → 프로젝트 CLAUDE.md → 세션 메모리, 3계층 구조로 지식을 관리한다
배경
1편에서 온톨로지의 개념과 필요성을 다뤘습니다. 에이전트 간 관계를 정의하는 것이 왜 중요한지, CLAUDE.md와 메모리가 어떤 역할을 하는지.
이번 2편에서는 실제 구현을 다룹니다. 에이전트끼리 어떻게 데이터를 주고받는지, 왜 컨텍스트를 격리해야 하는지, 메모리를 어떻게 계층화하는지.
본문
1. 메시지 허브 — 에이전트 간 통신 설계
온톨로지에 관계를 정의했으면, 실제로 데이터가 오갈 통로가 필요합니다.
에이전트 간 통신은 두 가지로 나뉩니다. 성격이 완전히 다릅니다.
① 인사이트 전달 (fire-and-forget)
POST /api/webhooks
{"content": "...", "tags": ["분석"], "source": "에이전트명"}
"이런 발견이 있었다" 수준의 가벼운 알림입니다. 보내고 끝. 상대방이 받았는지, 처리했는지 확인하지 않습니다.
사용 예시: - 오픈클로 에이전트가 분석 인사이트를 대시보드에 전달 - 주식 에이전트가 시그널 변동을 로그로 기록
② 작업 요청 (ACK 필요)
POST /api/agent-messages
{
"fromAgent": "홈서버 관리자",
"toAgent": "글 작성 디렉터",
"messageType": "task_request",
"intent": "blog_material",
"body": {"text": "이 소재로 블로그 글 작성해주세요"}
}
확인 응답(ACK)이 필요한 요청입니다. 재시도, 스레드 추적, 상태 관리가 됩니다.
수신 에이전트는 받은 메시지를 확인하고 응답합니다:
POST /api/agent-messages/{messageId}/ack
{"status": "acked", "response": {"text": "수신 완료, 작성 시작"}}
이 두 경로를 나누는 이유는 명확합니다. 모든 통신에 ACK를 요구하면 시스템이 느려지고, 모든 통신을 fire-and-forget으로 하면 중요한 작업이 빠집니다. 정보 알림은 가볍게, 작업 요청은 확실하게.
실제 사례: 홈서버 관리자가 글 작성 디렉터에게 블로그 소재를 task_request로 전달하면, 글 작성 디렉터가 ACK 후 작업을 시작합니다. 사람이 중계하지 않아도 에이전트끼리 일을 넘기는 구조입니다.
2. 컨텍스트 격리 — 왜 에이전트를 나누는가
"하나의 강력한 에이전트에 모든 역할을 넣으면 안 되나?"
실제로 해봤습니다. 안 됩니다. 이유는 세 가지입니다.
① 컨텍스트 오염
주식 분석 맥락과 Flutter UI 코드가 같은 대화에 있으면, AI가 맥락을 혼동합니다. "이 함수의 리턴값을 분석해줘"라고 했을 때, 주식 데이터 분석인지 코드 분석인지 모호해지는 상황이 실제로 발생합니다.
② CLAUDE.md 충돌
여러 프로젝트의 규칙을 하나의 CLAUDE.md에 넣으면, 지시가 서로 모순됩니다. "간결하게 써라" (콘텐츠)와 "모든 엣지케이스를 명시해라" (코드)가 공존할 수 없습니다.
③ 프롬프트 길이와 성능 저하
AI는 프롬프트가 길어질수록 앞부분 지침을 덜 따르는 경향이 있습니다. 필요 없는 맥락을 줄이는 것 자체가 성능 최적화입니다.
격리 원칙: - 1 에이전트 = 1 역할 = 최소 컨텍스트 - 서브 에이전트에게 작업을 넘길 때, 전체 세션 히스토리를 전달하지 않음 - 에이전트가 알아야 할 것만 전달하고, 나머지는 격리
이 원칙이 에이전트 수가 늘어나도 품질이 유지되는 비결입니다.
3. 메모리 3계층 구조
지식을 어디에, 어떤 수준으로 저장할지가 중요합니다. 3계층으로 나눠 관리합니다.
Layer 1: 글로벌 CLAUDE.md — 모든 에이전트가 아는 것
~/.claude/CLAUDE.md (심링크로 전 에이전트 공유)
여기에 들어가는 것: - 전체 에이전트 목록과 관계 (온톨로지) - 사용자의 판단 기준과 가치관 - 에이전트 간 통신 규약 - 크로스 프로젝트 규칙
모든 에이전트가 세션 시작 시 읽으므로, 여기 있는 정보는 시스템 전체에 공유됩니다.
Layer 2: 프로젝트 CLAUDE.md — 이 에이전트만 아는 것
{프로젝트 루트}/CLAUDE.md
여기에 들어가는 것: - 프로젝트 목적과 구조 - 해당 프로젝트만의 규칙과 워크플로우 - 스킬 트리거, 에이전트 역할 분리 - 기술 스택, API 설정
프로젝트 고유 지식이 다른 에이전트를 오염시키지 않도록 격리합니다.
Layer 3: 세션 메모리 — 대화에서 축적되는 것
{프로젝트}/.claude/projects/{id}/memory/
여기에 들어가는 것: - 사용자 피드백 ("이렇게 하지 마", "이건 좋았어") - 프로젝트 상태 변화 - 작업 중 학습한 패턴
세션을 넘어 유지되며, 해당 프로젝트의 에이전트가 점점 더 사용자에게 맞춰갑니다.
계층 간 흐름:
세션에서 반복되는 피드백
→ 프로젝트 CLAUDE.md에 규칙으로 승격
→ 여러 프로젝트에 공통이면 글로벌 CLAUDE.md로 승격
아래에서 위로 올라가는 구조입니다. 한 에이전트에서 검증된 원칙이 전체 시스템으로 퍼져나갑니다.
4. 온톨로지 관리 실전 팁
운영하면서 정리된 팁들입니다.
① 관계 테이블을 CLAUDE.md에 유지한다
## Relationships
- 오픈클로 → 홈서버: 인사이트 → 대시보드 표시 [data]
- 콰이어트 ↔ 성장 일지: Flutter 패턴 공유 [tech]
- 나의 삶 정리 → 글 작성 디렉터: 경험 → 콘텐츠 소재 [content]
태그([data], [tech], [content])로 관계 유형을 표시합니다. 한눈에 파악됩니다.
② 새 에이전트 추가 시 체크리스트
- 온톨로지에 역할 추가
- 기존 에이전트와의 관계 정의 (최소 1개)
- 관계가 없으면 → 정말 필요한 에이전트인지 재검토
- 글로벌 CLAUDE.md 업데이트
③ 주기적으로 관계를 검증한다
정의된 관계가 실제로 작동하고 있는지 확인합니다. 온톨로지에는 "A → B 데이터 전달"이라고 적혀있는데, 실제로는 한 번도 전달된 적 없다면 그 관계는 삭제하거나 구현해야 합니다.
④ 글로벌 CLAUDE.md는 간결하게 유지한다
온톨로지 정보, 사용자 성향, 통신 규약 정도만. 상세 구현은 프로젝트 CLAUDE.md에. AI가 매 세션 읽는 파일이므로, 짧을수록 잘 따릅니다.
주의사항 및 설계 고려사항
-
메시지 허브 없이 시작해도 됩니다. 초기에는 사람이 중계해도 충분합니다. "이 에이전트 결과를 저 에이전트에 넣어줘" 하는 식으로. 빈도가 잦아지면 그때 자동화합니다.
-
격리와 공유의 균형이 중요합니다. 너무 격리하면 에이전트가 섬이 되고, 너무 공유하면 컨텍스트가 오염됩니다. 공유는 글로벌 CLAUDE.md로, 격리는 프로젝트 CLAUDE.md로. 이 경계를 의식적으로 관리해야 합니다.
-
온톨로지는 살아있는 문서입니다. 에이전트가 추가/삭제되고, 관계가 바뀌고, 역할이 변합니다. 한 번 만들고 끝이 아니라 계속 업데이트해야 합니다.
-
에이전트 교체는 단계적으로. 안정적으로 운영 중인 에이전트를 교체할 때는 병행 운영(Strangler Fig 패턴)으로 검증 단계를 거쳐야 합니다. 새 에이전트가 토큰 폭주나 예상치 못한 동작을 보이면, 즉시 원래 에이전트로 회귀할 수 있는 구조가 필요합니다.
마무리
에이전트 하나는 도구입니다. 에이전트가 많아지고 온톨로지가 없으면 혼란입니다. 에이전트가 많아지고 온톨로지가 있으면 시스템입니다.
차이를 만드는 건 에이전트 수가 아니라, 관계 설계와 지식 계층화입니다. CLAUDE.md를 공유하고, 메시지 허브로 통신하고, 컨텍스트를 격리하고, 메모리를 계층화하면 — 에이전트가 늘어나도 품질이 유지되는 구조가 만들어집니다.
에이전트를 하나씩 늘려가고 있다면, 지금이 온톨로지를 정리할 타이밍입니다.
시리즈 전체 안내: 시리즈 목차
댓글
댓글 쓰기