Skip to content

필사 모드: Claude Code Skills 직접 만들기 — SKILL.md 한 장으로 에이전트의 새 도구를 빚는 실전 핸즈온 (2026)

한국어
0%
정확도 0%
💡 왼쪽 원문을 읽으면서 오른쪽에 따라 써보세요. Tab 키로 힌트를 받을 수 있습니다.
원문 렌더가 준비되기 전까지 텍스트 가이드로 표시합니다.

프롤로그 — "이 절차 또 붙여넣고 있네?"라는 순간

Claude Code를 한두 달 쓰다 보면 누구든 같은 깨달음에 도달한다.

매번 같은 지시를 채팅에 붙여넣고 있다. "PR 만들 때는 conventional commits 따라줘", "릴리스 노트는 우리 팀 포맷으로", "테스트 돌리고 빌드 통과한 다음에만 머지해줘". 처음 한두 번은 컨텍스트에 넣어두면 되지만, 같은 절차를 다섯 번째 반복하는 순간 의문이 든다 — **이걸 매번 입력하는 게 맞나?**

CLAUDE.md에 넣으면 되지 않냐고? 부분적으로 맞다. 그런데 CLAUDE.md는 전역으로 항상 로드되는 컨텍스트라, 모든 작업에 절차가 따라붙는다. 토큰이 아깝고, 무엇보다 **상황과 무관한 절차가 모델의 주의를 분산시킨다**. PR 만들 때만 필요한 70줄짜리 체크리스트가 단순한 typo 수정 세션에도 매번 메모리에 올라간다.

Anthropic은 2025년 10월에 이 문제에 답을 냈다. **Agent Skills.** 이름은 거창해 보이지만 본질은 단순하다 — 디렉터리 하나에 SKILL.md 한 장. 프론트매터에 description을 쓰면 모델이 "지금 이 작업에 이 Skill이 어울리는지" 스스로 판단해서 invoke한다. 항상 로드되는 게 아니라, **필요할 때만 메모리에 올라간다.** 그리고 같은 형식을 git에 체크인하면 팀 전체가 공유할 수 있다.

2025년 12월 Anthropic은 한 발 더 나아갔다. Skills를 **오픈 표준**으로 풀어버렸다. 같은 SKILL.md 포맷이 Claude.ai, Claude Code, Agent SDK, API 어디서나 동작하고, OpenAI Codex CLI와 일부 서드파티 도구도 같은 스펙을 채택했다. 사실상 Markdown + YAML로 표현되는 "에이전트 능력 단위"의 공용어가 된 셈이다.

2026년 5월 현재, 잘 만든 팀은 30~50개의 Skill 카탈로그를 가지고 있다. 배포는 git에 push하거나 plugin marketplace를 통한다. 이 글은 Skill을 처음 만드는 사람을 위해, 정확히 무엇이 어떻게 동작하는지를 펼친다 — SKILL.md의 모든 필드, 호출 모델, 디렉터리 레이아웃, 패키징, 그리고 release-notes-from-git-log Skill을 처음부터 끝까지 만들어보는 핸즈온까지.

1장 · Skill이란 정확히 무엇인가

한 줄 정의: **YAML 프론트매터 + 마크다운 지시문을 담은 SKILL.md 한 장과, 그 옆에 선택적으로 놓이는 스크립트/레퍼런스 파일들의 묶음.**

가장 작은 Skill은 이렇게 생겼다.

name: pr-summary

description: 현재 PR의 변경사항을 요약하고 위험 요소를 표시한다. 사용자가 PR을 리뷰하거나 머지 전 점검을 요청할 때 사용.

작업

현재 PR diff를 읽고 다음 형식으로 요약하라:

1. 변경의 의도 (2~3문장)

2. 새로 추가된 의존성/설정

3. 위험 영역 (오류 처리 누락, 하드코딩, 테스트 갱신 필요 등)

마지막에 "머지해도 좋음 / 검토 필요 / 보류 권장" 한 줄로 결론을 낸다.

이게 전부다. `~/.claude/skills/pr-summary/SKILL.md`에 저장하면, 다음 세션부터 사용자가 "PR 한번 봐줘" 같은 말을 할 때 Claude가 description을 보고 자동으로 invoke한다. 아니면 사용자가 직접 `/pr-summary`라고 입력해도 같은 결과.

Skill이 풀어주는 것

- **반복되는 절차의 캡슐화.** 같은 지시를 매번 붙여넣지 않는다.

- **선택적 로딩.** description만 항상 카탈로그에 보이고, 본문은 invoke 시점에만 컨텍스트에 들어간다 — 토큰이 싸다.

- **이름으로 명시 호출.** `/skill-name`으로 사용자가 직접 트리거할 수도 있다.

