용어사전 — 읽다 막히는 말
바탕 이 컴퓨터의 실제 설정 · 실측일 2026-08-24 · 스킬 14개 · 플러그인 3개
용어 카드가 말 하나를 푼다면 이 글은 그 말들이 한 판에서 어떻게 맞물리는지를 잇습니다.
클로드 코드에 무언가를 더하는 방법이 다섯 가지 있습니다. 스킬·슬래시 명령·서브에이전트·훅·MCP 서버입니다. 이름만 보면 다섯이 비슷한 층에 있는 것 같지만 꽂히는 자리가 다릅니다. 어디에 꽂히느냐가 그 부품으로 무엇을 할 수 있고 무엇을 못 하는지를 정합니다.
앞선 용어 카드에서 하네스(harness)를 열두 걸음으로 풀었습니다. 그 열두 걸음 가운데 부품이 실제로 꽂히는 줄은 셋뿐입니다.
부품 다섯이 판의 어느 줄에 꽂히나
이 배치에서 읽을 것이 하나 있습니다. 다섯 중 넷이 ②에 꽂힙니다. ②는 모델을 부르기 직전에 지금까지의 상태를 글로 조립하는 자리입니다. 즉 「도구를 확장했다」는 말은 대개 모델에게 읽힐 글을 늘렸다는 뜻입니다. 실행을 실제로 바꾸는 부품은 훅 하나뿐이고, 나머지는 모델이 읽고 판단하기를 기대하는 것입니다.
부르는 주체와 꽂히는 자리로 가르면 섞이지 않습니다.
스킬(skill)은 폴더 하나에 담은 절차서입니다. 모델이 「지금 이 일에 필요하다」고 판단해 스스로 엽니다. 슬래시 명령(slash command)도 글을 넣는 것은 같은데, 사람이 /이름을 쳐야 열립니다. 서브에이전트(subagent)는 판을 통째로 하나 더 여는 것입니다. 그 판에서 무엇을 읽었든 이 판에는 마지막 보고 한 덩어리만 돌아옵니다.
훅(hook)은 정해진 시점에 무조건 도는 프로그램입니다. 모델의 판단을 거치지 않습니다. MCP 서버(Model Context Protocol server)는 도구 목록을 하네스 밖에서 꽂는 규격입니다. 이 컴퓨터에는 fetch · memory · time 셋이 붙어 있습니다. 플러그인(plugin)은 이 다섯을 한 상자에 담아 남에게 넘기는 포장입니다.
앞 절의 배치를 읽으려면 판 자체를 먼저 봐야 합니다. 아래 그림은 용어 카드에 실린 것과 같은 그림입니다.
하네스가 도는 한 판
요점은 ②가 요청마다 되풀이된다는 것입니다. 모델은 요청과 요청 사이에 아무것도 기억하지 않습니다. 지금 어느 디렉터리에 있는지, 무엇을 이미 고쳤는지, 쓸 수 있는 도구가 무엇인지를 매번 처음부터 다시 적어 보냅니다. 열두 걸음짜리 한 판이면 ②가 대여섯 번 되풀이됩니다.
그래서 ②에 무엇을 얹느냐가 값을 정합니다. 얹은 글은 한 번 읽히고 끝나지 않습니다. 판이 도는 내내 매 요청에 다시 실립니다.
절차서를 통째로 ②에 얹으면 그 값을 매 요청 물게 됩니다. 스킬은 이것을 두 단계로 나눠 피합니다. 평소에는 각 스킬의 description 한 줄만 실리고, 지금 하는 일과 맞는 한 장이 나타났을 때만 그 본문이 더해집니다.
스킬 14개를 깔아도 평소에는 4.1%만 실린다
이 저장소에서 실제로 재 본 값입니다. 스킬 14개의 본문을 다 합치면 82,552자인데 평소 실리는 것은 3,389자, 전체의 4.1%입니다. 스킬을 스무 개 더 깔아도 평소 부담은 설명 한 줄씩만 늘어납니다.
대가가 있습니다. 열리는 판단이 description 한 줄에 걸립니다. 그 줄이 지금 하는 일을 못 가리키면 본문은 영영 안 읽힙니다. 스킬을 쓸 만하게 만드는 일의 절반은 본문이 아닙니다. 그 한 줄을 다듬는 일입니다.
둘 다 ②에 글을 얹습니다. 다른 것은 누가 여느냐 하나입니다. 스킬은 모델이 설명 한 줄을 보고 스스로 열고, 슬래시 명령은 사람이 /이름을 쳐야 열립니다.
이 차이가 쓰임을 가릅니다. 「이 작업을 할 때는 반드시 이 절차를 따라라」처럼 모델이 알아서 집어야 하는 것은 스킬이어야 합니다. 「지금 이걸 해라」처럼 사람이 시점을 정하는 것은 명령이어야 합니다. 커밋 메시지를 만드는 일을 스킬로 두면 모델이 안 부를 때가 생기고, 문체 규칙을 명령으로 두면 사람이 매번 쳐야 합니다.
이 저장소에는 슬래시 명령이 0개, 스킬이 14개 있습니다. 규칙이 「글을 쓰기 전에 반드시 연다」는 성격이라 전부 스킬 쪽에 있습니다.
서브에이전트는 판을 하나 더 여는 것입니다. 새 판에는 새 컨텍스트 창이 붙습니다. 거기서 파일 마흔 개를 읽든 로그 만 줄을 훑든, 이 판에 돌아오는 것은 마지막 보고 한 덩어리뿐입니다.
이 저장소가 서브에이전트를 두는 이유가 그것입니다. semianalysis-transformer는 영어 뉴스레터 원문 한 편을 통째로 읽어 한국어 변환본을 씁니다. 원문이 수만 자라 메인 판에서 읽으면 그 뒤 작업 내내 그 글자가 매 요청에 다시 실립니다. 따로 연 판에서 읽고 결과 파일만 남기면 메인 판은 그 원문을 한 번도 안 봅니다.
대가는 두 가지입니다. 새 판은 이 판이 지금까지 알아낸 것을 모릅니다. 무엇을 하라는 지시를 처음부터 다 적어 보내야 합니다. 그리고 그 판이 무엇을 잘못 읽었는지도 이 판에 안 남습니다. 돌아온 보고를 그대로 믿게 되는 구조라, 틀린 값이 조용히 들어오는 사고가 여기서 납니다. 이 컴퓨터에는 서브에이전트가 저장소에 1개, 사용자 설정에 13개 있습니다.
앞의 셋은 전부 모델에게 글을 읽히는 일입니다. 읽고 안 따를 수 있습니다. 훅은 다릅니다. 정해진 시점에 프로그램이 무조건 돌고, 모델은 그 프로그램을 막을 수단이 없습니다.
훅은 모델을 거치지 않는 자리에 선다
이 컴퓨터의 ~/.claude/settings.json에 걸린 훅이 PreToolUse입니다. Bash 도구를 부를 때마다 먼저 돌아 명령을 갈아 끼웁니다. 같은 일을 「앞에 rtk를 붙여라」라고 규칙 문서에 적어 둘 수도 있습니다. 그러면 모델이 잊는 날이 생깁니다. 훅에는 잊는 날이 없습니다.
훅이 붙을 수 있는 시점은 판의 여러 자리입니다. 세션이 열릴 때(SessionStart), 사람이 무언가를 칠 때(UserPromptSubmit), 도구를 부르기 직전(PreToolUse), 도구가 끝난 뒤(PostToolUse). 앞의 둘은 ②에 글을 얹는 일이고 뒤의 둘은 집행을 가로채는 일입니다. 같은 훅이라도 어느 시점에 거느냐로 성격이 완전히 갈립니다.
MCP(Model Context Protocol)는 도구 목록을 하네스 밖에서 꽂는 규격입니다. 하네스가 기본으로 주는 도구는 파일 읽기·쓰기·셸 실행 정도입니다. 지메일을 읽거나 브라우저를 몰거나 사내 데이터베이스를 뒤지는 일은 하네스 안에 없습니다. MCP 서버를 붙이면 그 서버가 「내가 할 수 있는 일은 이것들이다」를 하네스에 알리고, 하네스가 그 목록을 ②에 얹습니다.
이 컴퓨터에는 fetch · memory · time 셋이 붙어 있습니다. 꽂히는 자리가 둘이라는 것이 중요합니다. 도구 목록은 ②에 실리고 실제 집행은 ④에서 일어나는데, 그 일을 하는 것은 셸이 아닙니다. 하네스가 따로 띄운 그 서버 프로세스입니다.
여기에 스킬과 똑같은 문제가 생깁니다. 도구가 백 개면 그 설명 백 개가 매 요청 ②에 실립니다. 그래서 요즘 하네스는 도구 정의도 두 단계로 나눕니다. 평소에는 이름만 싣고, 필요할 때 검색해서 그 도구의 규격만 불러옵니다. 스킬이 설명 한 줄과 본문을 나눈 것과 같은 처방입니다.
플러그인은 새로운 능력이 아닙니다. 앞의 다섯을 한 상자에 담아 남에게 넘기는 포장입니다. 마켓플레이스라 부르는 것은 깃 저장소 하나이고, 설치는 그 저장소에서 폴더를 받아 오는 일입니다.
같은 플러그인이라도 담긴 것이 다르다
두 상자를 나란히 두면 「플러그인을 깔았다」가 한 가지 뜻이 아님이 보입니다. superpowers는 스킬 14개로 절차만 줍니다. 안 부르면 아무 일도 안 일어납니다. caveman은 훅을 SessionStart · UserPromptSubmit 두 시점에 걸어 둡니다. 세션이 열리는 순간 이미 응답 문체가 바뀌어 있고, 사용자가 무엇을 부른 적은 없습니다.
그래서 플러그인을 받을 때 볼 것은 이름이나 소개가 아닙니다. 상자 안에 hooks가 들었는지입니다. 스킬과 명령만 든 상자는 안 부르면 조용하지만, 훅이 든 상자는 깔린 순간부터 판을 바꿉니다.
실제 배치는 이렇습니다. 스킬 14개 · 서브에이전트 1개 · 슬래시 명령 0개 · 훅 1개 · MCP 서버 3개 · 플러그인 3개.
스킬로 몰린 이유가 있습니다. 이 저장소의 규칙은 대부분 「글을 쓰기 전에 반드시 이 절차를 연다」는 꼴입니다. 시점을 사람이 정하지 않고 모델이 상황을 보고 집어야 합니다. 명령으로 두면 사람이 매번 쳐야 합니다.
그런데 정작 「반드시」를 지키게 하는 것은 스킬 문장이 아닙니다. 검사기 여섯 개(check_notes·check_prose·check_read·check_cite·check_fresh·check_report)가 파이썬으로 돌면서 막습니다. 은유를 주어 자리에 두면 check_prose의 P14가 FAIL을 냅니다. 스킬에 「은유를 주어 자리에 두지 않는다」고 적어만 두었을 때는 두 번 그대로 나갔습니다.
이것이 앞 절들의 요점을 되풀이합니다. 읽히는 글로 두면 안 따르는 날이 생기고, 코드로 옮기면 안 따를 방법이 없습니다. 훅이 하는 일과 검사기가 하는 일이 같은 성격입니다.
부품을 다섯으로 나눈 것은 우리 분류입니다. 공식 문서가 이 다섯을 한 줄에 세워 놓고 견주지 않습니다. 「어디에 꽂히나」로 나눈 것은 이 글의 물음에 맞춘 것이고, 다른 물음으로 보면 다르게 갈립니다.
숫자는 2026-08-24 이 컴퓨터를 센 값입니다. 스킬 14개도 플러그인 3개도 이 설정에서만 참입니다. 다른 사람 컴퓨터에서는 다릅니다. 세는 코드는 scratchpad/agent_facts.py에 있고, 생성기를 다시 돌리면 값이 그때 기준으로 바뀝니다.
판의 번호는 설명을 위한 것입니다. ②·③·④·⑥은 용어 카드의 그림에서 온 번호이고, 하네스 제품마다 실제 단계 수와 순서가 다릅니다. 우리가 하네스 소스를 열어 확인한 것은 아닙니다.
두 단계 로딩의 내부 동작도 확인하지 않았습니다. 스킬 설명 한 줄만 평소에 실린다는 것은 문서에 적힌 설계이고, 우리가 실제 요청 본문을 떠서 센 것이 아닙니다. 3,389자와 82,552자는 파일을 센 값이지 전송된 글자를 잰 값이 아닙니다.
「표를 HBM 밖으로 내보낸다」는 말이 왜 FFN 에는 안 되고 엔그램에는 되는지. 최근 모델들이 메모리 벽을 우회하는 방식이다.
▾엔그램은 최근 토큰 몇 개를 해시해 큰 표에서 행을 꺼내 쓰는 층이다. FFN 과 같이 「표에서 꺼내 잔차 스트림에 더한다」인데 꺼내는 방식이 다르다 — FFN 은 입력을 key 전부와 대 봐야 어디가 걸리는지 알고, 엔그램은 토큰 ID 만으로 읽을 행이 먼저 정해진다. 그 차이가 표를 어느 메모리에 둘 수 있느냐까지 끌고 간다.
핵심 포인트
FFN 과 엔그램 — 21초짜리 한 바퀴
scratchpad/ngram_trace.py.모델이 글자를 이어 붙일 때 한 층에서 무슨 일이 벌어지는지. 「그것은」이 문장 앞의 무엇을 가리키는지 정하는 걸음과, 그 결과를 다듬는 걸음을 나눠 본다.
▾트랜스포머 한 층은 두 걸음이다. 먼저 어텐션이 지금 토큰과 앞선 토큰들을 섞고, 그다음 FFN 이 그 결과를 토큰 하나하나에 따로 먹여 다듬는다. 섞는 걸음은 토큰끼리 서로 보고, 다듬는 걸음은 옆을 안 본다. 이 두 걸음이 층마다 되풀이된다.
핵심 포인트
1막 — 어텐션 (23초짜리 한 바퀴)
2막 — FFN (21초짜리 한 바퀴)
scratchpad/attn_trace.py 와 scratchpad/ffn_trace.py 이고, 거기서 직접 계산한 결과가 모델이 낸 것과 같은지를 굽는 단계에서 검사한다. 가중치 개수는 모델 설정에서 바로 센 것이다.「클로드 코드가 파일을 고쳤다」고 할 때 실제로 파일을 고친 것이 무엇인지. 모델이 낸 글자가 터미널 명령이 되어 돌아오기까지 열두 번을 오간다.
▾하네스는 AI 모델과 실제 컴퓨터 사이에 서서 모델이 뱉은 글자를 실행으로 바꾸는 프로그램이다. 모델은 다음에 올 토큰(한 번에 내놓는 글자 조각)을 이어 붙일 뿐 파일을 열지도 명령을 돌리지도 못한다. 그 글자를 셸에 던지고, 돌아온 로그를 모델이 읽을 크기로 줄여 다시 넣어 준다. 이 일을 맡은 프로그램이 하네스다.
핵심 포인트
pytest라고 써 놓아도 그 자체로는 아무 일도 안 벌어진다. 답이 옳은지 그른지와 무관하게, 모델의 출력은 문서 한 조각이다.EXEC: 같은 접두어나 도구 호출 JSON)를 찾아내 셸과 파일 시스템에 실제로 던진다. 클로드 코드·커서·오픈 인터프리터가 전부 하네스다.하네스가 도는 한 판
Loop (Typescript)
type Msg = { role: "user" | "assistant" | "tool"; text: string };
async function harness(ask: string) {
// 상태는 하네스가 들고 있다. 모델은 요청과 요청 사이에 아무것도 기억하지 않는다
① const state: Msg[] = [{ role: "user", text: RULES + "\n" + ask }];
while (true) {
② const reply = await model.complete(state, TOOLS); // 상태를 통째로 보낸다
state.push({ role: "assistant", text: reply.text });
// 모델이 낸 것은 글자뿐이다. 도구 호출도 실행이 아니라 JSON 한 조각이다
⑪⑫ if (reply.toolCalls.length === 0) return reply.text;
③ for (const call of reply.toolCalls) { // 모델이 적어 보낸 명령
if (risky(call)) await askUser(call); // 지우는 명령 앞에서 멈춘다
④⑤ const log = await runInShell(call); // 셸에 실제로 던진다
⑥ state.push({ role: "tool", text: shrink(log) }); // 실패한 줄만 남긴다
}
if (stuckOnSameError(state)) return "같은 실패가 되풀이돼 멈춥니다";
}
}EXEC:는 설명을 위해 쓴 표시다. 실제 제품은 도구 호출(tool use) 규격에 맞춘 JSON을 주고받는 쪽이 많다. 순서와 역할 분담은 같다. 코드도 뼈대만 남긴 것이다 — 실제 하네스에는 답을 한 글자씩 받아 보여 주는 처리, 끊긴 요청을 다시 부르는 처리, 오래된 대화를 요약해 넣는 처리가 더 붙는다.