규칙 파일은 계속 늘어나기만 합니다. 아무런 역할도 하지 않는 규칙을 찾는 방법
요약
AI 코딩 에이전트를 위한 프로젝트 규칙 파일이 비대해지며 발생하는 컨텍스트 비용과 성능 저하 문제를 다룹니다. 단순히 규칙이 실행되는 횟수가 아니라, 실제 결과의 변화를 이끌어내는지 측정하여 불필요한 규칙을 정리하는 감사 루프의 필요성을 강조합니다.
핵심 포인트
- 불필요한 규칙은 토큰 비용을 높이고 에이전트의 주의력을 분산시킴
- 도구 업데이트에 따라 과거의 규칙이 잘못된 정보를 제공하는 부패 현상 발생
- 규칙의 유효성은 실행 횟수가 아닌 실제 결과의 변화로 판단해야 함
- 효율적인 에이전트 운영을 위해 규칙 파일에 대한 정기적인 감사 루프가 필수적임
이 글은 AI 코딩 에이전트를 위한 프로젝트 규칙 시리즈의 세 번째 파트입니다. Part 1에서는 Cursor, Claude Code, Codex가 규칙을 로드하는 방식을 다루었습니다. Part 2에서는 훅 (hooks)을 사용하여 규칙을 강제하는 방법을 다루었습니다. 이번 파트에서는 거의 아무도 하지 않는 부분, 즉 여러분의 규칙 중 어떤 것이 쓸모없는 짐(dead weight)인지 파악하는 방법을 다룹니다.
추가만 되는 문제 (The append-only problem)
제가 본 거의 모든 장기 운영되는 규칙 파일은 동일한 생애 주기를 가집니다. 처음에는 다섯 줄 정도로 시작합니다. 에이전트가 짜증 나는 행동을 하면 누군가 규칙을 추가합니다. 버그가 발생하면 누군가 규칙을 추가합니다. 6개월 후에는 40개의 규칙이 쌓여 있고, 그중 어떤 것이 여전히 중요한지 아무도 말해주지 못합니다.
그 이유는 체감되는 방식의 비대칭성 때문입니다: 규칙을 삭제하는 것은 위험하게 느껴지지만, 유지하는 것은 비용이 들지 않는 것처럼 느껴집니다. 하지만 유지하는 것은 공짜가 아닙니다:
- 컨텍스트 비용 (Context cost). 규칙은 모든 요청과 함께 전송됩니다. Claude Code에서는
CLAUDE.md가 매 세션마다 컨텍스트 (context)에 로드되며, Cursor에서는alwaysApply규칙이 모든 작업에 따라붙습니다. 쓸모없는 규칙에 소비되는 토큰은 실제 코드에 쓰이지 못하는 토큰입니다. - 희석 (Dilution). 에이전트는 40개의 지침을 동일한 비중으로 처리하지 않습니다. 가치가 낮은 모든 규칙은 실제로 사고를 방지하는 규칙들과 주의력을 두고 경쟁합니다. 짧은 파일은 단순히 비용이 저렴할 뿐만 아니라, 더 잘 준수됩니다.
- 부패 (Rot). 규칙은 작성 당시의 도구 동작에 대한 가정을 인코딩합니다. 도구는 매달 변경됩니다. 더 이상 존재하지 않는 동작을 참조하는 규칙은 단순한 노이즈보다 더 나쁩니다. 그것은 에이전트(그리고 새로운 팀원들)에게 잘못된 정보를 가르치기 때문입니다.
따라서 파일에는 감사 루프 (audit loop)가 필요합니다. 문제는 어떤 신호를 기준으로 감사할 것인가입니다.
"실행되었는가?"는 잘못된 질문입니다
당연한 본능은 각 규칙이 얼마나 자주 실행 (fires) 되는지, 즉 요청에 얼마나 자주 첨부되는지를 세는 것입니다. Cursor는 심지어 어떤 규칙이 첨부되었는지 보여주기 때문에, 이것이 측정 가능한 것처럼 느껴집니다.
이 시리즈의 파트 1 이후, 한 독자(@dipankar_sarkar)가 정확히 이 지점을 지적했고, 그의 프레임워크가 옳습니다: 매칭(matches)이 아니라 결과의 변화(outcomes-changed)를 세어야 합니다. 200번의 요청에 첨부되었지만 에이전트가 수행하는 동작을 단 한 번도 바꾸지 않은 규칙은 주석(comment)과 구별할 수 없습니다. 첨부(Attachment)는 규칙이 '존재(present)'했음을 알려줄 뿐, 그것이 '하중을 견디고(load-bearing)' 있었음을 의미하지는 않습니다.
문제는 "결과의 변화"가 반사실적(counterfactual)이라는 점입니다. 이를 직접 측정하려면 규칙이 '없었을 때' 에이전트가 무엇을 했을지 알아야 하는데, 일반적인 운영 중에는 이를 관찰할 수 없습니다. 모든 요청에 대해 모든 규칙을 A/B 테스트하는 것은 작업량을 두 배로 늘리지 않고서는 불가능합니다.
하지만 저렴한 근사치가 있습니다.
삭제 테스트: 저렴한 반사실적 방법
규칙이 없는 세상을 시뮬레이션할 수 없다면, 잠시 동안 그 세상을 '만드십시오'.
- 대상 선정. 지난 한 달 동안 당신을 "구해준" 기억이 없는 규칙들. 모두가 읽기를 그만둔 규칙들. 베이스 모델(base model)이 이미 잘 수행하고 있는 내용을 중복하는 규칙들을 고르세요.
- 삭제하지 말고 격리(Quarantine)하세요. 로드되는 파일에서 완전히 제외하여, 어떤 도구도 로드하지 않는
rules-quarantine.md로 옮기세요 (Cursor 규칙의 경우,alwaysApply를 끄거나 파일을.cursor/rules/외부로 이동시키세요). Git은 어떤 경우에도 히스토리를 유지하므로, 이는 설계상 되돌릴 수 있습니다. 피해야 할 함정 하나: CLAUDE.md 내부에서 특정 섹션에 "이것을 무시하세요"라고 표시하기만 해서는 안 됩니다. 에이전트는 여전히 로드된 파일의 모든 토큰(token)을 읽기 때문에, 규칙은 여전히 컨텍스트(context)에 남아 있으며, 당신의 테스트는 아무것도 측정하지 못하게 됩니다. - 1~2주 동안 평소처럼 작업하세요. 특별한 테스트 장치는 필요 없습니다. 당신의 정기적인 코드 리뷰(code review) 자체가 테스트 장치입니다.
- 무엇을 수정하는지 관찰하세요. 격리된 규칙이 규정했던 사항에 대해 에이전트를 단 한 번도 다시 수정하지 않았다면, 그 규칙은 불필요한 짐(dead weight)이었습니다. 모델이 이미 오래전에 해당 동작을 내재화했거나, 다른 규칙이 이미 이를 커버하고 있는 것입니다. 이제 실제로 삭제하세요.
- 실패가 다시 발생하면 규칙을 복구하세요. 그러면 이제 당신은 가치 있는 사실 하나를 알게 됩니다: 그 규칙은 하중을 견디고 있으며(load-bearing), 문장(prose)으로서의 역할도 하고 있다는 사실입니다.
이 시리즈의 파트 2에서는 하중을 견디는 규칙(load-bearing rules)이 단순한 문장(prose)이 아니라, 기계적인 강제 집행(hooks, linters, CI)을 받을 자격이 있다고 주장했습니다. 잘못된 방향으로 삭제 테스트(deletion test)를 통과한 규칙은 훅(hook)으로 승격시키기에 가장 적합한 후보입니다.
이 작업이 안전한 이유는 두 가지 실패 모드(failure modes)의 비대칭성 때문입니다. 잘못 삭제된 규칙으로 인한 회귀(regression)는 가시적이며 비용이 저렴합니다 — 어차피 검토 중이던 diff에 나타나며, git revert로 해결할 수 있습니다. 반면, 계속 유지하고 있는 죽은 규칙은 비가시적이며 영구적인 비용을 발생시킵니다 — 모든 요청에 영원히 부하를 주지만 아무도 알아차리지 못합니다. 에이전트(agent)의 출력을 어차피 검토하는 워크플로우라면, 삭제는 생각보다 훨씬 안전합니다.
당신의 수정 로그가 감사 신호입니다
삭제 테스트 사이의 일상적인 신호는 더 간단합니다: 당신은 무엇을 계속 수정하고 있는가? 에이전트의 출력을 수동으로 수정할 때마다, 그 수정 사항은 세 가지 범주 중 하나에 속하며, 각 범주에는 서로 다른 조치가 필요합니다:
- 이미 규칙이 커버하고 있는 내용을 수정했습니다. 해당 규칙은 하중을 견디고 있지만 강제 집행이 부족한 상태입니다. 문장(prose)으로서의 역할은 실패했으므로, 문구를 다듬는 것을 멈추고 기계적으로 강제 집행하십시오 (파트 2 참조).
- 어떤 규칙도 커버하지 않는 내용을 수정했습니다. 규칙이 누락되었습니다. 규칙을 추가하십시오 — 이것이 파일이 늘어나는 정당한 방식입니다.
- 규칙이 당신의 수정 사항에 전혀 나타나지 않습니다 — 당신도 위반하지 않고, 에이전트도 위반하지 않습니다. 그것이 당신의 다음 삭제 테스트 후보입니다.
이것이 분류(triage)의 전부입니다. 모든 규칙은 결국 네 가지 상태 중 하나로 귀결됩니다: 강제 집행(enforce) (훅으로 승격), 유지(keep) (절감 효과 관찰됨), 추가(add) (규칙 없는 수정 사항), 삭제 테스트(delete-test) (어느 쪽인지 증거가 없음).
20분 분기별 감사
구체적으로, 분기에 한 번(또는 속도가 빠르다면 N 세션마다):
- 파일을 처음부터 끝까지 읽습니다. 각 규칙에 대해 다음을 질문하세요: 이 규칙이 마지막으로 우리를 구해준 적이 언제인가? 만약 아무도 구체적인 사례를 들어 답할 수 없다면, 해당 규칙을 표시하세요.
- 그 기준에 따라 하위 20%를 격리(Quarantine)합니다.
- 격리 파일에 날짜를 기록하고(팀 변경 로그(changelog)에 한 줄의 포인터를 남겨), 팀 전체가 이 테스트를 인지할 수 있도록 합니다.
- 2주 후: 아무런 반응이 없었던 규칙은 삭제하고, 반응이 있었던 규칙은 복구합니다(그리고 훅(hook)화하는 것을 고려하세요).
- 시간이 지남에 따라 하나의 수치를 추적하세요: 순 라인 수 (net line count). 수정률(correction rate)이 떨어지면서 라인 수가 정체되거나 감소한다면, 파일이 더 밀도 있게 구성되고 있는 것입니다. 만약 라인 수만 계속 늘어난다면, 당신은 큐레이션(curating)을 하는 것이 아니라 축적(accumulating)하고 있는 것입니다.
불편한 결론
잘 감사된 규칙 파일의 최종 상태는 짧습니다. 모델은 매 릴리스마다 더 많은 관습을 흡수합니다. 1월에 진정으로 자리를 잡았던 규칙이 6월에는 베이스 모델(base-model)의 기본 동작이 되어 있을 수 있습니다. 반복적인 삭제 테스트에서 살아남는 규칙은 모델이 알 수 없는 것들을 인코딩(encoding)하는 규칙들입니다: 즉, 당신의 아키텍처 결정, 팀의 명확하지 않은 제약 조건, 그리고 당신의 완료 정의(definition of done)입니다.
규칙을 법이 아닌 의존성(dependencies)처럼 취급하세요: 규칙을 감사하고, 업그레이드하고, 더 이상 아무런 역할도 하지 않는 규칙은 제거하세요. 그렇게 해서 얻게 된 파일은 더 작고, 더 저렴하며 — 살아남은 모든 규칙은 누군가가 이름을 댈 수 있는 이유가 있기 때문에 — 그것을 읽는 사람과 에이전트(agents)들에게 실제로 신뢰받게 됩니다.
저는 Rulestack을 운영하고 있습니다. 이는 현재 도구의 동작에 맞춰 감사된 Cursor, Claude Code, Codex용 규칙 팩입니다. 이를 통해 당신은 자격을 갖춘 규칙들로부터 시작할 수 있습니다. Bluesky @ai-shop.bsky.social을 통해 피드백을 환영합니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기