$0/$1/$2 로 여러 인수 다루기

위치 인수 $0, $1, $2 는 커맨드에 넘긴 값을 공백 기준으로 나눠 순서대로 받는 자리표시자이며 공식 문서 기준 $0 이 첫 번째 값입니다. @ 파일 참조와 조합하는 법, 인수가 모자랄 때의 동작, 공백이 든 값을 따옴표로 묶는 법을 다룹니다.

9분 갱신

앞 편의 $ARGUMENTS는 값을 통째로 받았습니다. 그런데 회의록 커맨드에 "전사 파일"과 "출력 형식"을 함께 넘기고 싶으면 두 값을 본문의 다른 자리에 넣어야 합니다. 이때 쓰는 것이 위치 인수입니다. 넘긴 값을 공백 기준으로 나눠 첫 값은 $0, 둘째 값은 $1로 받습니다.

이 글은 커스텀 커맨드 코스의 마지막 편입니다. 위치 인수가 어떻게 전개되는지, 언제 $ARGUMENTS 대신 써야 하는지, @ 파일 참조와 어떻게 묶는지, 값이 모자라거나 공백이 섞였을 때 어떻게 되는지를 다루고, 마지막에 우리 팀이 쓰는 PR 리뷰 준비 커맨드로 마무리합니다.

핵심 요약

  • 공식 문서 기준 위치 인수는 0부터 셉니다. $0이 첫 번째, $1이 두 번째 값입니다.
  • $0은 $ARGUMENTS[0]의 줄임 표기입니다. 둘 다 쓸 수 있습니다.
  • 공백이 든 값은 따옴표로 묶어야 한 자리로 들어갑니다. 셸과 같은 규칙입니다.
  • 넘기지 않은 자리는 빈칸이 아니라 $2 글자가 그대로 남습니다(2.1.246 실측).
  • @$0처럼 자리표시자 앞에 @를 붙이면 그 경로의 파일 내용이 프롬프트에 들어갑니다.

위치 인수는 어떻게 전개되나

공식 문서의 문자열 치환 표는 $ARGUMENTS[N]을 "0 기반 인덱스로 특정 인수에 액세스"한다고 정의하고, $N을 그 약자로 둡니다. 원문 예시는 명확합니다. "$0은 첫 번째 인수, $1은 두 번째 인수." 셸 스크립트의 $1이 첫 인수인 것과 달라서 처음엔 헷갈리지만, Claude Code는 0부터 셉니다.

$0 컴포넌트를 $1 에서 $2 로 옮깁니다. 기존 동작과 테스트는 그대로 유지합니다.

/migrate SearchBar React Vue를 실행하면 $0은 SearchBar, $1은 React, $2는 Vue로 바뀝니다. 같은 본문을 $ARGUMENTS[0], $ARGUMENTS[1], $ARGUMENTS[2]로 적어도 결과는 같습니다. 우리 수업에서는 짧은 $N을 기본으로 쓰되, 본문에 금액 표기처럼 $ 뒤에 숫자가 오는 문장이 섞이면 \$1.00으로 이스케이프한다고 함께 가르칩니다.

공식 문서에는 한 가지 더 편한 방법이 있습니다. 프론트매터에 arguments: [file, format]처럼 이름을 선언하면 본문에서 $file, $format으로 받을 수 있습니다. 이름이 순서대로 자리에 대응하므로 $0, $1과 같은 값입니다. 자리 번호를 외우기 싫은 팀원에게는 이 방식이 읽기 쉽습니다.

언제 $ARGUMENTS 대신 위치 인수를 쓰나

기준은 "값이 본문의 서로 다른 자리에 들어가야 하는가"입니다. 에러 메시지 한 줄처럼 통째로 한 곳에 넣는 값은 $ARGUMENTS가 맞습니다. 반대로 "어떤 파일을, 어떤 형식으로, 어디에" 같이 역할이 다른 값 두세 개를 받는 커맨드는 위치 인수가 맞습니다.

우리 자동화 예로 나누면 이렇습니다.

커맨드 인수 선택
/debug:where <에러 한 줄> 통째로 하나 $ARGUMENTS
/fix-issue <번호> 값 하나 어느 쪽이든
/meeting:summary <전사파일> <형식> 역할이 다른 둘 $0, $1
/report:daily <날짜> <프로젝트> 역할이 다른 둘 $0, $1

