CPN 한국어 자습서 · Claude Code in Action
2 · 직접 해보기
Custom commands
Claude Code에서 / 를 입력하면 기본 명령들이 뜹니다. 여기에 직접 만든 명령을 더할 수 있습니다. .claude/commands/ 폴더에 <이름>.md 파일을 두면 그 파일 이름이 곧 /이름 명령이 되고, $ARGUMENTS 자리표시자로 인자까지 받을 수 있습니다.
Stephen Grider · Anthropic 기술 스태프
Claude Code를 실행하고 슬래시(/)를 입력하면 Claude Code에 기본으로 들어 있는 여러 명령이 보입니다. 이 기본 명령들에 더해, 직접 만든 커스텀 명령도 손쉽게 추가할 수 있습니다. 커스텀 명령은 자주 반복하게 되는 작업을 자동화하는 데 유용합니다. 만드는 법을 예로 보여 드리죠.
프로젝트 디렉터리 안에서 .claude 폴더를 찾습니다. 그 안에 commands라는 새 디렉터리를 만들고, 다시 그 안에 audit.md라는 새 파일을 만듭니다. 우리가 만드는 파일 이름 — 여기서는 audit — 이 곧 나중에 실행할 명령의 이름이 됩니다.
이 명령의 목표는 이 프로젝트에 설치된 여러 의존성을 점검(audit)하고, 취약점이 있으면 업데이트한 뒤, 테스트를 돌려 아무것도 깨지지 않았는지 확인하는 것입니다.
명령 파일을 만들었으면 Claude Code를 재시작합니다. 재시작을 잊지 마세요. 다시 열고 /audit을 입력하면 방금 만든 명령이 표시됩니다. 이걸 실행하면 우리가 시킨 그대로 합니다 — 명령을 돌려 취약한 패키지가 있는지 보고, 필요하면 고치고, 테스트를 실행합니다.
명령은 인자도 받을 수 있습니다. 예를 들어 보죠. write-test라는 또 다른 명령을 만듭니다. 이 명령을 실행할 때마다, 프로젝트 안의 아주 특정한 파일에 대한 테스트를 만들고 싶습니다. 명령 텍스트 안에 $ARGUMENTS라는 자리표시자를 넣습니다. 명령을 실행할 때 파일 경로를 넘기면, 그 경로가 $ARGUMENTS 자리에 끼워집니다.
이제 Claude Code를 다시 재시작하고 write-test 명령을 실행할 수 있습니다. 분명히 해 두자면, 넘기는 인자가 꼭 파일 경로일 필요는 없습니다. 원하는 어떤 문자열이든 넘길 수 있습니다. 그래서 어떤 특정 폴더의 파일에 대한 테스트를 가볍게 요청하면서, Claude에게 어디를 봐야 할지 약간의 방향만 줄 수도 있습니다.
이 장에서 배우는 것What you'll learn
약 1분/ 를 누르면 보이는 기본 명령에 내 명령을 더한다
.claude/commands/<이름>.md — 파일 이름이 곧 명령 이름
예) audit.md — 의존성 점검 → 취약점 수정 → 테스트
명령 파일을 만들면 Claude Code 재시작이 필수
$ARGUMENTS 자리표시자로 인자를 받는다
인자는 파일 경로뿐 아니라 임의의 문자열도 가능
Claude Code에서 / 를 누르면 기본 명령 목록이 뜹니다. 여기에 직접 만든 명령을 더할 수 있습니다. 자주 반복하는 작업 — 예컨대 의존성 점검 — 을 한 번에 돌리고 싶을 때 제격입니다. 만드는 자리는 프로젝트 안의 .claude/commands/ 폴더입니다.
프로젝트 구조
명령 실행
파일 이름이 곧 명령 이름입니다. $ARGUMENTS 가 든 명령은 실행할 때 넘긴 값이 그 자리에 끼워집니다 — 파일 경로든, 그냥 던지는 한 문장이든 됩니다.
.claude/commands/ 안에 audit.md 를 만들면, 그 파일 이름이 곧 명령 이름(/audit)이 됩니다. 파일 본문에는 Claude가 할 일을 평범한 말로 적습니다.
# /audit 을 실행하면 Claude 가 이 내용을 그대로 수행합니다.
이 프로젝트에 설치된 의존성을 모두 점검하세요.
취약점이 있으면 해당 패키지를 업데이트하고,
마지막으로 테스트를 실행해 아무것도 깨지지 않았는지 확인하세요.명령 파일을 만들었으면 Claude Code를 재시작해야 인식됩니다. 다시 열고 /audit 을 입력하면 방금 만든 명령이 보이고, 실행하면 의존성 점검 → 취약점 수정 → 테스트까지 진행합니다.
명령은 인자도 받습니다. 본문에 $ARGUMENTS 자리표시자를 넣어 두면, 명령을 실행할 때 넘긴 값이 그 자리에 끼워집니다.
# /write-test <값> 으로 실행하면 넘긴 값이 $ARGUMENTS 에 들어갑니다. $ARGUMENTS 에 해당하는 파일에 대한 테스트를 작성하세요. 엣지 케이스를 포함하고, 작성 후 테스트를 실행해 통과를 확인하세요.
재시작한 뒤 인자를 붙여 실행합니다. 인자는 파일 경로일 필요가 없습니다 — 임의의 문자열이면 됩니다.
> /write-test src/auth.ts # 경로를 넘기면 그 파일을 테스트 > /write-test payments 폴더의 환불 로직 # 그냥 문장으로 방향만 줘도 됨
.claude/commands/<이름>.md 를 만들면 파일 이름이 곧 /명령.$ARGUMENTS 로 인자를 받고, 인자는 임의 문자열도 가능.Q1커스텀 명령 /audit 을 만들려면 어떤 파일을 두나요?
.claude/commands/ 안의 audit.md 파일이 곧 /audit 명령이 됩니다. 파일 이름이 명령 이름입니다.
Q2명령 파일을 새로 만든 직후 해야 할 일은?
새 명령은 재시작 후에 인식됩니다. 강사도 “재시작을 잊지 마라”고 강조합니다.
Q3$ARGUMENTS 에 대한 설명으로 옳은 것은?
$ARGUMENTS 자리에 실행 시 넘긴 값이 끼워집니다. 파일 경로뿐 아니라 임의의 문자열도 됩니다.
명령 파일 하나가 어떻게 슬래시 명령이 되고, 실행할 때 넘긴 인자가 $ARGUMENTS 자리에 끼워지는지 직접 확인합니다.
// 커스텀 명령 확장기 — .claude/commands/<이름>.md 파일 하나가 곧 /이름 슬래시 명령이 된다.
// 실행할 때 넘긴 인자는 본문의 $ARGUMENTS 자리표시자에 그대로 끼워진다.
// 파일 경로에서 명령 이름을 뽑는다: .claude/commands/audit.md → /audit
function commandName(path) {
const file = path.split("/").pop(); // audit.md
return "/" + file.replace(/\.md$/, ""); // /audit
}
// 본문의 $ARGUMENTS 를 넘긴 인자로 치환해, Claude가 받을 최종 프롬프트를 만든다.
function expand(body, args) {
const usesArgs = body.indexOf("$ARGUMENTS") >= 0;
return { prompt: body.split("$ARGUMENTS").join(args || ""), usesArgs: usesArgs };
}
// ── 여기서부터 직접 고쳐 보세요 ──
// .claude/commands/ 아래에 둔 명령 파일들(경로 → 본문).
const files = {
".claude/commands/audit.md":
"의존성을 점검하고, 취약점이 있으면 업데이트한 뒤, 테스트를 실행해 확인하세요.",
".claude/commands/write-test.md":
"다음 대상에 대한 단위 테스트를 작성하세요: $ARGUMENTS\n엣지 케이스를 포함하고, 작성 후 테스트를 돌려 통과를 확인하세요.",
};
// 실행할 명령과 인자(인자는 파일 경로든 그냥 문장이든 됩니다).
const runs = [
{ cmd: "/audit", args: "" },
{ cmd: "/write-test", args: "src/auth.ts" },
{ cmd: "/write-test", args: "payments 폴더의 환불 로직" },
{ cmd: "/deploy", args: "" }, // 파일 없음 — 등록되지 않은 명령
];
// 파일 목록으로 명령 등록부를 만든다(파일 이름이 곧 명령 이름).
const registry = {};
Object.keys(files).forEach(function (path) { registry[commandName(path)] = files[path]; });
console.log("등록된 명령: " + Object.keys(registry).join(" · "));
console.log("");
runs.forEach(function (run) {
const body = registry[run.cmd];
if (!body) {
console.log(run.cmd + " → 그런 명령이 없습니다(파일이 없거나 재시작 전).\n");
return;
}
const r = expand(body, run.args);
const note = r.usesArgs
? (run.args ? "인자 \"" + run.args + "\" 끼움" : "$ARGUMENTS 있으나 인자 없음 → 빈 값")
: "인자 없이 실행";
console.log(run.cmd + (run.args ? " " + run.args : "") + " [" + note + "]");
console.log("Claude가 받는 프롬프트 ↓");
r.prompt.split("\n").forEach(function (line) { console.log(" " + line); });
console.log("");
});
명령으로 작업을 자동화했으니, 이제 외부 도구를 Claude Code에 붙여 능력을 넓혀 봅니다. → Claude Code의 MCP 서버
전 코스는 계속 무료입니다. 등록하면 이 코스의 남은 16개 레슨을 끝까지 읽을 수 있습니다.
이미 등록하셨다면 그때 쓰신 이메일을 넣어 주세요.