인트로: mods 열 개, 살아남는 건 셋
Claude Code mods는 plugin 안에 들어 있는 TypeScript 함수로, Claude Code의 인터페이스를 다시 그리거나 동작 방식을 바꿔 쓸 수 있습니다. 10월 초 출시 후 하루도 지나지 않아 세 개의 영상 투어가 개발자에게 열 개를 설치하라고 권했습니다. 그중 두 크리에이터는 일부 mod가 아무것도 절약해 주지 않는다고 카메라 앞에서 인정했지만, 정작 단 하나도 측정하지 않았습니다. 이 테스트는 측정합니다. 화제가 된 mod 열 개를 전부 실제 업무 한 주 동안 돌리고, 오버헤드와 절감량, 유지할지 삭제할지의 판정을 숫자로 남겼습니다. 결론부터 말하면 현업 개발자의 머신에 둘 가치가 있는 건 열 개 중 셋뿐이고, 그중 하나는 모든 답변마다 조용히 token을 씁니다.
이번 유행과 우리가 돌린 것
Anthropic의 정의는 한 문장으로 끝납니다. mod는 이벤트에 hook을 거는 함수이고, 그 이벤트 전에, 후에, 또는 대신 실행될 수 있습니다. 이벤트란 tool call, 제출된 prompt, 그려지는 인터페이스의 한 부분입니다. mod는 평범한 TypeScript이며, 다른 것과 똑같이 설치하는 plugin 안에 담겨 배포됩니다.
출시 트윗은 약 하루 만에 조회수 400만을 넘겼고, 좋아요는 2만 개, 북마크는 답글과 리포스트를 합친 것보다 많았습니다. 출시 이틀 뒤에는 커뮤니티 카탈로그가 수백 개 저장소에 걸친 공개 mod 1,000개 이상을 이미 스캔한 상태였습니다.
이 테스트의 벤치는 실제 업무 한 주입니다. 프로젝트 네 개에 걸친 85개 세션, 거의 900개의 prompt, 6,000개에 조금 못 미치는 tool call입니다. 모든 mod는 무엇에 hook을 걸고 무엇에 접근할 수 있는지 보여 주는 validator 감사를 거쳤고, 현재 릴리스에서 같은 머신으로 깨끗한 기준선과 같은 작업을 돌려 비교했습니다.
결과의 큰 구도는 이렇습니다. 열 개 중 여섯은 런타임에서 측정할 만한 비용이 없고, 셋은 실제 시간이나 실제 token을 쓰며, 하나는 자신이 내건 단 하나의 약속을 깨뜨립니다.
측정한 장식 계층
조용한 여섯은 연결 상태의 오차 범위 안에 들어옵니다. 목표 미터, 저장소 히트맵, 플라이트 레코더, 모델 라우터, 세션 북마크, 자동 핸드오프는 모두 약 4초짜리 기준 작업에서 0.25초 빨라지거나 0.2초 느려지는 범위 안에 있습니다.
| mod | 런타임 차이 | 비고 |
|---|---|---|
| 목표 미터 | 오차 범위 내 | 장식용 패널 |
| 저장소 히트맵 | 오차 범위 내 | 파일을 읽는 즉시 불을 밝힘 |
| 플라이트 레코더 | 오차 범위 내 | 턴의 실시간 타임라인 |
| 모델 라우터 | 오차 범위 내 | subagent에서 효과를 냄, 판정 참고 |
| 세션 북마크 | 오차 범위 내 | 넓은 권한 범위 |
| 자동 핸드오프 | 유휴 시 ~70 ms | context 임계값에서 핸드오프를 한 번 기록 |
보기에는 훌륭하고 망가진 것도 없습니다. 모든 설정의 모든 실행이 작업을 올바르게 끝냈습니다. headless에서는 그릴 게 없으니 비용도 없습니다. 터미널에서는 이 패널들이 초당 최대 30번 다시 그려지므로, 장식 계층의 진짜 비용은 token이 아니라 주의력입니다.
validator 감사에서부터는 더 이상 웃을 수 없습니다. 북마크 mod는 모델을 호출하고, 머신에서 프로세스를 시작하고, 파일을 쓸 수 있으며, 환경 변수에서 설정 경로를 읽습니다. 숨겨진 것도, 악의적인 것도 없지만 북마크 하나에 주어진 권한치고는 너무 넓습니다. 여기서 네 개가 탈락합니다. 목표 미터, 히트맵, 플라이트 레코더는 측정된 이점이 0인 장식이라서, 북마크 mod는 얻는 것보다 더 많이 요구해서입니다.
대표 mod는 매 턴 청구서를 보냅니다
제안 엔진은 모든 영상이 가장 먼저 시연하는 mod입니다. 답변이 끝나면 composer 위에 prompt 제안 세 개가 나타나고, 숫자를 누르면 초안이 알아서 채워집니다. 이 동작 방식은 제작자 본인이 문서에 적어 두었습니다. 턴이 끝나면 세션을 fork해서 모델에게 제안을 요청하고, fork는 세션의 prompt cache를 공유하므로 짧은 답변 한 번 정도의 비용이 든다는 것입니다. 소개 영상들은 이 줄을 한 번도 언급하지 않습니다.
벤치에서 측정한 결과, 조건에 맞는 답변 하나당 output token이 약 250개, 벽시계 시간이 거의 3초 늘어납니다. 그리고 조건에 맞는 답변이란 거의 모든 답변입니다. 길이가 약 80자를 넘는 답변이면 다 해당합니다. fork에는 표면 게이트도 없습니다. 제안은 터미널에서만 그려지는데, fork는 어디서나 발동합니다. 아무것도 그릴 수 없는 headless 실행에서도 마찬가지입니다.
| mod | 측정된 비용 | 발동 시점 |
|---|---|---|
| 제안 엔진 | 조건에 맞는 답변당 output token ~250개 + ~2.9초 | headless 포함, ~80자를 넘는 모든 답변 |
| 캐시 키퍼 | 턴당 ~1.5초, 워밍 모드의 모델 호출 추가 | 매 턴, 몇 시간 동안 워밍 |
캐시 키퍼도 같은 구조입니다. 턴당 약 1.5초가 들고, 워밍 모드는 prompt cache가 식지 않게 하려고 몇 시간 동안 작은 모델 호출을 계속 씁니다. 구독 플랜에서는 cache 유지 시간이 이미 한 시간이므로, 플랜이 대부분 해결한 문제를 풀려고 핑 비용을 내는 셈입니다. 둘 다 비용을 문서화한 솔직한 설계이지만, 설치 목록에는 가격이 적혀 있지 않은 매 턴의 세금이고, 둘 다 머신에서 내려야 합니다.
같은 일을 하는 mod와 hook
Claude Code에는 이미 hook이 있었습니다. 같은 이벤트에서 실행되는, settings에 적어 두는 셸 스크립트입니다. 문서는 어느 쪽을 쓸지를 표의 한 행으로 답합니다. mod는 인터페이스와 이벤트 재작성용이고, hook은 이미 갖고 있는 스크립트로 차단, 허용, 로깅할 때 씁니다.
측정 가능한 차이는 프로세스 생성입니다. settings의 hook은 tool call마다 새 프로세스를 시작합니다. 이 머신에서 재 보니 아무 일도 안 하는 셸 hook은 약 8 ms, Node를 시작하는 hook은 약 43 ms가 들고, 이는 스크립트가 아무것도 하기 전에 모든 호출마다 발생합니다. 벤치 주간의 tool call 5,993개로 계산하면 순수한 인터프리터 시작 시간만 4분이 넘습니다. mod는 이걸 전혀 내지 않습니다. handler가 엔진 자신의 프로세스 안에서 실행되고, 엔진 로그에서도 이 hop은 약 1밀리초에 안정됩니다.
| handler | 호출당 비용 | 호출 5,993번인 한 주 |
|---|---|---|
| 셸 hook (no-op) | ~8 ms | ~48초 |
| Node hook (no-op) | ~43 ms | ~4.3분 |
| mod (프로세스 내) | ~1 ms | ~6초 |
실제로 나온 유일한 마이그레이션 보고도 같은 말을 합니다. 셸 hook 27개가 mod 5개로 합쳐졌고, 호출마다 생기던 프로세스 생성도 함께 사라졌습니다. 남는 규칙은 이렇습니다. 인터페이스나 이벤트 재작성은 mod, 믿을 수 있는 스크립트로 차단, 허용, 로깅하는 건 hook(프로세스 생성 비용은 호출이 수천 번일 때만 문제가 됩니다), 계속 반복하는 지식은 skill입니다. 읽어 본 hook이 읽어 보지 않은 mod보다 낫습니다.
아무것도 안 하는 가드
만들 수 있는 가장 단순한 안전 mod는 모든 셸 명령을 지켜보는 가드이고, 이번에는 일부러 터지도록 작성했습니다. Claude Code에게 마커 파일을 만들라고 시켰더니 가드는 예외를 던졌고, 명령은 그대로 실행되어 파일이 생겼습니다. 버그가 아니라 문서화된 기본값입니다. hook이 예외를 던지거나, 시간 초과되거나, 잘못된 형태를 반환하면 Claude Code는 그 hook을 건너뛰고 계속 진행합니다. 망가진 장식 때문에 세션이 먹통이 되어서는 안 되지만, 망가진 가드는 아무도 읽지 않는 디버그 로그 한 줄만 남기고 조용히 fail open됩니다.
해결책은 deny를 반환하는 catch handler 하나입니다. 똑같이 터지는 가드에 catch를 붙이면 명령을 거부하고 실패 사실을 알려 줍니다. 한 줄이 가드를 fail open으로 둘지 fail closed로 둘지 결정하고, 문서가 바로 이 패턴을 제공하는데도 설치하는 사람은 거의 없습니다.
한 커뮤니티 팀이 현재 릴리스에서 이 케이스들을 다시 돌렸고, 모델이 한 말이 아니라 마커 파일로 판정했습니다. catch 패턴은 세 번 중 세 번 fail closed였습니다. 다만 한 경로는 여전히 조용히 망가져 있습니다. 호출이 이미 전달된 뒤에 반환한 deny는 tool을 멈추지 못합니다. 모델은 쓰기가 실패했다고 들었는데, 파일은 세 번 중 세 번 생겼습니다.
이 문제를 짚은 현장 보고에서는 며칠 동안 가드를 돌렸는데, 그 가드는 활성화되어 있고 로드도 되어 있었지만 아무 일도 하지 않았습니다. 오래된 플래그가 밑에서 가드를 꺼 버렸기 때문입니다. 카운터는 0에 멈춰 있는데 초록색 상태 칩이 세 개 켜져 있었습니다. 건강한 상태와 똑같아 보이는 침묵입니다.
충돌 가드가 첫 번째 유지 판정을 받습니다. 열려 있는 두 채팅이 같은 파일을 편집하는 실제 문제를 풀고, 실패 방식도 시끄럽습니다. 대화상자로 물어보고 조용히 허용하는 법이 없습니다. 편집 시 약 0.5초가 들고 prompt에는 아무것도 더하지 않습니다. 설치하되, 그래도 catch handler는 붙여 주세요.
붙여 넣을 때 내주는 권한
Anthropic은 출시 당일 이를 평이한 말로 밝혔습니다. mod는 Claude Code 자체와 같은 수준으로 머신에 접근하며 sandbox에서 실행되지 않으므로, 컴퓨터에 다른 코드를 설치할 때처럼 설치하라는 것입니다. 구체적으로 mod는 당신의 권한으로 머신에서 행동할 수 있습니다. API 키가 있는 환경 변수와 settings를 읽고, 모든 prompt와 tool call을 보고, 그것들을 고쳐 쓰고, 묻기도 전에 tool call을 승인하고, 플랜의 사용량을 자기만의 모델 호출에 쓸 수 있습니다.
조심하는 사용자도 걸리는 함정이 둘 있습니다. 권한 규칙은 mod 자신의 호출이 아니라 Claude의 tool call을 통제합니다. Claude에게 env 파일을 막아 두어도 mod는 자신의 파일 접근으로 그 파일을 직접 읽거나, 읽어 주는 프로그램을 시작할 수 있습니다. 네트워크 정책도 같은 경계가 있습니다. 웹 트래픽을 끄면 mod 자신의 fetch 호출은 거부되지만, mod가 시작한 자식 프로세스는 전체 권한으로 네트워크에 닿습니다. 모든 것보다 먼저 로드되는 내장 가드 mod가 있긴 하지만, 관리되는 머신과 Team 또는 Enterprise 좌석에서만 적용됩니다. 개인 구독의 단독 좌석에는 아무것도 없습니다.
이건 이론이 아닙니다. 한 사용자가 출시 며칠 뒤 개념 증명을 공개했습니다. 버튼을 누르면 프로그램을 시작하고 홈 디렉터리에 쓰는 mod가 경고 하나 없이 카탈로그에서 설치되었습니다. 그의 지적은 여전히 유효합니다. 카탈로그는 앱 스토어처럼 생겼고, 그래서 존재하지 않는 검증이 있는 것처럼 보입니다. 별개의 hook 버그는 하루 동안 subagent 격리를 깨뜨렸고, 메인테이너는 이를 큰 실수라고 부르며 한 릴리스 뒤에 고쳤습니다.
카탈로그가 스캔한 공개 mod 1,000개 이상 중에서 400개 넘게 호스트 프로세스를 시작하고, 400개 가까이 파일을 읽고, 300개 넘게 모든 tool call을 봅니다. 카탈로그 자체의 단서가 올바른 해석입니다. 이는 판정이 아니라 권한 범위입니다. PR 트래커는 git을 실행해야 하니까요. 이 습관에는 2분이 듭니다. 무엇이든 활성화하기 전에 validator를 돌리고, 탈출구를 알아 두세요. 한 세션 동안 쓰는 safe mode, 설치된 모든 hook을 영구히 멈추는 설정 하나입니다.
셋은 유지, 일곱은 삭제
열 개 중 자리를 지킬 만한 건 셋입니다. 충돌 가드, 모델 라우터, 자동 핸드오프입니다.
| mod | 판정 | 근거가 되는 숫자 |
|---|---|---|
| 충돌 가드 | 유지 | 편집 시 ~0.5초, 시끄럽게 실패, prompt에 추가되는 것 없음 |
| 모델 라우터 | 유지 | subagent가 저렴한 모델로 청구됨, 가격은 3분의 1 |
| 자동 핸드오프 | 유지 | 70 ms의 무(無), context 임계값에서 핸드오프 기록 한 번 |
| 제안 엔진 | 삭제 | 조건에 맞는 모든 답변에 output token ~250개 + ~2.9초 |
| 캐시 키퍼 | 삭제 | 턴당 ~1.5초, 1시간짜리 cache 창을 상대로 한 워밍 핑 |
| 녹화 모드 | 삭제 | 화면은 가리지만 디스크는 가리지 못함 |
| 목표 미터 | 삭제 | 장식, 측정된 이점 0 |
| 저장소 히트맵 | 삭제 | 장식, 측정된 이점 0 |
| 플라이트 레코더 | 삭제 | 장식, 측정된 이점 0 |
| 세션 북마크 | 삭제 | 하는 일을 훨씬 넘어서는 권한 |
모델 라우터에는 영수증이 있습니다. 큰 모델로 돌린 세션이 subagent 하나를 띄웠는데, 그 실행의 사용량 표시에는 subagent가 저렴한 모델로, 같은 작은 일에 3분의 1 가격으로 청구된 것으로 나왔습니다. subagent를 많이 쓰는 주에는 이게 실제 돈입니다. 자동 핸드오프는 효과를 내는 순간까지 아무 비용이 없습니다. 유휴 오버헤드는 70밀리초이고, context 임계값을 넘으면 콜드 스타트용 핸드오프를 한 번 기록합니다. 이번 유행의 크리에이터 한 명은 수동 핸드오프 버튼이 시간을 별로 아껴 주지 않는다고 인정했는데, 임계값에서 자동으로 기록하는 방식이라면 실제로 아껴 줍니다.
테스트 끝에 남는 습관은 이렇습니다. 무엇이든 활성화하기 전에 validator 감사를 읽고, 모든 가드에 catch handler를 붙여 fail closed로 만들고, 데모는 마스킹 mod를 믿지 말고 safe mode에서 녹화하세요. 한계도 분명합니다. 한 주, 한 머신, 한 가지 작업량이고 작은 모델에서 측정 지점당 세 번 실행했습니다. 당신의 셋은 다를 수 있지만, 이제 그걸 찾는 방법은 알게 되었습니다.
AIDive