- **공유 가능성.** git에 체크인 → 팀 전체가 같은 절차로 동작.

Skill이 아닌 것

- **MCP 서버가 아니다.** 외부 프로세스도 아니고, JSON-RPC도 없다. 그냥 텍스트 파일이다.

- **모델 fine-tune이 아니다.** 모델은 그대로, 컨텍스트 주입 방식만 바뀐다.

- **하드코딩된 함수가 아니다.** Skill 본문은 자연어 지시문이고, 모델이 해석한다. 그래서 같은 Skill이 매번 약간 다르게 행동할 수 있다.

Claude Code 안에서의 위치

Claude Code에는 원래부터 몇 가지 확장 메커니즘이 있었다 — Custom Commands(슬래시 명령), Subagents(`.claude/agents/`), MCP 서버, Plugins, CLAUDE.md. Skills는 **Custom Commands를 흡수**하면서 등장했고, 지금은 가장 자주 쓰이는 확장 단위가 됐다. `.claude/commands/foo.md`와 `.claude/skills/foo/SKILL.md`가 둘 다 `/foo`를 만든다 — 같은 슬롯에서 경쟁한다. Skill 쪽이 더 풍부한 기능(디렉터리, 자동 invoke, 스크립트 포함)을 가지므로 신규 개발은 Skill로 한다.

2장 · SKILL.md 포맷 — 모든 필드를 펼친다

가장 자주 헷갈리는 부분이라 모든 필드를 한 번에 정리한다. 모든 필드는 선택이지만, **description만은 사실상 필수**다.

name: my-skill

description: 무엇을 하는 Skill인지, 그리고 언제 사용해야 하는지 한 문장으로.

when_to_use: description으로 부족할 때, 추가 트리거 문구나 예시 요청을 적는다.

argument-hint: "[issue-number]"

arguments: [issue, branch]

disable-model-invocation: false

user-invocable: true

allowed-tools: Read Grep Bash(git *)

model: inherit

effort: high

context: fork

agent: Explore

paths: ["src/**/*.py", "tests/**/*.py"]

shell: bash

hooks:

PreToolUse:

- matcher: "Bash"

command: "echo running bash"

본문은 마크다운으로 자유롭게 작성. 이 본문이 invoke 시점에 통째로 컨텍스트에 들어간다.

각 필드의 의미를 풀어두면:

| 필드 | 의미 | 자주 쓰나 |

| --- | --- | --- |

| `name` | 표시명. 생략하면 디렉터리명. 소문자·숫자·하이픈, 64자 이내. | 가끔 |

| `description` | 무엇을 하고 언제 쓰는지. **모델이 invoke를 결정할 때 가장 중요한 신호.** | 거의 항상 |

| `when_to_use` | description에 못 담은 트리거 문구·예시. | 가끔 |

| `argument-hint` | 자동완성에 보이는 인자 힌트. `[name]` 같은 표시. | 종종 |

| `arguments` | 명명된 위치 인자. `arguments: [a, b]`면 본문에서 `$a`, `$b`로 참조. | 종종 |

| `disable-model-invocation` | true면 사용자만 invoke 가능. 부작용 있는 명령(`/deploy`, `/commit`)에 권장. | 자주 |

| `user-invocable` | false면 `/` 메뉴에서 숨김. 백그라운드 지식용. | 가끔 |

| `allowed-tools` | 이 Skill이 활성일 때 자동 승인되는 도구 목록. | 자주 |

| `model` | 이 Skill 동작 동안 쓸 모델. `inherit`이 안전. | 가끔 |

| `effort` | reasoning effort 수준 (`low`~`max`). 정밀 작업에는 `high` 이상. | 가끔 |

| `context: fork` | 별도 서브에이전트 컨텍스트에서 실행. 대화 히스토리 격리. | 종종 |

| `agent` | `context: fork`일 때 어떤 서브에이전트 유형을 쓸지 (`Explore`, `Plan`, `general-purpose`). | 종종 |

| `paths` | 특정 파일 패턴에서 작업할 때만 자동 invoke 후보가 됨. | 가끔 |

| `shell` | `bash` 또는 `powershell`. Windows에서만 의미. | 거의 안 씀 |

| `hooks` | 이 Skill 동안만 활성화되는 hook 들. | 가끔 |

description 작성법 — 가장 중요한 한 줄

description은 사용자 발화와 매칭되는 **검색 키**다. 좋은 description의 특징:

1. **무엇을 하는지** — "PR 변경사항을 요약하고 위험을 표시한다"

2. **언제 사용하는지** — "사용자가 변경사항을 묻거나, 커밋 메시지를 요청하거나, diff 리뷰를 부탁할 때"

