---
title: "Mycelium으로 복잡성 관리하기: AI 코딩 에이전트 시대의 소프트웨어 아키텍처"
published: 2026-02-25T23:51:52.000Z
canonical: https://jeff.news/article/184
---
# Mycelium으로 복잡성 관리하기: AI 코딩 에이전트 시대의 소프트웨어 아키텍처

LLM도 인간과 동일한 인지적 한계(context rot)를 겪기 때문에, 계층적이고 분리 가능한 컴포넌트 설계가 필수적임. Clojure 기반 Mycelium 프레임워크는 상태 머신으로 라우팅과 데이터 변환을 분리하고, Malli 스키마로 Cell 간 계약을 강제하여 AI 에이전트가 제한된 컨텍스트에서 안전하게 작업할 수 있게 함.

## 문제: 인간도, LLM도 같은 벽에 부딪힘

- 소프트웨어 아키텍처는 본질적으로 인간의 인지적 한계를 보완하기 위한 장치임
- LLM도 똑같은 문제를 겪음 - 함수 하나는 완벽하게 짜지만, 수천 개의 움직이는 부품이 있는 프로젝트에선 금방 맥을 못 추게 됨
- 이걸 "context rot"이라 부르는데, 결국 코딩 아키텍처 실패와 같은 문제임
- 공유 가변 상태(shared mutable state)에 LLM을 풀어놓으면 작동하는 솔루션이 나와도 그건 거의 우연에 가까움

## Herbert Simon의 시계공 우화

- 첫 번째 시계공: 시계 전체를 한 번에 조립함. 중간에 방해받으면 처음부터 다시 해야 함
- 두 번째 시계공: 작고 안정적인 모듈을 먼저 만들어서 조립함. 방해받아도 소량의 작업만 잃음
- 핵심 교훈 - 계층적 하위 조립체(hierarchical subassemblies)가 복잡성 관리의 열쇠임
- 각 하위 시스템은 독립적으로 진화 가능하고, 한 곳의 오작동이 전체를 무너뜨리지 않음

## 함수형 프로그래밍의 장점과 한계

- 순수 함수 + 불변 데이터로 전역 상태 문제를 효과적으로 길들일 수 있음
- 프로그램이 데이터 파이프라인처럼 작동 - 입력 데이터가 순수 함수 체인을 거쳐 출력으로 변환됨
- 불변 데이터는 숨겨진 상태나 부작용이 없어서 신뢰할 수 있는 계약이 됨
- **그런데 문제가 있음**: 데이터 변환 로직과 라우팅 로직이 여전히 뒤섞이게 됨
- 인증 핸들러 안에 "다음에 어떤 함수를 호출할지" 결정하는 코드가 섞여 들어가면서 커플링 발생

## 상태 머신으로 제어 역전하기

- 이벤트 버스는 라우팅 로직을 흩뿌려서 전체 흐름 추적이 불가능함
- 의존성 주입은 암묵적 콜백으로 흐름을 숨김
- 상태 머신은 라우팅을 선언적으로 만들어 한 곳에서 볼 수 있게 함
- "무엇을 할지"와 "어떻게 할지"를 강제로 분리시킴

## Mycelium 프레임워크

- Clojure 기반 프레임워크로, 프로그램을 워크플로우의 재귀적 생태계로 취급함
- Maestro 위에 구축됨 - 워크플로우를 그래프로 구조화하고, 노드는 상태 계산, 엣지는 전환을 표현
- **Cell**: 완전히 격리된 미니 애플리케이션. IO 리소스와 입력 상태 맵만 접근 가능
- 각 Cell은 엄격한 라이프사이클을 따름: 상태 맵 수신 → 데이터 로드 → 로직 실행 → 새 상태 출력
- **Malli 스키마**: Cell의 입출력 계약을 공식적으로 정의함. 입력으로 뭘 받고 출력으로 뭘 낼 수 있는지 정확히 명시

```clojure
{:id :auth/validate-session
 :schema {:input  [:map [:user-id :string] [:auth-token :string]]
          :output {:authorized   [:map [:session-valid :boolean] [:user-id :string]]
                   :unauthorized [:map [:session-valid :boolean] [:error-type :keyword]]}}}
```

- 라우팅은 별도의 `:edges`와 `:dispatches` 키로 완전히 분리됨
- 워크플로우 전체 결정 트리를 EDN 스펙만 보고 파악 가능

## AI 에이전트와의 시너지

- Conductor(전략 에이전트)가 EDN으로 워크플로우를 설계하고, 소규모 전문 에이전트들이 개별 Cell을 구현
- 에이전트가 Cell 작업 시 Malli 스키마가 경계를 명확히 정해줌 - 맵에 어떤 키가 있고, 타입이 뭔지 다 알려줌
- 에이전트가 계약을 위반하면 시스템이 즉시 거부하고 피드백을 제공하는 자기 교정 루프가 작동
- 인간이 지루해하는 보일러플레이트와 ceremony를 LLM은 오히려 좋아함 - 명시적이고 모호하지 않은 지도 역할을 하기 때문

## 테스트가 놀라울 정도로 쉬워짐

- 각 Cell이 순수 데이터 변환이라 mock 없이 테스트 가능
- "User Not Found" 시나리오 테스트? DB를 mock할 필요 없이 `:user` 키가 없는 상태 맵을 넣어주면 끝
- `:mycelium/trace`로 모든 전환 이력이 기록되어, 실패 시 블랙박스 기록처럼 전체 히스토리를 확인 가능
- 리소스(DB 등)는 외부에서 주입되므로 테스트에서 Postgres를 mock으로 교체하는 게 워크플로우에 전혀 영향 없음

## 재귀적 확장: 무한 스케일

- Cell 네트워크 전체가 다시 하나의 Cell이 될 수 있음 - 자연스러운 재귀 구조
- 로그인 처리 네트워크 → 결제 프로세스의 컴포넌트 → 전체 온라인 상점의 컴포넌트로 계층화 가능
- 스케일링이 코드베이스 내 커플링 증가가 아니라 그래프 위에 컴포넌트를 배치하는 문제가 됨
- 그래프가 너무 복잡해지면 독립적인 서브그래프로 다시 분할 가능 - 컨텍스트가 감당 불가능하게 커질 필요가 없음

## 핵심 포인트

- LLM의 context rot은 소프트웨어 아키텍처 실패와 동일한 문제
- 상태 머신으로 라우팅 로직을 선언적으로 분리하면 커플링 해소
- Mycelium의 Cell은 Malli 스키마로 입출력 계약이 강제되는 격리된 미니 앱
- AI 에이전트는 인간이 지루해하는 ceremony와 구조화를 오히려 잘 활용함
- Cell 네트워크가 다시 Cell이 되는 재귀 구조로 무한 확장 가능

## 인사이트

AI 에이전트 시대에 '좋은 아키텍처'의 정의가 바뀌고 있음. 인간에겐 과도한 ceremony였던 것이 LLM에겐 명확한 작업 경계가 됨. 구조적 엄격함이 곧 AI 친화적 설계.
