당신의 AI 에이전트에게는 룰 파일이 있습니다. 시스템의 모델은 없습니다.

당신의 저장소 루트에 있는 CLAUDE.md, AGENTS.md, .cursor/rules를 열고, 에이전트에게 도달하는 그대로 읽어 보세요. 하나의 텍스트 덩어리로, 어떤 줄이 아직 참인지 표시해 주는 것이 아무것도 없는 상태로 말입니다.

거기서 발견하게 될 대부분은 컨벤션입니다. 탭을 쓸 것. any를 쓰지 말 것. 일찍 return할 것. 에러는 %w로 감쌀 것. 이런 줄들은 오래갑니다. 코드 한 줄을 어떻게 쓰는지를 서술하고 있고, 에이전트는 그것을 눈앞의 코드에 적용하기 때문입니다.

그리고 다른 종류의 줄이 있습니다. 당신의 시스템을 서술하는 줄입니다. 어떤 서비스가 존재하는지, 어떤 package가 무엇을 소유하는지, 레이어끼리 어떻게 대화하는 것이 허용되는지. 그 파일을 가질 만한 이유가 바로 그 줄들이고, 썩는 것도 바로 그 줄들입니다.

저는 압니다. 우리 파일이 그렇게 됐으니까요.

우리 파일에서 낡아 버린 것

Archyl 저장소에는 루트에 CLAUDE.md가 있습니다. 이 장르의 기준으로 보면 좋은 축입니다. 422줄, 아키텍처 트리, 설정 변수, dependency injection 배선, discovery 파이프라인 설명. 이 코드베이스를 건드리는 모든 에이전트는 다른 어떤 일을 하기 전에 이 파일을 읽습니다.

이 글을 쓰던 날 아침, 2026년 8월 5일에 파일에는 이렇게 적혀 있었습니다. 392번째 줄:

No test suite: The codebase currently has no Go test files or frontend tests.

테스트 스위트 없음: 이 코드베이스에는 현재 Go 테스트 파일도 프런트엔드 테스트도 없다.

backend/ 아래에는 146개의 _test.go 파일이 있고, frontend/src/ 아래에는 31개의 테스트 파일이 있습니다.

140번째 줄은 이렇게 말합니다:

AI Provider Abstraction: Supports both OpenAI and Ollama via ai.Provider interface.

AI 프로바이더 추상화: ai.Provider 인터페이스를 통해 OpenAI와 Ollama를 모두 지원한다.

backend/internal/adapter/ai/resolver.go는 플랫폼이 관리하는 OpenAI·Ollama 경로에 더해 OpenAI, Anthropic, Gemini, Bedrock, 그리고 OpenAI 호환 엔드포인트 전부로 라우팅합니다. 하나의 switch 문 안에 다섯 가지 프로바이더 타입. 파일이 이름을 대는 건 두 개입니다.

그리고 아키텍처 트리는 74번째 줄부터 87번째 줄에 걸쳐 internal/domain/ 아래 열한 개의 package를 나열합니다. c4, project, user, team, adr, projectdoc, flow, insight, subscription, dependency, history. 오늘 internal/domain/에는 마흔한 개의 디렉터리가 있습니다. 언급되지 않은 서른 개 중에는 이런 것들이 있습니다. conformance, drift, apicontract, marketplace, reality, managedagent, mcpsession. 다시 말해, 그 파일이 쓰인 이후 이 제품이 되어 온 것의 대부분입니다.

그 줄들은 하나하나 타이핑되던 날에는 참이었습니다. 이후에 고쳐진 것은 하나도 없습니다. 고치려면 사람이 알아차려야 하는데, 지켜보는 것이 아무것도 없었기 때문입니다.

여기는 아키텍처 문서화를 파는 회사입니다. 규율이 해법이었다면, 여기서야말로 통했을 겁니다.

그 파일의 두 절반은 서로 아무 공통점이 없다