3. **사용자가 실제로 쓸 만한 키워드** — "PR", "변경사항", "diff", "리뷰"

나쁜 예: `description: 좋은 도구입니다`. 모델이 언제 써야 할지 모른다.

좋은 예: `description: 코드를 conventional commit 규칙에 맞춰 커밋한다. 사용자가 커밋, commit, 변경사항 저장을 요청할 때 사용.`

description + when_to_use를 합쳐 1,536자까지 카탈로그에 노출된다. 그 안쪽에 **핵심 키워드를 앞쪽에 배치**해야 길이 제한이 걸려도 잘려 나가지 않는다.

문자열 치환 — `$ARGUMENTS`와 친구들

본문 안에서 동적 값을 끼워 넣을 수 있는 자리표시자가 몇 가지 있다.

- `$ARGUMENTS` — invoke 시 따라온 인자 전체.

- `$ARGUMENTS[0]` / `$0` — 첫 번째 위치 인자.

- `$name` — `arguments: [name]`으로 선언된 명명 인자.

- `${CLAUDE_SESSION_ID}` — 현재 세션 ID.

- `${CLAUDE_EFFORT}` — 현재 effort 수준.

- `${CLAUDE_SKILL_DIR}` — 이 SKILL.md가 위치한 디렉터리. 스크립트 경로 만들 때 필수.

동적 컨텍스트 주입 — 셸 명령을 미리 실행

본문에 백틱-느낌표-백틱 문법(`!`로 시작하는 인라인 코드)을 쓰면, Claude가 보기 **전에** 셸이 실행되고 그 출력이 본문에 인라인된다. 멀티라인은 `!`를 붙인 코드 펜스를 쓴다.

현재 변경사항

!`git diff HEAD`

PR 정보

gh pr view --json title,body,labels

gh pr diff --name-only

작업

위 정보로 릴리스 노트를 작성하라.

이건 매우 강력하다 — 모델이 "diff를 좀 보여줘"라고 도구를 부르지 않아도 되고, **항상 사실 기반**으로 시작한다. invoke 시점의 실제 상태가 본문에 들어가기 때문에.

3장 · 호출 모델 — Claude는 언제 Skill을 부르는가

가장 자주 묻는 질문. 답은 두 가지 경로다.

**경로 1: 사용자가 명시적으로 invoke.** `/skill-name [args]`. 메뉴에서 골라도 같다. 이 경로는 항상 동작한다.

**경로 2: 모델이 자동으로 invoke.** 세션 시작 시 모든 Skill의 `name + description (+ when_to_use)`이 모델 컨텍스트에 카탈로그로 들어간다. 사용자가 어떤 발화를 했을 때, 모델은 카탈로그를 훑고 매칭되는 Skill이 있으면 그걸 트리거한다.

자동 invoke는 다음 조건을 만족해야 한다:

1. Skill에 `disable-model-invocation: true`가 없어야 함.

2. description이 사용자 발화와 의미적으로 매칭되어야 함.

3. `paths`가 설정된 경우, 현재 작업 파일이 패턴에 맞아야 함.

"Skill이 안 불려요" 디버깅

겪을 가능성이 가장 높은 문제다. 체크리스트:

- description에 사용자가 쓸 법한 키워드가 있는가?

- `What skills are available?` 명령으로 카탈로그에 보이는가?

- 카탈로그가 budget overflow로 잘렸는가? `/doctor`로 확인.

- 충돌하는 다른 Skill이 더 매칭 점수가 높지는 않은가?

- 이름이 `.claude/commands/`의 옛 명령과 겹치지 않는가?

"Skill이 너무 자주 불려요"

반대 문제도 흔하다. description이 너무 일반적이면 모든 발화에 후보로 떠오른다.

- description을 더 구체적으로.

- 부작용 있는 명령은 `disable-model-invocation: true`로 막아라.

- `paths`로 트리거 범위를 좁혀라.

4장 · 디렉터리 레이아웃과 거주 위치

Skill은 디렉터리 하나가 단위다. 거주 위치는 네 곳.

| 위치 | 경로 | 적용 범위 |

| --- | --- | --- |

| Enterprise | managed settings로 배포 | 조직 전체 |

| Personal | `~/.claude/skills/<name>/SKILL.md` | 내 모든 프로젝트 |

| Project | `.claude/skills/<name>/SKILL.md` | 이 프로젝트만 |

| Plugin | `<plugin>/skills/<name>/SKILL.md` | 이 plugin이 활성인 곳 |

이름이 겹치면 Enterprise > Personal > Project 순서. Plugin Skill은 `plugin-name:skill-name` 네임스페이스로 격리되어 충돌 안 함.

디렉터리 안의 파일들

