콘텐츠로 이동

Claude Code를 잘 쓰는 5가지 원칙

문제

모델이 좋아졌으니 프롬프트 기교는 이제 챙기지 않아도 될 것 같습니다. 그 대신 무엇을 챙겨야 하는지는 알기 어렵습니다.

추천

모델이 좋아져도 결과를 검증하는 요구는 줄지 않습니다. 프롬프트 기교는 덜 필요해집니다. 아래 다섯 원칙은 모델이 아무리 좋아져도 사람이 계속 챙겨야 하는 검증 쪽에 있습니다.

이유

최신 모델은 예전만큼 세심한 프롬프트 설계를 요구하지 않습니다. 정확한 문구, 예시를 여러 개 붙이는 few-shot 구성, 모호한 지시를 명확하게 쪼개는 작업 같은 것의 필요성이 줄었습니다. 같은 지시를 반복해서 다듬거나, 계획 모드를 억지로 빠져나오려고 별도 문구를 넣거나, 관련 파일을 하나하나 @로 지목해 물려주는 습관도 마찬가지입니다. 모델이 스스로 맥락을 찾아내므로 이런 손질이 예전만큼 필요하지 않습니다.

모델이 아무리 좋아져도 줄지 않는 일이 있습니다. 결과를 검증하는 일입니다. 모델은 그럴듯해 보이지만 틀린 코드를 여전히 만들어 낼 수 있고, 스스로 “완료했다”고 말하는 것과 실제로 검증을 통과하는 것은 여전히 다른 일입니다. 좋아진 모델이 없애 주는 노동과 아무리 좋아져도 없애 주지 않는 노동을 구분하는 것이 이 사이트 전체의 논지입니다. 아래 다섯 원칙은 모델이 없애 주지 않는 쪽에 관한 것입니다.

1. 자연어 트리거는 강제가 아닙니다

섹션 제목: “1. 자연어 트리거는 강제가 아닙니다”

“낯선 패턴을 만나면 X를 참조하라” 같은 지시는 에이전트가 선택적으로 적용하고, 동기가 없으면 건너뜁니다. CLAUDE.md에 문장으로 적어둔 트리거는 잊히기 쉽습니다. 반면 훅이나 스킬 게이트처럼 기계적으로 강제되는 형태는 판단이 개입할 여지가 없어 계속 발동합니다. 차이는 트리거의 정교함이 아니라 자연어냐 기계 판정이냐입니다.

CLAUDE.md에 쓴다고 습관이 되지는 않습니다. 강제하려면 훅에서 조건을 기계적으로 판정하거나, 그 작업 스킬 맨 앞에 “착수 전 읽을 것” 고정 목록을 박아 판단할 여지 자체를 없앱니다.

강제되지 않습니다

CLAUDE.md에 “낯선 라이브러리를 만나면 <조회 스킬>을 참고한다”라고만 적어둡니다. 읽을지 말지는 매 순간 모델의 선택으로 남습니다.

강제됩니다

스킬 맨 앞에 “착수 전 읽을 것” 고정 목록을 박아 판단할 여지를 없애거나, PreToolUse 훅에서 조건을 기계적으로 판정해 exit 2로 막습니다.

2. 지침이 가리키는 도구가 보이지 않으면 그 지침은 죽은 코드입니다

섹션 제목: “2. 지침이 가리키는 도구가 보이지 않으면 그 지침은 죽은 코드입니다”

지침을 쓸 때는 그 지침이 참조하는 도구가 실제로 모델에게 보이는지까지 확인해야 합니다. CLAUDE.md에 “예외 없이 /x를 실행한다”라고 써 두고 x가 user-invocable-only로 등록돼 있으면, 그 지침은 구조적으로 실행 불가능한 죽은 코드입니다. 문서만 읽으면 아무 문제 없어 보인다는 점이 더 나쁩니다. 지침도 있고 도구도 있기 때문입니다. 깨지는 지점은 둘 사이의 연결, 즉 모델의 도구 목록에 그 도구가 떠 있는지 여부입니다.

3. 증상이 한쪽만 어긋나면, 하네스 지원 차이부터 의심합니다

섹션 제목: “3. 증상이 한쪽만 어긋나면, 하네스 지원 차이부터 의심합니다”

