1편은 빠져든 이야기, 2편은 만든 것들이 부서진 이야기였습니다. 이번 편이 마지막입니다. 부서진 것들을 치우면서 저는 처음의 질문으로 돌아갔고, 그 끝에서 유니콘을 만났습니다.

일단 줄였다

제일 먼저 한 일은 다이어트였습니다. 하네스를 줄이고, 서브에이전트 수를 줄이고, 흩어진 책임과 업무를 합쳤습니다. 모델의 능력을 최대한 발휘하게 하는 방향으로 모넷과 하네스를 다시 잡았습니다. 그리고 그때 비로소, 메모리가 왜 필요한지를 다시 고민하기 시작했습니다.

보통 에이전트 메모리라고 하면 잘 저장하고 잘 읽어오면 되는 것 아닌가 생각합니다. 저도 그랬습니다. 근데 잘 읽어와서, 어떻게 쓰이기를 원하는 걸까요. 질문을 바꾸니 더 기본적인 질문이 나왔습니다. 사람들은 코딩 에이전트를 왜 쓸까. 무엇을 원하고, 어떨 때 만족할까.

제가 도달한 답은 이겁니다. 그 팀이, 그 사용자가 원하는 결과물. 똑같이 “사과를 그려줘"라고 시켜도 받는 사람마다 기대하는 그림이 다릅니다. 원하는 결과물을 만들어내려면 모델이 그 사람이 원하는 것을 알아야 합니다. 방법은 의외로 간단합니다. 원하는 사과 그림을 정확히 설명하거나, 그 사과를 그리는 과정을 설명하거나. 단, 내가 그걸 알고 있다면 말입니다.

사과 그림을 코딩으로 그리기

저는 그림을 하나도 모릅니다. 그래도 멋진 사과 그림을 에이전트의 도움으로 그리고 싶습니다. 어떻게 할까요. 일단 요청합니다. “멋진 사과 그림 그려줘.” 그림을 받고, 뭐가 마음에 안 드는지, 어떤 느낌이면 좋겠는지 취향을 말해줍니다. 에이전트가 다시 그립니다. 마음에 들 때까지 반복합니다. 이게 지금 에이전트들이 일하는 방식입니다. 모델은 훈련받은 것을 기준으로 확률로 움직이고, 에이전트는 턴을 돌면서 나온 결과물과 기대 사이의 갭을 줄여갑니다.

코딩도 비슷합니다. 지시에 따라 계획을 세우고, 스펙을 만들고, 코딩과 테스트를 만들고, 스펙대로 됐는지 테스트가 통과하는지 빌드에 문제가 없는지 확인하는 사이클을 돕니다. 이 과정에서 원하는 결과물을 받으려면 원하는 것을 설명해줘야 합니다. 처음부터 빠짐없이 다 알고 있다면 첫 프롬프트에 주면 됩니다. 실제로 그런 시대가 있었습니다. 누군가 만들어놓은 ‘완벽하다는’ 프롬프트를 복사해서 쓰고, 내 취향에 맞게 개조해가며 쓰던 프롬프트 엔지니어링의 시대. 그 시대는 지나갔다고 생각합니다. 두 가지가 사실상 불가능하기 때문입니다. ‘다 알고 있다면’과 ‘빠짐없이’. 시키는 일은 매번 달라지고 복잡해지는데 완벽한 첫 프롬프트는 없고, 어긋난 결과물을 받았을 때의 손실은 너무 큽니다.

남는 방법은 과정에 개입하는 겁니다. 아키텍처를 잡을 때는 이렇게, 코딩할 때는 이렇게, 테스트는 이렇게. 어디서 많이 들어본 것들입니다. CLAUDE.md나 AGENTS.md의 단골 주제들이니까요. 그럼 문제가 해결된 걸까요. 뭔가 친숙합니다. 바로 Stig의 그 무거운 프롬프트입니다.

엄마, 지금은 때가 아닌가 봐

뜬금없이 웬 때인가 싶겠지만, 그 때가 중요합니다. 내가 원하는 것은 에이전트가 그 작업을 하는 순간에 주입돼야 합니다. 아키텍처를 고민할 때 어떤 방법을 선호하는지, 기존 아키텍처는 어떻게 생겼는지. 그때 없으면 사실상 답이 없습니다.