가장 작은 Skill은 SKILL.md 한 파일이다. 하지만 본문이 길어지거나 도우미 자원이 필요하면 같은 디렉터리에 더 둘 수 있다.

release-notes/

├── SKILL.md # 필수. 진입점.

├── template.md # 출력 템플릿. SKILL.md가 참조.

├── examples/

│ ├── good.md # 예시 출력 1

│ └── bad.md # 예시 출력 2 (반면교사)

├── references/

│ └── changelog-spec.md # Keep a Changelog 규약 등 상세 레퍼런스

└── scripts/

└── collect.sh # SKILL.md에서 호출하는 셸 스크립트

SKILL.md 본문에서 다른 파일을 참조하려면 명시적으로 적어줘야 모델이 알아본다.

추가 자료

- 출력 형식 전체는 `template.md` 참조.

- 좋은 예시는 `examples/good.md`, 피해야 할 예시는 `examples/bad.md`.

- 변경 로그 규약 상세는 `references/changelog-spec.md`.

데이터 수집

bash ${CLAUDE_SKILL_DIR}/scripts/collect.sh

핵심: **SKILL.md는 500줄 이내**로 유지하고, 길어지면 references/로 빼라. SKILL.md 본문은 invoke되면 통째로 컨텍스트에 들어가서 세션 내내 머문다 — 매 턴 토큰 비용이다.

5장 · 핸즈온 — `release-notes-from-git-log` Skill 만들기

이제 실제로 하나를 만들어본다. 목표는 명료하다 — **마지막 태그 이후의 git 로그를 보고 Keep a Changelog 형식의 릴리스 노트를 생성하는 Skill**. 단순한 PR 요약보다 한 단계 깊이가 있어, 인자 처리·동적 컨텍스트·도우미 스크립트·템플릿까지 한 번에 다룬다.

1단계: 디렉터리 생성

mkdir -p ~/.claude/skills/release-notes/{scripts,references,examples}

cd ~/.claude/skills/release-notes

2단계: 도우미 스크립트 — 마지막 태그 이후의 커밋 수집

`scripts/collect.sh`에 저장한다.

#!/usr/bin/env bash

set -euo pipefail

LAST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "")

if [[ -z "$LAST_TAG" ]]; then

echo "## 마지막 태그 없음 — 전체 로그"

git log --pretty=format:"- %h %s (%an)" --no-merges

else

echo "## 마지막 태그: $LAST_TAG"

echo ""

echo "## 그 이후의 커밋"

git log "${LAST_TAG}..HEAD" --pretty=format:"- %h %s (%an)" --no-merges

echo ""

echo "## 그 이후의 머지 커밋"

git log "${LAST_TAG}..HEAD" --merges --pretty=format:"- %h %s"

echo ""

echo "## 변경된 파일 (요약)"

git diff --stat "${LAST_TAG}..HEAD" | tail -1

fi

실행 권한을 준다.

chmod +x scripts/collect.sh

3단계: 출력 템플릿

`references/template.md`에 저장한다. Keep a Changelog 1.1 규약에 맞춘 골격이다.

[VERSION] - YYYY-MM-DD

Added

- 새 기능, 외부 가시적 추가만.

Changed

- 기존 기능의 변경. 호환 깨지지 않는 한 여기.

Deprecated

- 다음 메이저에서 제거 예정.

Removed

- 이번에 제거됨.

Fixed

- 버그 수정. 영향 범위 한 줄.

Security

- 보안 패치. CVE 있으면 링크.

4단계: 좋은 예시 / 나쁜 예시

`examples/good.md`.

[1.4.0] - 2026-05-10

Added