컨벤션 쪽은 강제할 수 있습니다. "Go에서 fmt.Println 금지"는 grep 한 번입니다. "Go 파일명은 snake_case여야 한다"는 스크립트 하나입니다. 에이전트가 그중 하나를 어기면 CI에서 linter가 그렇게 말해 줍니다. 컨벤션 자체가 바뀌면 linter가 깨지기 시작하고 누군가 파일을 업데이트합니다. 피드백 루프가 있고, 그 루프는 작동할 만큼 짧습니다.

시스템 쪽에는 대응물이 없습니다. "결제 서비스는 데이터베이스 직접 접근 금지"에 해당하는 go vet은 없습니다. 그 문장을 파싱하는 것도 없고, 저장소와 대조하는 것도 없고, 더 이상 들어맞지 않게 되었을 때 실패하는 것도 없습니다. markdown 파일 안의 산문이고, 산문에는 실패 모드가 없습니다.

그래서 룰 파일은 하나의 파일명을 공유하는 두 개의 문서입니다. 하나는 계속해서 검증되고, 다른 하나는 한 번도 검증되지 않으며, 파일 안에는 그 둘을 구분해 주는 것이 없습니다. "에러는 %w로 감쌀 것"과 "이 코드베이스에는 테스트가 없다"가 같은 목록에, 같은 목소리로 놓여 있습니다. 하나는 에이전트 눈앞의 코드에 대한 규칙입니다. 다른 하나는 에이전트가 보고 있지도 않은 146개 파일에 대한 주장입니다.

더 어려운 절반은 부재다

낡아 가는 것은 누구나 그려 볼 수 있는 실패입니다. 더 조용한 쪽이 더 중요합니다. 룰 파일에는 누군가 적어야겠다고 생각한 것만 들어 있고, 그 안에는 "이건 존재하지 않는다"와 "아무도 언급하지 않았다"를 구분해 주는 것이 없습니다.

우리 파일은 internal/adapter/marketplace/를 한 번도 언급하지 않습니다. 그 package에는 provider 인터페이스 하나와 여덟 개의 어댑터가 들어 있습니다. GitHub, GitLab, Argo CD, Datadog, Prometheus, Sentry, SonarQube, PagerDuty. CLAUDE.md의 어댑터 목록은 git, ai, stripe, email, osv, registry에서 멈춥니다. 그 파일이 marketplace에 대해 말하는 것 중 틀린 건 하나도 없습니다. 그 파일에는 marketplace가 없으니까요.

에이전트에게 아홉 번째 연동을 추가해 달라고 요청하는 실험을 저는 해 보지 않았고, 그것이 무엇을 내놓을지 말씀드릴 생각도 없습니다. 결과를 지어내는 셈이 되니까요. 제가 말씀드릴 수 있는 것은, 그 지도 위에 marketplace가 없다는 것, 그리고 이것이 제가 읽어 본 모든 룰 파일의, 제가 직접 쓴 것들을 포함한, 지극히 평범한 상태라는 것입니다.

모델에는 그런 성질이 없습니다. 모델에는 무엇이 존재하는지 물어볼 수 있고, 의미 있는 답을 받습니다. 그 답이 산문을 훑는 검색이 아니라 집합에 대한 쿼리이기 때문입니다. "무엇이 결제 서비스와 대화하는가"는 그래프는 답할 수 있고 문단은 답할 수 없는 질문입니다.

뻔한 두 가지 답, 그리고 둘 다 성립하지 않는 이유

더 좋은 룰 파일을 쓴다. 더 길게, 더 꼼꼼하게, pull request 템플릿에 체크박스 하나. 팀들은 이렇게 합니다. 그리고 몇 주는 잘 굴러갑니다. 오래가지 않습니다. 규율과는 무관한 이유 때문입니다. 시스템을 서술하는 모든 줄은 다른 곳에 사는 무언가의 캐시된 사본이고, 캐시에는 무효화가 필요합니다. 여기서 무효화란 사람이 알아차리는 것입니다. 그게 메커니즘의 전부이고, 지난 이십 년간 아키텍처 다이어그램을 정확하게 유지하기로 되어 있던 바로 그 메커니즘입니다. 결과가 어땠는지는 우리도 압니다. drift 탐지 가이드가 그 논지의 긴 버전입니다.