“저장은 되는데 조회가 안 된다”처럼 한쪽만 동작한다면, 스킬 품질 차이가 아니라 한쪽만 하네스가 지원하고 있다는 뜻인 경우가 많습니다. 저장은 Stop 훅이 세션 종료마다 상기시켜 사람이 직접 타이핑하게 만들고, 조회는 순전히 모델의 판단에 맡겨져 있으면서 override로 차단까지 걸려 있는 경우가 그렇습니다. 이때 저장은 눈에 보이게 동작하고 조회는 아무 표시 없이 실행되지 않습니다. 증상이 대칭이 아니면 스킬을 고치기보다 한쪽 하네스 지원을 먼저 봅니다.

4. 종료 게이트가 없으면, 진입 게이트에서 쓴 계획은 버려지는 문서가 됩니다

섹션 제목: “4. 종료 게이트가 없으면, 진입 게이트에서 쓴 계획은 버려지는 문서가 됩니다”

“착수 전 계획서를 써라”만 있고 종료 게이트가 없으면, plan은 쓰고 나서 버리는 문서가 되기 쉽습니다. 실행이 계획과 얼마나 어긋났는지, 검증 출력이 무엇이었는지, 완료 상태가 어떤지가 레포 문서 어디에도 남지 않고 사람의 기억에만 남는 일이 생길 수 있습니다. 진입 게이트만큼 종료 게이트에도 같은 무게를 줍니다.

5. 검증은 명령 출력의 green으로 판정하고, 검증 도구 자신도 의심합니다

섹션 제목: “5. 검증은 명령 출력의 green으로 판정하고, 검증 도구 자신도 의심합니다”

“완료했습니다”는 검증이 아닙니다. 검증은 명령을 실행한 출력이 green인지로만 판정합니다.

검증 도구 자신이 검증 대상을 깨뜨릴 수 있습니다. 예를 들어 page.screenshot()이 caret: 'hide' 처리 과정에서 폼 요소에 빈 style=""을 남겨 innerHTML 해시 검증을 거짓 실패시킬 수 있습니다. CDP 레벨에서 일어나는 변경이라 MutationObserver로는 잡히지 않습니다. 이런 경우의 판별법은 검증 대상을 제거한 대조군에서 스크린샷만 두 장 찍어 해시를 비교하는 것입니다. 해시가 그래도 달라지면 원인은 코드가 아니라 검증 도구입니다(자세한 진단 절차는 검사는 통과하는데 실제로는 깨져 있을 때 참고).

새 게이트를 추가할 때도 순서가 있습니다. 검사를 추가하고, 실패를 먼저 확인하고, 수정한 뒤, 초록을 확인합니다. 정규식 하나가 어긋나면 검사는 조용히 전부 통과하고, 그 축은 죽은 채로 초록이 됩니다. 고치기 전에 exit 1이 실제로 나는지부터 봅니다.

예시

원칙 1·2를 한 스킬 안에 같이 적용한 예입니다. 자연어 트리거 대신 스킬 본문 맨 앞에 강제 목록을 박고, 그 목록이 가리키는 절차가 실제로 모델에게 열려 있는지까지 스킬 안에서 확인합니다.

## 착수 전 읽을 것 (건너뛰지 말 것)
1. `docs/conventions/*.md`를 먼저 연다.
2. 이 스킬이 참조하는 `/verify` 커맨드가 `skillOverrides`에서
`off`로 막혀 있지 않은지 확인한다 — 막혀 있으면 이 스킬 자체가
죽은 지침이다.

원칙 5는 계획 파일 안에 확인 명령을 박아 넣는 형태로 나타납니다.

## 단계별 확인 명령
- [ ] 구현 후: `npm run build && npm run verify`
- [ ] 위 명령이 실패하면 완료로 치지 않는다.

하지 말 것

CLAUDE.md에 “항상 X 해라” 한 줄 적어두고 끝내기. 자연어 트리거는 실제로는 잊히기 쉽습니다. 강제하려면 훅이거나 스킬 맨 앞 고정 목록이어야 합니다.

지침만 쓰고 그 지침이 가리키는 도구가 모델에게 보이는지 확인하지 않기. user-invocable-only 도구를 “예외 없이 실행”하라고 써 둔 문서는 읽는 사람에게는 문제없어 보이지만 모델에게는 애초에 보이지 않습니다.

“완료했습니다”라는 모델의 말을 검증으로 치기. 명령 출력으로 확인한 green이 아니면 보고이지 검증이 아닙니다. 검증 도구 자신도 실패의 원인일 수 있다는 것까지 검토해야 완료입니다.