- OAuth2 디바이스 플로우 지원 (#234).

- 환경 변수 `RATE_LIMIT_PER_MIN`으로 토큰 버킷 조절.

Fixed

- 동시 1만 연결에서 발생하던 메모리 누수 (#241).

- 윈도우에서 경로 구분자 처리 오류.

Security

- `axios` 1.7.0으로 업그레이드 (CVE-2025-12345).

`examples/bad.md`.

v1.4.0

- 이것저것 수정함.

- 버그 잡음.

- 성능 좋아짐.

- 리팩토링.

- 코드 정리.

5단계: SKILL.md — 본체

이제 진입점을 적는다. 위에서 만든 자원을 모두 묶는다.

name: release-notes

description: 마지막 git 태그 이후의 커밋과 머지를 분석해 Keep a Changelog 형식의 릴리스 노트를 작성한다. 사용자가 릴리스 노트, 체인지로그, changelog, release notes 작성을 요청할 때 사용.

when_to_use: "다음 릴리스 노트를 써줘", "이번 버전 changelog 좀 만들어줘", "v1.5.0 릴리스 노트", 같은 발화에서 트리거.

argument-hint: "[version]"

arguments: [version]

allowed-tools: Bash(git *) Read

effort: high

Release Notes — Keep a Changelog

목표 버전: `$version` (지정 없으면 적절한 다음 버전을 SemVer 규칙으로 추정).

입력 데이터

bash ${CLAUDE_SKILL_DIR}/scripts/collect.sh

출력 형식

`${CLAUDE_SKILL_DIR}/references/template.md`의 골격을 따른다. 카테고리는

Added / Changed / Deprecated / Removed / Fixed / Security 여섯 개로 한정.

좋은 예시: `${CLAUDE_SKILL_DIR}/examples/good.md`

피해야 할 예시: `${CLAUDE_SKILL_DIR}/examples/bad.md`

분류 규칙

1. conventional commit prefix가 있으면 우선 신뢰:

- `feat:` → Added

- `fix:` → Fixed

- `refactor:` / `perf:` / `chore:` → 사용자 가시 변경이 있을 때만 Changed

- `security:` / `sec:` → Security

2. prefix가 없거나 애매하면 커밋 메시지와 변경 통계로 추정.

3. 단순 리팩토링·테스트·CI 변경은 **사용자 가시 영향이 없으면 제외**.

톤과 길이

- 각 항목 한 줄. 사용자가 무엇이 달라졌는지 즉시 안다.

- 내부 함수명·파일 경로는 쓰지 않는다.

- 이슈/PR 번호가 있으면 끝에 `(#123)`로.

- 마크다운 ASCII만. 이모지 금지.

결과 검증

작성 후 다음을 확인:

- 모든 머지 커밋이 어딘가에 반영됐는가?

- "기타", "잡다한 변경" 같은 카테고리를 만들지 않았는가?

- Security 항목에 CVE 링크가 빠지지 않았는가?

문제가 있으면 사용자에게 "이 커밋을 어디로 분류할까요?"라고 묻고 진행한다.

6단계: 테스트

세션을 시작하고 두 가지 방식 다 시도한다.

cd /path/to/your/repo

claude

1) 자동 invoke

> v1.5.0 릴리스 노트 좀 만들어줘

2) 명시 invoke

> /release-notes 1.5.0

두 경로 모두 같은 결과로 이어져야 한다. 안 불리면 description에 키워드가 부족한 것이고, 너무 일반적으로 불리면 description을 좁혀라.

7단계: 팀에 공유

개인용으로 확인했으면 프로젝트 또는 plugin으로 옮긴다.

프로젝트 단위 공유

mv ~/.claude/skills/release-notes /path/to/repo/.claude/skills/

git add .claude/skills/release-notes

git commit -m "skill: add release-notes generator (Keep a Changelog)"

이제 같은 리포에서 누가 Claude Code를 켜든 이 Skill을 쓸 수 있다.

6장 · 패키징과 배포

Skill을 다른 사람과 공유하는 길은 세 갈래다.

6-1. Git에 그대로 — 가장 단순

`.claude/skills/`를 리포에 체크인. clone → claude 실행이면 끝. 이게 90% 케이스에 답이다.

장점: 별도 인프라 필요 없음, 버전 관리 자동, 코드 리뷰 자연스럽게 됨.

단점: 다른 리포에서 쓰려면 복붙. plugin이나 dotfiles 동기화로 보완.

6-2. Plugin — 여러 Skill·subagent·hook을 함께 묶을 때

Claude Code Plugin은 Skill·subagent·hook·command를 한 패키지로 묶는 단위다. `<plugin>/skills/<name>/SKILL.md` 구조로 plugin 안에 Skill을 둔다. plugin은 marketplace를 통해 설치된다.

언제 plugin인가:

- 관련된 Skill 5개 이상을 한 묶음으로 배포할 때.

- Skill에 더해 custom subagent나 hook도 같이 필요할 때.

- 외부 사용자가 한 번의 설치 명령으로 받게 하고 싶을 때.

6-3. Anthropic Skills Marketplace — 공개 카탈로그

2025년 12월에 공개된 파트너 빌트 Skill 디렉터리. Atlassian, Figma, Canva, Stripe, Notion, Zapier 등이 자사 워크플로우용 Skill을 올려뒀다. 자기 Skill을 공개 배포하고 싶으면 이 경로를 검토.

보안 고려

`allowed-tools`로 권한을 미리 승인하는 Skill을 git에 체크인하면, 그 리포를 clone하는 모두에게 같은 권한이 부여된다. Claude Code는 처음 신뢰할 때 workspace trust 다이얼로그를 띄우니까 한 번은 검토 기회가 있지만, **남의 Skill을 무비판적으로 활성화하지 말 것**. SKILL.md 본문, scripts/, allowed-tools를 반드시 읽어본다.