에이전트가 저장소를 읽게 한다. 읽을 수 있고, 파일 하나에 대한 질문이라면 읽어야 합니다. 하지만 코드를 읽는다고 해서 어떤 경계가 의도된 것이었는지는 알 수 없습니다. 서비스 앞에 놓인 인터페이스는, 2년 전 장애 이후 내려진 결정 때문에 거기 있는 경우와 누군가 인터페이스를 좋아해서 거기 있는 경우가 똑같이 생겼습니다. 의도는, 그로부터 나온 산출물에서 복원되지 않습니다. 애초에 룰 파일이 존재하는 이유가 그것이고, 그것을 지우는 것도 답이 아닌 이유가 그것입니다.

이 회사 밖에서도 같은 것을 알아챈 사람이 있다

Thoughtworks는 "Architecture drift reduction with LLMs"를 Technology Radar Vol. 34의 Assess 링에 올렸습니다. 2026년 4월 발행입니다. 그들의 첫 문단:

Increased use of AI coding agents can accelerate drift from the intended codebase and architecture designs. Left unchecked, this drift compounds as agents and humans replicate existing patterns, including degraded ones, creating a feedback loop where poor code begets poorer code.

AI 코딩 에이전트의 사용이 늘어나면 의도했던 코드베이스와 아키텍처 설계로부터의 이탈이 가속될 수 있다. 방치하면 이 drift는 에이전트와 사람이 기존 패턴을, 열화된 것까지 포함해 복제하면서 누적되고, 나쁜 코드가 더 나쁜 코드를 낳는 피드백 루프를 만든다.

Assess는 레이더 자체의 정의로 "worth exploring with the goal of understanding how it will affect your enterprise" — 그것이 당신의 조직에 어떤 영향을 줄지 이해하려는 목적으로 탐색해 볼 만하다는 뜻입니다. 무언가에 대한 추천이 아니며, 우리에 대한 추천은 더더욱 아닙니다. 그들의 일부 팀이 이것을 시도하고 있고 아직 이르다는 메모입니다.

쓸모 있는 부분은 그들이 묘사하는 형태입니다. 결정론적 분석 도구(Spectral, ArchUnit, Spring Modulith을 거론합니다)와 LLM 평가의 결합. 구조는 프로그램이 검사할 수 있고 의도는 그럴 수 없기 때문입니다. 그들이 보고한 교훈도 훔쳐 올 만합니다. 첫 스캔은 누구도 트리아지하고 싶지 않을 만큼 많은 위반을 끄집어냅니다.

그 레시피에 없는 것을 눈여겨보세요. 에이전트가 가속시키는 drift에 대한 답으로 더 긴 markdown 파일을 내놓는 사람은 아무도 없습니다.

그 산출물이 갖춰야 할 것

두 가지 성질입니다. 둘 다 특이한 것이 아닙니다.

열거할 수 있어야 합니다. 무엇이 존재하는지 물었을 때 누군가의 기억이 아니라 집합을 받아야 합니다. 읽는 것이 아니라 질의하는 산출물이라는 뜻이고, 그 차이가 가장 혹독하게 드러나는 건 아무도 적어 두지 않은 질문들에서입니다.

반증 가능해야 합니다. 무언가가 그것을 코드와 대조해서 어느 부분이 더 이상 참이 아닌지 보고해야 합니다. 그것도 "사람이 알아차릴 때"가 아닌 주기로요. ArchUnit은 Java 레이어 규칙에 대해 이 일을 합니다. dependency-cruiser는 JavaScript import에 대해 합니다. 둘 다 의도적으로 좁고, 둘 다 핵심을 보여 줍니다. 가질 만한 가치가 있는 산출물이란 프로그램이 반박할 수 있는 산출물입니다.

룰 파일은 두 가지 모두에서 낙제합니다. 열거하지 않고, 아무것도 그것에 반박할 수 없습니다.