근데 그것보다 어려운 문제가 있습니다. 나와 팀이 원하는 것을 어떻게 쉽게 모으고 관리할까. 어떤 상황, 어떤 때에 주입할까. 어떻게 주입할까. 모으는 건 기존 것을 기본으로 두고 새로 발견되는 것들을 계속 추가하며 관리해야 합니다. 제가 생각하는 에이전트 메모리의 중요 업무 중 하나입니다. 주입은 두 가지입니다. 필요한 곳에서 발동되는 훅으로 밀어 넣거나, 에이전트가 상황을 봐가며 읽어오게 하거나. 저는 후자를 스테이지라고 이름 붙였습니다. 세션이 시작될 때 어떤 스테이지들이 있는지 알려주고, 그 스테이지가 오면 규칙을 읽어 적용하게 하는 겁니다.

그럼 어떤 때가 아니라 항상 적용돼야 하는 것은요. 그건 원칙이라고 이름 붙였고, 거의 유일하게 CLAUDE.md에 들어갈 자격이 있는 내용입니다. 그리고 CLAUDE.md는 철저하게 관리돼야 합니다. 컨텍스트 절약 차원이 아닙니다. 모델은 정해진 바운더리로 훈련되지만 늘 그 안에서 움직인다는 보장이 없습니다. 그래서 모델을 제한해야 하는 상황이 계속 생기고, 그 제한들은 아주 쉽게 CLAUDE.md로 향합니다. CLAUDE.md는 갈 곳 없는 것들이 채워지기만 하고, 좀처럼 비워지지 않는 곳입니다.

다 된 줄 알았다

기분이 좋았습니다. 다 찾은 줄 알았습니다. 그렇게 저만의 원칙과 규칙을 세워갔습니다. 얼마 뒤 몇 안 되는 원칙과 규칙이 자리를 잡았고, 필요할 때 주입되거나 불려오는 것까지 확인했습니다.

근데 행동이 달라지지 않습니다. 결과물도 바뀌지 않습니다. 예를 하나만 들겠습니다. 코딩이 끝나면 코덱스에게 PR 리뷰를 받아라, 받은 리뷰는 이렇게 처리하라. 규칙으로 만들어 뒀고, 코덱스 리뷰 진행을 지켜보는 모니터링 스크립트까지 있습니다. 그런데 몇 주가 지나도록, 이 절차를 처음부터 제대로 해낸 세션이 단 한 번도 없었습니다. 분명히 주입됐고, 보냈고, 읽혔습니다. 근데 안 바뀝니다. 에이전트를 향한 신뢰가 도리어 떨어져 갔고, 모델이 더 똑똑해질수록 이 경향은 더 강해질 겁니다.

인정하게 된 것이 있습니다. 애초부터 ‘내가 원하는 방식’과 ‘내가 원하는 완벽한 결과물’은 존재하지 않습니다. 존재하는 건 모델이 학습된 방식, 그리고 모델이 인풋을 따르는 방식뿐입니다. 그 방식은 새 모델, 새 버전이 나올 때마다 달라질 겁니다. 저는 완벽한 제품이 존재할 수 없는 곳에서, 제품으로 가능하지 않은 것을 그려왔던 겁니다.

유니콘

처음 Antigravity로 바이브 코딩을 접했을 때, 이제 만드는 것의 문턱은 사라졌다고 믿었습니다. 그래서 어떻게 만들지보다 무엇을 만들어야 할지를 고민했고, 쉬지 않고 에이전트 메모리만 팠습니다. 아홉 달이 지나 도달한 결론은 이렇습니다.

메모리는 이제 그 자체로는 제품이 설 곳이 없습니다. ChatGPT도 Claude도 메모리는 기본 기능입니다. 저장하고, 필요할 때 불러와서, 참고해 대답하는 것까지는 이미 다 합니다. 이제 메모리는 목적이 분명한 메모리여야 합니다.

그리고 제가 만들려던 것, 행동과 결과물을 완벽하게 바꾸는 메모리는 존재할 수 없는 제품입니다. 저는 이걸 유니콘이라고 부르는데, 이유가 둘입니다. 존재하지 않는 동물이라서. 그리고 누군가 정말로 만들어낸다면, 그 회사는 단번에 유니콘이 될 것이라서.

결론이 틀리기를 바라는 마음도 없지 않습니다. 제 규칙이 서툴렀을 가능성도 물론 있습니다. 그래서 계측을 시작합니다. 어떤 규칙이 언제 발동해 무엇을 막았는지 기록을 쌓아보려고 합니다. 지난 코드 리뷰 글에서 끝의 기준을 에이전트에게 넘겨주는 실험을 이야기했는데, 그 실험의 데이터이기도 합니다. 몇 주 뒤 그 숫자가 이 결론을 지지하는지 반박하는지, 여기에 다시 적겠습니다.