7장 · Skills vs MCP vs Subagent vs Plugin — 결정 트리

가장 자주 헷갈리는 부분이다. 네 가지 메커니즘은 겹치지 않는 영역이 있다.

| 메커니즘 | 무엇 | 언제 |

| --- | --- | --- |

| **Skill** | YAML+마크다운 한 파일. invoke 시 컨텍스트에 인라인. | 절차·체크리스트·반복 지시. 코드는 셸 스크립트 정도. |

| **MCP 서버** | 외부 프로세스, JSON-RPC, 도구를 노출. | 외부 API·DB·툴체인과 상호작용. 다른 에이전트도 같은 도구를 쓰게 하고 싶을 때. |

| **Subagent** | 자체 시스템 프롬프트를 가진 격리된 컨텍스트. | 컨텍스트 격리가 필요한 큰 작업(코드베이스 탐색, 깊은 리서치). |

| **Plugin** | 위 셋을 묶는 배포 단위. | 다수의 Skill/Subagent/Hook를 한 패키지로. |

결정 트리

질문 1: **외부 시스템과 통신해야 하는가?** (DB, 외부 API, 파일 시스템의 특수 도구)

- 예 → **MCP 서버**. 새 도구가 필요하면 MCP. Skill은 도구를 만드는 게 아니라 기존 도구를 어떻게 쓸지 지시한다.

- 아니오 → 질문 2.

질문 2: **별도 컨텍스트에서 격리 실행이 필요한가?** (긴 탐색, 별도 권한)

- 예 → **Subagent**, 또는 `context: fork`가 붙은 Skill.

- 아니오 → 질문 3.

질문 3: **여러 Skill·Subagent·Hook를 한 묶음으로 배포해야 하는가?**

- 예 → **Plugin**. 단일 Skill이라도 marketplace 배포면 plugin.

- 아니오 → **Skill**.

구체 예시로 보면

| 상황 | 선택 |

| --- | --- |

| Jira 티켓 자동 조회·업데이트 | MCP (Jira API 필요) |

| PR 요약 절차 | Skill |

| 깊은 코드베이스 탐색 | Subagent (or Skill with `context: fork`) |

| "릴리스 워크플로우" 패키지 (Skill 3개 + hook 2개) | Plugin |

| 매 커밋마다 자동 실행될 검사 | Hook (Skill 아님) |

핵심: **Skill은 도구를 만드는 게 아니라 도구 사용법을 가르치는 것.** "새 도구가 필요해" = MCP. "있는 도구를 어떻게 쓸지 매번 다시 설명하기 싫어" = Skill.

8장 · 고급 패턴

8-1. `context: fork`로 서브에이전트에 위임

큰 작업은 메인 대화 컨텍스트를 오염시킨다. `context: fork`를 쓰면 Skill 본문이 새 격리된 컨텍스트의 task가 되고, 결과만 메인으로 돌아온다.

name: deep-research

description: 주어진 주제를 코드베이스에서 깊게 조사. 사용자가 "이 기능 어디서 구현됐어?", "왜 이렇게 짜여졌어?"를 물을 때.

context: fork

agent: Explore

$ARGUMENTS를 코드베이스에서 깊게 조사:

1. Glob과 Grep으로 관련 파일을 찾는다.

2. 핵심 파일을 읽고 호출 그래프를 만든다.

3. 발견을 구체적인 파일:줄 참조와 함께 요약한다.

장점: 메인 대화에 200개 파일 전체가 들어오지 않는다. 단점: 결과만 받으니, 중간에 사람이 끼어들 여지가 적다.

8-2. `allowed-tools`로 마찰 줄이기

매번 "Bash 실행해도 될까요?"를 묻지 않게 하려면 미리 승인한다. 단, **범위를 좁게**.

allowed-tools: Bash(git add *) Bash(git commit *) Bash(git status *)

`Bash(*)`로 모든 셸을 미리 승인하지 마라. Skill이 의도치 않게 위험한 명령을 실행할 여지가 생긴다.

8-3. `paths`로 자동 invoke 범위 좁히기

특정 파일에서만 의미 있는 Skill은 `paths`로 트리거를 좁힌다.

paths: ["src/**/*.py", "tests/**/*.py"]

작업 중 파일이 패턴에 안 맞으면 모델 자동 invoke 후보에서 빠진다. 사용자 직접 invoke는 여전히 가능.

8-4. 동적 컨텍스트로 사실 기반 시작

가장 강력한 패턴 중 하나. invoke 시점에 셸 명령이 실행되고 출력이 본문에 인라인된다.

환경

node --version

npm --version

git status --short

최근 변경

!`git log --oneline -10`

작업

위 환경에서 ...