우리가 서 있는 자리, 그리고 제가 말씀드릴 수 없는 것

Archyl은 당신 시스템의 C4 모델을 유지합니다. 시스템, 컨테이너, 컴포넌트, 관계. AI 디스커버리가 저장소에서 생성하고, 사람이 그리는 것이 아니라 사람이 승인합니다. 그 모델이 열거 가능한 절반이고, 에이전트는 MCP를 통해, 181개 툴에 해당하는 폭으로 거기에 접근합니다. 그래서 에이전트는 누군가 적어 두었기를 바라는 대신 무엇이 존재하는지 묻습니다. 컨벤션 절반은 conformance 카탈로그입니다. 이름이 붙은 23개 기술에 걸친 169개 규칙에 언어 비의존 세트를 더한 것으로, 산문이 아니라 결정론적 검사입니다. 그리고 모델은 코드와 다시 대조되어 점수가 매겨지는데, 이것이 반증 가능성이라는 성질입니다.

MCP 서버를 갖고 있다는 것 자체는 흥미로운 부분이 아니고, 그것을 차별점이라며 파는 사람은 당신에게 콘센트를 파는 것입니다. Structurizr도 하나 내놓았고, IcePanel의 것은 오픈 베타 중입니다. 다툴 만한 질문은 콘센트 뒤에 있는 것이 유지되고 있느냐입니다. 3월에 낡아 버린 모델을 서빙하는 엔드포인트는 더 빨리 틀리는 방법일 뿐이니까요.

저는 그것이 중요한 차이라고 생각합니다. 증명할 수는 없습니다. 유지되는 모델에서 작업하는 에이전트가 잘 다듬어진 룰 파일에서 작업하는 에이전트보다 형태가 더 나은 코드를 쓰는지는 아무도 측정하지 않았고, 누군가 측정하기 전까지 그 문장은 메커니즘에 대한 주장이지 결과가 아닙니다. 그렇게 붙들어 두시고, 제가 방금 말한 것보다 더 단정적으로 말하는 사람이 있으면 되받아치세요.

여기에는 솔직하게 짚어야 할 주름도 있습니다. Archyl은 룰 파일을 생성합니다. MCP 툴 get_agent_context는 아키텍처를, 당신의 저장소에 commit할 수 있는 markdown 브리핑으로 돌려줍니다. 이름만 다른 룰 파일입니다. 파일이 문제였던 적은 없습니다. 문제는 그 뒤에 아무것도 서 있지 않았다는 것, 그래서 아무것도 그것을 재생성할 수 없었다는 것입니다. 유지되는 모델의 캐시인 룰 파일은 괜찮습니다. 유일한 사본인 룰 파일은 한 사람이 어느 오후에 믿었던 것의 스냅숏입니다.

5분짜리 버전, 비용은 하나도 들지 않습니다

위의 내용은 전부 무시하고 대신 이것을 해 보세요.

당신의 룰 파일을 엽니다. 한 줄씩 내려가면서 각 줄을 컨벤션(에이전트에게 코드를 어떻게 쓰는지 알려 주는 줄)이거나 주장(에이전트에게 당신 시스템에 대해 무언가를 알려 주는 줄)으로 표시합니다. 그런 다음 주장 하나하나에 대해, 그것이 더 이상 참이 아니게 되었다는 걸 무엇이 알려 줄지를 적습니다.

제 짐작으로는 두 번째 열이 빈 채로 파일 끝에 도달하실 겁니다. 그게 간극입니다. 그에 대해 무엇을 할지는 별개의 결정이고, 그 간극을 보기 위해 무언가를 살 필요는 없습니다.

우리 파일은 몇 분이 걸렸고 틀린 줄 세 개가 나왔습니다. 그걸 고치는 건 commit 하나이고, 구조적으로는 아무것도 바뀌지 않습니다. 다음 줄도 똑같은 방식으로 낡아 갈 것이고, 그 줄을 지켜보는 것 역시 아무것도 없으니까요.