지난번에는 Claude Code에 스스로 스킬을 작성하게 하여 키우는 이야기에 대해 썼습니다. 스킬이나 플러그인을 늘려가다 보면 언젠가 반드시 부딪히게 되는 문제가 바로 세션이 무거워지거나 지시를 놓치는 문제입니다. 이번에는 그 원인을 측정하여 컨텍스트 주입 (Context Injection)을 228KB에서 48KB까지 줄인 감사 (Audit) 기록입니다.
증상: 최근의 지시를 놓침
어느 시점부터 Claude Code가 다음과 같은 동작을 하기 시작했습니다.
- 세션 시작이 무거움
- 「방금 말한 것」을 무시하고, 이전 화제와 혼선됨
처음에는 "모델의 상태" 문제인가 생각했지만, 아니었습니다. SessionStart에서 주입되는 컨텍스트가 너무 비대해져서, 최근 사용자의 지시가 파묻혀 있었던 것이 원인이었습니다. 주입량이 클수록 대화의 최신 부분에 대한 상대적인 존재감이 옅어집니다.
구분: 무거운 것과 멍해지는 것은 원인이 다르다
감사를 통해 알아낸 중요한 구분점은 이것입니다.
| 증상 | 진짜 범인 | 대처 |
|---|
| 세션이 무겁기만 함 | 활성화된 플러그인 수 | 사용하지 않는 플러그인을 disable |
| 최근 지시를 놓침·화제가 혼선됨 | 주입 총량 | 주입원을 측정하여 쳐내기 |
"무거운 것"과 "멍해지는 것(보케, ボケ)"을 하나로 묶어 생각하면, 플러그인만 줄이다가 효과를 보지 못합니다. 멍해지는 쪽의 본질적인 원인은 따로 있습니다.
측정: 주입원별 바이트 수 산출
주입원은 여러 가지가 있습니다. 플러그인의 메타데이터 (metadata), rules/, Obsidian 문맥, auto-memory, remember 이력. 이것을 소스별로 실측합니다. 토큰은 대략 "바이트 수 ÷ 4 ≒ 영어 토큰"으로 추산할 수 있습니다.
# rules/ 하위는 「글로벌 지시 (Global Instruction)」로서 전문이 자동으로 로드됨 (상한 없음)
find ~/.claude/rules/ecc -name '*.md' -exec cat {} + | wc -c
# auto-memory (MEMORY.md 는 전문 주입)
...
측정해 보니 범인은 명확했습니다. **rules/ecc 단독으로 약 57K 토큰(≒228KB)**을 차지하고 있었으며, 전체 주입량 중에서 압도적인 최대 블록이었습니다.
rules/가 그렇게 무거웠던 이유
여기가 가장 큰 함정이었습니다. ~/.claude/rules/ 하위는 @import로 필요할 때 읽는 것이 아니라, **Claude Code가 글로벌 지시로서 디렉터리 전체를 매번 풀 로드 (Full Load)**합니다.
저의 rules/ecc에는 범용 규칙 팩 유래로 10개 언어분의 규칙(angular / golang / swift / php / ruby / arkts / java / kotlin …)이 통째로 들어 있었습니다. 제가 실제로 쓰는 것은 Python / TypeScript / Web 3개뿐인데도, 쓰지도 않는 Swift나 Ruby의 코딩 규약이 매 세션마다 전문이 계속 주입되고 있었던 것입니다.
수정: 사용하는 언어만 남기고 「트리 외부」로 격리
rules/는 @import가 아니라 디렉터리 로드 방식이므로, import 행을 수정할 필요는 없습니다. 파일을 트리 외부로 mv 하는 것만으로 주입이 중단됩니다. 그리고 다시 되돌리고 싶을 때는 mv로 옮기기만 하면 됩니다 ―― 완전히 비파괴적입니다.
# 사용하는 언어(common/python/typescript/web)만 남기고, 나머지는 트리 외부로 퇴피
A="$HOME/.claude/.rules-archive/ecc"; mkdir -p "$A"
cd ~/.claude/rules/ecc
...
결과
쳐낸 후, 현재의 rules/ecc를 다시 측정하니 다음과 같았습니다.
$ find ~/.claude/rules/ecc -name '*.md' -exec cat {} + | wc -c
48092
$ ls -d ~/.claude/rules/ecc/*/ | xargs -n1 basename
...
228KB(≒57K 토큰) → 48KB(≒12K 토큰). 약 79% 감소. 디렉터리도 10개 언어에서 4개로 줄었습니다. 새로운 세션을 열면 기동이 가벼워지고, 최근 지시를 놓치는 현상도 명확하게 줄었습니다.
빠졌던 함정
디스크 정리와 토큰 삭감은 별개
처음에는 Obsidian의 hot.md...
가 32KB로 부풀어 올라 있었기에 "이것을 깎아내면 가벼워질 것"이라고 생각했습니다. 틀렸습니다. Obsidian 문맥은 주입 스크립트 측에서 hot.md=9000자 / index=2500자와 같이 이미 상한선이 컷오프(cut-off)되어 있어서, 파일이 몇 KB로 커지든 주입량은 약 7K 토큰으로 일정합니다.
마찬가지로 remember의 today-*.done.md도 주입 대상에서 제외됩니다. 이것들을 지우는 것은 디스크 정리일 뿐, 토큰은 1bit도 줄어들지 않습니다. "파일이 크다 = 주입이 무겁다"는 성립하지 않으므로, 반드시 주입원(injection source)을 실측해야 합니다.
MAX 플랜에서도 메리트는 있다
"MAX 플랜이라면 $/token은 정액제니까 상관없지 않을까?"라고 생각할지도 모릅니다. 비용 측면에서는 그렇습니다. 하지만 절감의 진짜 메리트는 따로 있습니다.
- 컨텍스트 창 (Context Window)의 절약 (긴 작업에서 효과적)
- 캐시 히트율 (Cache Hit Rate)의 안정화
- 세션 기동의 고속화
- 그리고 무엇보다, 최근 지시사항이 묻히지 않음
disable은 가역적, uninstall은 비가역적
플러그인을 줄일 경우, settings.json의 enabled: true → false라면 즉시 롤백(rollback)할 수 있습니다. claude plugin uninstall은 디스크 자체를 회수하므로 비가역적입니다. 우선은 disable로 경과를 지켜봐야 합니다. 단, disable하면 해당 플러그인의 슬래시 명령(slash command)은 에러가 발생하므로, 드물게 사용하지만 중요한 명령은 남겨둡니다.
요약
- "무겁다"(=플러그인 수)와 "멍해진다"(=주입 총량)는 별개의 문제. 혼동하지 말 것.
~/.claude/rules/는 @import가 아니라 디렉토리 전체 로드. 최대의 주입원이 되기 쉬움 - 수정은 파일을 트리 외로 = 비파괴적인 mv를 하는 것만으로 충분. 롤백도 mv로 가능.
- 디스크 청소 ≠ 토큰 절감. 반드시 주입원을 바이트(byte) 단위로 실측할 것.
- 결과: 228KB → 48KB (약 79% 감소), 기동과 응답 모두 가벼워짐.
다음에는 이러한 자동화(스킬 생성·감사·브리프)를 24시간 돌리기 위해 구성한 launchd 이야기와, 그 과정에서 빠졌던 macOS 특유의 함정에 대해 쓰겠습니다.
Discussion