모델이 "환경 좀 알려줘"라고 도구 호출을 하지 않아도 되고, 항상 실제 데이터로 시작한다.

8-5. hooks로 결정론적 끼어들기

Skill 활성 동안만 동작하는 hook를 frontmatter에 둘 수 있다. PostToolUse로 lint를 강제하거나, PreToolUse로 위험 명령을 차단하거나.

8-6. ultrathink로 깊은 추론 한 번

본문 어디든 `ultrathink`라는 단어를 넣으면 그 Skill 동안 모델이 더 깊은 추론 모드로 들어간다. 복잡한 의사결정이 끼는 Skill(예: 마이그레이션 계획)에서 유용. 모든 Skill에 남발하면 비용·지연 폭증.

9장 · 실제 예시 — 사람들이 만들고 있는 Skill들

2026년 5월 기준, 자주 보이는 패턴들.

**PR Summary** — diff와 PR 본문을 받아 한 화면 요약 + 위험 표시. 가장 흔한 Skill.

**Conventional Commit** — `disable-model-invocation: true`. `/commit`으로만 트리거. 스테이지 → 메시지 작성 → 커밋. `allowed-tools: Bash(git add *) Bash(git commit *)`.

**Release Notes** — 위에서 만든 그것. 회사마다 포맷이 달라서 직접 만들기 좋은 종류.

**Code Review Checklist** — 자사 코딩 규약에 맞춘 체크리스트. references/에 보안·성능·접근성 가이드를 두고 SKILL.md가 진입점.

**Runbook Executor** — 운영 절차 자동화. "배포 롤백해줘"가 들어오면 정확한 순서로 헬름 차트 롤백, 슬랙 알림, 메모리 정리.

**Bug Triage** — 이슈 본문을 읽고 라벨·우선순위·담당자 추천. GitHub MCP와 짝.

**Migration Guide** — 코드베이스 일부를 React 16 → 19로 옮기는 등. `arguments: [from, to, target]`.

**Content Drafting** — 블로그 초안, 트윗 스레드, 변경 공지. 회사 톤 가이드를 references/에.

**Security Review** — 새 의존성·새 API 엔드포인트가 들어왔을 때 체크리스트. CWE 매핑.

**Database Migration** — 스키마 변경 절차. dry-run → diff → 승인 → 배포. PreToolUse hook로 prod 보호.

**Postmortem Drafter** — 인시던트 후 회고 초안. 5 whys, blameless 톤.

**Docs Sync** — 코드 변경 후 README, API 문서, 변경 로그를 함께 갱신. `paths` 활용.

**Cost Reporter** — 마지막 PR이 클라우드 비용에 어떤 영향을 주는지 추정. terraform plan + 가격 표.

이 목록은 단지 흔히 보이는 모양일 뿐, **본인 팀 절차를 캡슐화한 Skill이 가장 가치 있다**. "이걸 또 입력하고 있네?"가 떠오를 때마다 새 Skill 후보가 하나 생긴 셈이다.

10장 · 안티패턴 — 흔히 망가지는 방식

수십 개의 Skill을 만들고 본 패턴들.

1. **description이 모호하다.** "좋은 도구입니다" — 모델이 언제 부를지 못 정한다.

2. **description이 너무 일반적이다.** "코드를 작성한다" — 거의 모든 발화에 매칭되어 매번 invoke된다.

3. **본문이 500줄을 넘는다.** 매 턴 토큰 비용. references/로 빼라.

4. **`allowed-tools: Bash(*)`.** 모든 셸 명령을 미리 승인. 사고 나기 좋다. 범위 좁혀라.

5. **부작용 있는 명령에 `disable-model-invocation: false`.** 모델이 멋대로 `/deploy`를 부른다. 부작용 있는 건 항상 사용자만.

6. **CLAUDE.md와 중복.** 같은 지시를 양쪽에 적으면 충돌·혼선. CLAUDE.md는 항상 적용되는 사실, Skill은 상황별 절차.

7. **MCP로 풀어야 할 걸 Skill로 푼다.** 외부 API 호출 로직을 마크다운 지시로 우회. MCP 서버를 만들어라.

8. **테스트가 없다.** Skill도 코드다. 자동 invoke와 명시 invoke 둘 다 통과하는지 매번 확인.

9. **버전 관리 안 함.** Skill을 바꾸면 동작이 바뀐다. git 히스토리가 답.

10. **이름 충돌.** Personal·Project·Plugin에 같은 이름 Skill. 우선순위 규칙은 있지만 헷갈린다. 충돌하지 않게 이름을 짜라.

11장 · Skill 콘텐츠 생명주기 — 토큰 측면

이건 자주 빠뜨리는 디테일이다. Skill이 invoke되면 본문이 **한 메시지로 컨텍스트에 들어가고, 세션 끝까지 머문다**. 매 턴 다시 읽지 않는다.