값이 하나뿐이면 굳이 위치 인수를 쓸 이유가 없고, 셋을 넘어가면 순서를 외우기 어려워지니 arguments 이름 선언이나 커맨드 분리를 고려합니다.

실전 예: @ 파일 참조와 조합하기

대화형 모드 문서에 따르면 프롬프트에서 @를 치면 파일 경로 자동 완성이 뜨고, @경로는 그 파일을 대화에 끌어옵니다. 커맨드 본문 안에서도 @$0처럼 자리표시자와 붙여 쓸 수 있습니다. 우리가 2.1.246에서 @$0을 넣은 커맨드에 note.txt를 넘기고 파일 읽기 도구를 모두 막은 채 실행했더니, Claude가 파일 첫 줄을 정확히 답했습니다. 치환이 끝난 @note.txt가 파일 참조로 해석되어 내용이 프롬프트에 들어갔다는 뜻입니다.

이 조합으로 3주차 회의록 커맨드를 완성합니다.

~/.claude/commands/meeting/summary.md

---
description: 전사 파일을 회의록 4항목으로 정리. 형식은 md 또는 notion
argument-hint: [전사파일] [형식: md|notion]
arguments: [file, format]
allowed-tools: Read
---
전사 원문: @$file

위 전사를 회의록으로 정리합니다. 출력 형식: $format

항목:
1. 참석자
2. 논의 내용
3. 결정 사항 (없으면 "결정 사항 없음")
4. 할 일 (담당자와 기한)

규칙:
1. 전사에 없는 내용을 추측해 채우지 않습니다.
2. 고객 실명은 첫 글자만 남기고 가립니다.
3. $format 이 notion 이면 노션에 붙여 넣기 좋은 제목 없는 불릿 구조로 씁니다.
4. $file 이나 $format 이 비어 있거나 "$file" 글자 그대로 남아 있으면 값을 먼저 묻습니다.

/meeting:summary transcripts/0827-상담.txt notion으로 부르면 $file은 경로, $format은 notion이 됩니다. 4번 규칙이 왜 저렇게 생겼는지는 다음 절에서 설명합니다.

인수가 부족하면 어떻게 되나

공식 문서는 이 경우를 따로 설명하지 않아 우리가 직접 확인했습니다. Claude Code 2.1.246에서 $0, $1, $2를 쓰는 커맨드에 값 하나만 넘기고 렌더링된 프롬프트를 살펴보니, $0은 값으로 바뀌었지만 $1과 $2는 빈칸이 아니라 $1, $2 글자 그대로 남아 있었습니다. 즉 Claude는 "둘째 값이 비었다"가 아니라 "$1이라는 이상한 토큰이 있다"를 보게 됩니다. 반면 arguments로 이름을 선언한 $format 같은 자리는 같은 조건에서 빈 문자열이 되었습니다. 어느 쪽이든 커맨드가 값을 추측하게 두면 안 됩니다.

그래서 우리 수업의 방어 규칙은 두 가지입니다.

  1. 본문 끝에 "자리표시자가 글자 그대로 남아 있으면 값을 먼저 묻는다"는 지시를 넣습니다. 위 예시의 4번 규칙이 그것입니다.
  2. argument-hint로 필요한 값의 개수와 순서를 목록에 보여 줘서 애초에 빠뜨리지 않게 합니다.

정지 규칙은 증거여야 한다는 원칙이 여기서도 적용됩니다. "인수가 부족할 것 같다"가 아니라 "$1이 그대로 남아 있다"가 멈추는 근거입니다.

스페이스가 든 값은 어떻게 넘기나

공식 문서는 "인덱싱된 인수는 shell 스타일 인용을 사용하므로 다중 단어 값을 따옴표로 감싸서 단일 인수로 전달"한다고 안내합니다. 예시 그대로 /my-skill "hello world" second는 $0이 hello world, $1이 second가 됩니다. 우리 실측에서도 note.txt "hello world"를 넘기자 $1이 따옴표 없는 hello world로 들어왔습니다.

실무에서 이 규칙이 필요한 곳은 한글 파일명과 제목입니다.

/meeting:summary "transcripts/0827 김대표 상담.txt" md
/report:daily 2026-08-27 "BizPlan CRM"

따옴표를 빠뜨리면 0827이 $0, 김대표가 $1로 갈라져 들어갑니다. 반면 $ARGUMENTS는 따옴표까지 포함한 원문 그대로를 받으므로, 통째로 받는 커맨드에서는 따옴표를 붙일 필요가 없습니다.

