한계가 설계를 만든다 — 1인 AI 미디어 회사 빌드로그
나는 1인 AI 미디어 회사를 혼자 운영하는 개발자다. 이 글이 증명하려는 건 내가 멋진 아키텍처를 그렸다는 게 아니라, 도구가 그어 놓은 단 하나의 선을 만났을 때 그것을 우회하거나 한탄하지 않고 설계의 제1원리로 받아들였다는 사실이다. 한계가 설계를 규정하고, 그 설계가 다시 한계에 부딪혀 정련되는 사슬 — 이 글은 그 사슬을 처음부터 끝까지 따라간 기록이다.
콘텐츠를 수집하고, 다시 쓰고, 검수하고, 발행하는 일은 여러 AI 에이전트가 나눠 맡는다. 그 에이전트들을 어떻게 연결하느냐가 이 회사의 아키텍처 전부였고, 그 연결 방식은 처음 그렸던 그림에서 세 번 모양을 바꿨다. 그리고 그 세 번의 변형은 전부 내가 똑똑해서가 아니라, 하나의 제약이 시켜서 일어났다.
머릿속에서 무너진 다층 설계
처음 그림은 단순하고 우아했다. 글을 쓰는 작가 에이전트가 초안을 뽑고, 그 작가가 직접 어드바이저 에이전트를 불러 피드백을 받고, 받은 피드백으로 스스로 고친다. 사람이 팀을 운영하듯 에이전트가 에이전트를 호출하는 다층 구조. 머릿속에서는 완벽하게 돌아갔다.
실측해 보니 그 구조는 성립하지 않았다. 하나의 서브에이전트 안에서 다시 다른 에이전트를 호출하는 일이 구조적으로 막혀 있었다. 이건 내 코드의 버그가 아니라 도구 자체의 알려진 제약이었다. 작가가 어드바이저를 부르는 그 한 줄이 처음부터 불가능했던 것이다. 머릿속 다층 설계가 한순간에 바닥으로 내려앉았다.
여기서 갈림길이 생긴다. 제약을 만났을 때 할 수 있는 선택은 둘이다. 한탄하며 우회 트릭을 찾거나, 아니면 그 제약을 설계의 출발점으로 다시 세우거나. 나는 후자를 택했다. 그리고 이 선택이 이후 모든 파이프라인 아키텍처의 진짜 출발점이 됐다.
1단계 — 평면으로 펼치다 (세션 체이닝)
호출을 중첩할 수 없다면, 발상을 뒤집으면 된다. 위에서 아래로 부르는 수직 구조 대신, 옆으로 한 명씩 이어 붙이는 수평 구조로.
나는 에이전트들을 비대화형으로 한 명씩 따로 불렀다. 작가를 불러 초안을 받아 파일로 떨군다. 그 파일을 들고 어드바이저를 따로 불러 피드백을 받는다. 그 피드백을 다시 작가에게 넘긴다 — 이 모든 호출을 셸 스크립트 하나가 순서대로 이어 붙였다. 에이전트가 에이전트를 부르는 게 아니라, 바깥의 스크립트가 에이전트들을 차례로 부르는 구조. 다층 호출이 평면적 연쇄로 펼쳐진 셈이다.
핵심은 이것이다. 나는 잃어버린 다층 구조를 흉내 내려고 애쓰지 않았다. 제약이 “수직은 안 된다”고 말했으니, 설계를 수평으로 눕혔다. 한계의 모양을 보고 그 모양에 설계를 맞춘 첫 번째 사례다.
2단계 — 우회를 표준으로 (순수 스크립트)
우회책으로 시작한 세션 체이닝이 실제로 잘 돌자, 나는 그것을 임시방편이 아니라 정식 아키텍처로 승격시키기로 했다.
이 단계의 결정적 변화는 “팀장 역할을 하던 오케스트레이터 에이전트를 아예 없앤” 것이다. 처음엔 한 에이전트가 다른 에이전트들을 지휘하는 그림이 남아 있었는데, 어차피 그 지휘 자체가 제약에 걸리니 지휘자를 제거하고 그 역할을 순수한 스크립트에 넘겼다. 흐름을 통제하는 건 더 이상 똑똑한 에이전트가 아니라, 예측 가능하고 디버깅 가능한 셸 코드였다.
동시에 산출물을 정돈했다. 한 건의 작업에서 나오는 초안·피드백·수정본·검수 결과를 작업 단위 폴더 하나로 묶었다. 흩어진 파일을 쫓아다닐 일이 사라졌다. 제작 라인뿐 아니라 발행 라인까지 같은 원리로 다시 정렬했다 — 사람이나 에이전트의 판단이 흐름을 쥐는 대신, 스크립트가 흐름을 쥐고 에이전트는 각자 한 칸의 일만 하는 구조.
세션 체이닝이 “중첩이 안 되니 펼친다”였다면, 이 단계는 “펼친 걸 표준으로 굳힌다”였다. 같은 제약이 시킨 두 번째 변형이다.
제약이 공식이 되던 날
여기까지가 우회와 정착이었다면, 다음은 제약이 내 머릿속 미련까지 끊어 낸 순간이다.
한동안 나는 “언젠가 중첩이 풀리면 다층 모델로 돌아가야지” 하는 미련을 품고 있었다. 그런데 이후 “서브에이전트는 한 단계까지만”이라는 게 제약으로 굳어진 사실임이 분명해졌다. 내가 한때 그렸던 다층 모델은 임시로 막힌 게 아니라 영구히 닫힌 길이었다. 미련을 접었다.
미련을 접고 나니 오히려 시야가 트였다. 제약을 영구 조건으로 받아들이자, 질문이 “어떻게 다층을 흉내 낼까”에서 “이 평면 구조의 본질이 무엇이어야 하나”로 바뀌었다. 그 답은 자동화였다. 사람이 매번 버튼을 눌러 한 단계씩 진행시키는 모델 전부를 의심하기 시작했고, 일감을 큐에 쌓아 두고 직렬로 흘려보내는 모델로 사상이 옮겨 갔다. 제약 하나가 아키텍처를 넘어 운영 철학까지 밀고 간 것이다.
3단계 — 한계의 모양에 설계를 맞추다 (다이나믹 워크플로우)
그리고 결정적 진전이 왔다. 이 글에서 가장 중요한 단계다.
수직 중첩은 여전히 막혀 있다. 그건 변하지 않았다. 그런데 나는 다른 길을 실증했다. 하나의 워크플로우 안에서, 여러 서브에이전트가 같은 세션 안에 차례로 등장(spawn)해 직렬로 도는 것을 입증한 것이다.
이게 왜 진전인지 또렷이 짚고 넘어가자. 세 단계를 나란히 세우면 이렇다.
- 세션 체이닝: 바깥 스크립트가 매번 에이전트를 따로 불러 잇는다. 에이전트들은 서로 다른 세션에 흩어져 있고, 스크립트가 접착제다.
- 순수 스크립트: 그 연쇄를 표준으로 굳히고 지휘자를 제거한다. 여전히 호출은 바깥에서 하나씩.
- 다이나믹 워크플로우: 하나의 세션 안에서 여러 에이전트가 줄지어 spawn되어 직렬로 흐른다. 바깥에서 매번 새로 부르는 게 아니라, 한 흐름 안에서 차례가 넘어간다.
비유하자면, 세션 체이닝은 작업자를 한 명씩 불러다 일을 시키고 돌려보내기를 반복하는 것이고, 다이나믹 워크플로우는 한 작업장 안에 작업자들이 줄지어 서서 앞사람이 끝내면 뒷사람이 받는 컨베이어다. 중첩(한 사람이 다른 사람을 데려와 일을 시키는 것)은 끝까지 금지지만, ‘한 세션·직렬 진행’이라는 제약의 모양에 맞는 형태로 다층의 효과를 얻었다.
이게 핵심이다. 나는 한계를 우회한 게 아니다. 한계의 모양을 정밀하게 들여다보고, 그 모양에 정확히 들어맞는 설계를 만든 것이다. 우회는 한계를 피해 도망가는 것이고, 이건 한계를 입력값으로 받아 설계를 출력한 것이다.
그리고 그 형태도 한계에 부딪혔다
여기서 끝났다면 깔끔한 성공담이겠지만, 진짜 이야기는 그다음에 있다. 이 부분을 빼면 이 글은 정직하지 않다.
워크플로우가 여러 개로 늘자 자연스러운 욕심이 생겼다. 워크플로우마다 비슷한 로직이 반복되니, 공통 부분을 빼내 엔진 + 설정 + 프롬프트 세 계층으로 일반화하자는 것이었다. 잘 만든 번들러처럼, 공통 엔진 하나에 워크플로우별 설정과 프롬프트만 갈아 끼우는 구조. 정적으로 비교해 보면 분리 전과 분리 후가 완벽하게 동등했다. 출력도, 구성도, 로직도 한 글자까지 같았다. 나는 잘 짠 일반화라고 확신했다.
그런데 막상 돌려 보니, 런타임이 그 분리 구조를 받아 주지 않았다. 워크플로우 실행기는 자기완결형 정의만 인식했다. 엔진과 설정이 따로 떨어진 구조는, 종이 위에서 아무리 동등해도 실제로 돌릴 때는 흐르지 않았다. 정적 동등이 라이브 호환을 보장하지 않았던 것이다.
나는 잘 만든 번들러를 접었다. 일반화를 되돌려 다시 자기완결형 단일 형태로 합쳤다. 다만 만들었던 분리 구조를 지우지는 않았다 — 개념이 가능함을 보여 주는 PoC로 보존하고, 그 위에 “이 길은 런타임이 안 받는다”는 결론을 얹었다. 그렇게 자기룰 하나가 더 섰다. 정적으로 동등하다고 라이브에서 호환되는 게 아니다.
이 선회를 부끄러워하지 않는다. 오히려 반대다. 잘못 든 설계를 빨리 알아채고 되돌린 속도가, 잘 든 설계를 그린 것보다 더 중요한 능력이라고 생각한다. 설계 미스는 누구나 한다. 차이는 그걸 며칠 안에 인정하고 접느냐, 아니면 매몰비용에 끌려 우기느냐에서 난다.
그래서 지금
처음의 그 한 줄 — 작가가 어드바이저를 부르는 불가능한 한 줄 — 로 돌아가 보면, 그 좌절이 사실은 이 회사 아키텍처 전체의 설계도였다. 중첩 불가가 세션 체이닝을 낳고, 세션 체이닝이 순수 스크립트로 굳고, 그 위에서 자동화 사상이 서고, 다이나믹 워크플로우가 한계의 모양에 설계를 맞추고, 그 워크플로우의 일반화 시도가 다시 런타임 한계에 부딪혀 정련됐다. 매 단계가 앞 단계의 한계를 입력값으로 받아 다음 형태를 출력했다.
나에게 도구의 제약은 막다른 벽이 아니라 설계 명세서의 첫 줄이다. “여기까지는 된다, 여기부터는 안 된다”는 경계선이 또렷할수록, 그 위에 세울 수 있는 구조는 오히려 더 단단해진다. 다음 도구가 또 다른 선을 그어 오면, 나는 그 선을 한탄하는 대신 다시 설계도의 첫 줄에 받아 적을 것이다. 한계가 설계를 만든다 — 이 회사가 지금까지 자라 온 방식이고, 앞으로 자랄 방식이다.