오토 컴팩션이 일어나면 가장 최근에 invoke된 Skill들이 일부 유지된다. 각 Skill의 첫 5,000 토큰까지 보존되고, 모든 Skill 합쳐서 25,000 토큰 예산 안에서 가장 최근 것부터 채워진다. 옛 Skill은 컴팩션 후 사라질 수 있다.

영향이 사라진 것 같으면 — 사실 본문은 거의 항상 컨텍스트에 있고, 모델이 다른 접근을 선택했을 가능성이 더 크다. description과 본문 첫 줄에 행동 강제 표현(must, never)을 더 넣어보거나, hook로 결정론적으로 강제.

에필로그 — Skill을 의식하라

Skill은 "에이전트가 무엇을 할 수 있나"를 한 줄씩 늘리는 가장 싼 방법이다. 새 모델을 기다릴 필요 없고, 새 MCP 서버를 만들 필요도 없다. 절차를 한 디렉터리에 적고 git에 push하면, 다음 세션부터 팀 전체가 그 절차를 공유한다.

9개 항목 체크리스트

1. description은 무엇·언제·키워드를 모두 담았는가?

2. 본문 500줄 이내, 긴 자료는 references/로 뺐는가?

3. 부작용 있는 명령은 `disable-model-invocation: true`인가?

4. `allowed-tools`는 좁게 잡았는가?

5. 동적 컨텍스트(`!`)로 사실 기반 시작이 되어 있는가?

6. 자동 invoke와 명시 invoke 둘 다 테스트했는가?

7. 이름이 다른 Skill·command와 충돌하지 않는가?

8. Personal/Project/Plugin 중 어디 둘지 의식적으로 골랐는가?

9. 비슷한 능력을 MCP·Subagent로 해결해야 하는 건 아닌가?

안티패턴 빠른 회상

- 모호한 description / 과한 description / 길게 늘어진 본문 / 넓은 allowed-tools / 자동 invoke된 위험 명령 / CLAUDE.md 중복 / MCP로 풀어야 할 걸 Skill로 / 테스트 없음 / 버전 관리 없음 / 이름 충돌.

다음 글 예고

다음 글에서는 **MCP 서버를 직접 처음부터 만들기 — TypeScript SDK로 30분 만에 사내 API 노출하기**를 다룬다. Skill로 절차를 캡슐화했다면, MCP로는 진짜 새 도구를 만들 차례다.

그 다음은 **Plugin marketplace에 자기 plugin 올리기**, 그리고 **Claude Code Hooks 패턴북** — 결정론적 안전망을 깔아 에이전트에게 더 큰 권한을 넘기는 방법.

이 글에서 만든 release-notes Skill처럼, 작은 한 장의 마크다운이 팀 절차를 영원히 바꾼다. "이거 또 입력하고 있네"가 떠오를 때마다, 그게 다음 Skill의 후보다.

참고 / References

- [Anthropic — Extend Claude with skills (Claude Code 공식 문서)](https://code.claude.com/docs/en/skills)

- [GitHub — anthropics/skills (공식 예제 Skill 리포)](https://github.com/anthropics/skills)

- [Anthropic — The Complete Guide to Building Skills for Claude (PDF)](https://resources.anthropic.com/hubfs/The-Complete-Guide-to-Building-Skill-for-Claude.pdf)

- [Agent Skills 오픈 표준 사이트](https://agentskills.io)

- [Anthropic — Subagents (Claude Code)](https://code.claude.com/docs/en/sub-agents)

- [Anthropic — Plugins (Claude Code)](https://code.claude.com/docs/en/plugins)

- [Anthropic — Hooks (Claude Code)](https://code.claude.com/docs/en/hooks)

- [Anthropic — Memory / CLAUDE.md](https://code.claude.com/docs/en/memory)

- [Anthropic — Permissions](https://code.claude.com/docs/en/permissions)

- [The New Stack — Agent Skills: Anthropic's Next Bid to Define AI Standards](https://thenewstack.io/agent-skills-anthropics-next-bid-to-define-ai-standards/)

- [VentureBeat — Anthropic launches enterprise Agent Skills and opens the standard](https://venturebeat.com/technology/anthropic-launches-enterprise-agent-skills-and-opens-the-standard)

- [Keep a Changelog 1.1 규약](https://keepachangelog.com/en/1.1.0/)

- [Model Context Protocol 공식 사이트](https://modelcontextprotocol.io/)

현재 단락 (1/321)

Claude Code를 한두 달 쓰다 보면 누구든 같은 깨달음에 도달한다.

작성 글자: 0원문 글자: 15,661작성 단락: 0/321