응용 예: PR 리뷰 준비 커맨드

마지막으로 위치 인수, @ 참조, 사전 승인 도구를 한데 모은 커맨드입니다. 우리 CRM 레포에서 PR을 올리기 전에 돌리는 점검용으로, 공식 문서의 ! 명령 삽입도 함께 씁니다. 공식 문서에 따르면 본문의 !`명령`은 Claude가 보기 전에 실행되어 그 출력으로 바뀝니다.

.claude/commands/pr/prep.md

---
description: PR 번호와 기준 브랜치를 받아 리뷰 전 점검 보고서를 만든다
argument-hint: [PR번호] [기준브랜치] [체크리스트파일]
allowed-tools: Bash(gh pr *) Bash(git diff *) Read
disable-model-invocation: true
---
PR #$0 을 $1 기준으로 점검합니다.

변경 파일: !`gh pr diff $0 --name-only`
변경 내용: !`gh pr diff $0`
팀 체크리스트: @$2

순서:
1. 체크리스트 항목별로 통과/실패/해당없음을 표로 정리합니다.
2. .env, 키, 비밀번호가 diff에 있으면 실패로 표시하고 맨 위에 올립니다.
3. 결제 금액을 클라이언트가 정하는 코드가 있으면 실패로 표시합니다.
4. 테스트 실행 로그가 PR 설명에 없으면 "증거 없음"으로 적습니다.
5. 값이 비어 있거나 $0, $1, $2 가 글자 그대로 남아 있으면 먼저 묻습니다.

/pr:prep 232 develop docs/pr-checklist.md로 부르면 $0은 232, $1은 develop, $2는 체크리스트 경로가 되고, @$2가 그 파일 내용을 끌어옵니다. 2번과 3번 규칙은 우리 CRM 레포 CLAUDE.md의 절대 규칙("결제 금액은 서버가 정한다")을 커맨드 안의 정지 규칙으로 옮긴 것입니다.

정리

  • 위치 인수는 0부터이며 $0이 첫 값, $ARGUMENTS[0]과 같습니다.
  • 역할이 다른 값 두셋을 받을 때 위치 인수, 통째로 받을 때 $ARGUMENTS를 씁니다.
  • @$0처럼 붙이면 넘긴 경로의 파일 내용이 프롬프트에 들어갑니다(2.1.246 실측).
  • 빠진 자리는 $2 글자 그대로 남으므로 본문에 "그대로 남아 있으면 묻는다"를 넣습니다.
  • 공백이 든 값은 따옴표로 묶어 한 자리로 넘깁니다.

자주 묻는 질문

$0 이 첫 번째 인수인가요?

네. 공식 문서는 $ARGUMENTS[N]을 0 기반 인덱스로 정의하고 "$0은 첫 번째 인수, $1은 두 번째 인수"라고 예시합니다. 셸 스크립트의 $1이 첫 인수인 것과 다르니 커맨드를 옮겨 적을 때 한 칸씩 당겨야 합니다.

인수를 덜 넘기면 어떻게 되나요?

2.1.246에서 확인한 결과 넘기지 않은 자리는 빈 문자열이 아니라 $1, $2 글자 그대로 남습니다. 본문에 "자리표시자가 글자 그대로 남아 있으면 값을 먼저 묻는다"는 지시를 넣고, argument-hint로 필요한 값의 개수를 목록에 보여 주는 것이 예방책입니다.

스페이스가 든 값은 어떻게 넘기나요?

따옴표로 묶습니다. 공식 문서 예시대로 "hello world" second는 $0이 hello world, $1이 second가 됩니다. 한글 파일명이나 프로젝트 이름처럼 공백이 들어가는 값은 항상 따옴표를 붙이는 습관을 들이면 됩니다.

$ARGUMENTS 와 위치 인수 중 무엇을 써야 하나요?

값이 하나이거나 문장처럼 통째로 쓰이면 $ARGUMENTS, 파일과 형식처럼 역할이 다른 값을 본문의 다른 자리에 넣어야 하면 위치 인수입니다. 값이 셋을 넘어 순서가 헷갈리면 프론트매터 arguments로 이름을 선언해 $file, $format처럼 받는 편이 읽기 쉽습니다.

커스텀 커맨드위치 인수$0@ 파일 참조PR 리뷰

팀에 클로드코드를 도입하려면 실제 업무에 맞춘 설계가 필요합니다. 무료 상담 신청 →