같은 모양, 다른 맛
크리스마스 쿠키를 만드는 걸 상상해보세요.
별 모양 쿠키 커터가 하나 있어요. 이 커터로 반죽을 누르면 별 모양 쿠키가 나와요. 근데 재미있는 건, 같은 별 모양이라도:
- 초콜릿 반죽으로 누르면 → 초콜릿 별 쿠키
- 바닐라 반죽으로 누르면 → 바닐라 별 쿠키
- 딸기 반죽으로 누르면 → 딸기 별 쿠키
같은 틀에서 다른 맛이 나오는 거예요.
AI 스킬에서도 이런 일이 자주 있어요. 예를 들어, "코드 리뷰" 스킬을 만들었는데:
- JavaScript 코드 리뷰 스킬이 필요하고
- Python 코드 리뷰 스킬이 필요하고
- Go 코드 리뷰 스킬도 필요해요
리뷰하는 과정은 같은데 (코드 스타일 확인, 보안 체크, 성능 검토), 세부 내용만 다른 거예요 (JavaScript는 var 대신 const를 쓰라, Python은 PEP 8을 따르라...).
이런 상황에서 SKILL.md를 3개 따로 만들면? 비효율적이고, 공통 부분을 고칠 때 3개를 다 수정해야 하죠.
여기서 등장하는 게 바로 템플릿이에요.
SKILL.md.tmpl이 뭔가요?
SKILL.md.tmpl은 SKILL.md를 자동으로 생성해주는 틀이에요. "tmpl"은 template(템플릿)의 줄임말이에요.
핵심은 변수(variable)예요. 변수는 "나중에 채워 넣을 빈칸"이에요.
빈칸 채우기
여러분 어릴 때 이런 문제 풀어봤죠?
"나는 ___를 좋아합니다. ___는 맛있기 때문입니다."
빈칸에 "피자"를 넣으면 → "나는 피자를 좋아합니다. 피자는 맛있기 때문입니다."
빈칸에 "치킨"을 넣으면 → "나는 치킨을 좋아합니다. 치킨은 맛있기 때문입니다."
SKILL.md.tmpl도 이거예요. {{LANGUAGE}} 같은 빈칸을 만들어두고, 나중에 실제 값으로 채우는 거예요.
실제로 보면 이렇게 생겼어요:
---
description: "{{LANGUAGE}} 코드 리뷰를 해주는 스킬"
---
# {{LANGUAGE}} 코드 리뷰 스킬
당신은 {{LANGUAGE}} 전문 시니어 개발자입니다.
{{LANGUAGE}}의 베스트 프랙티스와 일반적인 실수 패턴을
잘 알고 있으며, 건설적인 코드 리뷰를 제공합니다.
{{LANGUAGE}}가 빈칸이에요. 여기에 "JavaScript"를 넣으면 JavaScript 코드 리뷰 스킬이 되고, "Python"을 넣으면 Python 코드 리뷰 스킬이 돼요.
실전: 언어별 코드 리뷰 스킬 템플릿
직접 만들어볼게요. 완전한 코드 리뷰 템플릿을 하나 작성해봅시다.
SKILL.md.tmpl:
---
description: "{{LANGUAGE}} 코드를 리뷰하고 개선점을 제안하는 스킬"
allowed-tools: ["Read", "Glob", "Grep"]
---
# {{LANGUAGE}} 코드 리뷰 스킬
당신은 {{EXPERIENCE_YEARS}}년 경력의 {{LANGUAGE}} 시니어 개발자입니다.
{{LANGUAGE}} 커뮤니티의 베스트 프랙티스를 잘 알고 있으며,
코드 품질 향상에 열정적입니다.
## 리뷰 체크리스트
1. **코드 스타일**: {{STYLE_GUIDE}}를 따르고 있는가?
2. **보안**: 일반적인 보안 취약점이 없는가?
3. **성능**: 비효율적인 패턴이 없는가?
4. **가독성**: 다른 개발자가 이해하기 쉬운가?
5. **테스트**: 테스트 커버리지가 충분한가?
## {{LANGUAGE}} 특화 검토 항목
{{LANGUAGE_SPECIFIC_CHECKS}}
## 출력 형식
```
## 코드 리뷰 결과
### 👍 잘한 점
- ...
### 🔧 개선 제안 (중요도 순)
1. [심각] ...
2. [보통] ...
3. [사소] ...
### 📚 학습 포인트
- ...
```
## 톤
- 건설적이고 교육적으로
- "이건 틀렸다"보다 "이렇게 하면 더 좋을 수 있다"
- 좋은 점을 반드시 먼저 언급
이 템플릿에서 변수는 다음과 같아요:
{{LANGUAGE}}— 프로그래밍 언어 이름{{EXPERIENCE_YEARS}}— 경력 연수{{STYLE_GUIDE}}— 해당 언어의 스타일 가이드{{LANGUAGE_SPECIFIC_CHECKS}}— 언어별 특화 검토 항목
JavaScript 버전으로 변환하면:
{{LANGUAGE}} → JavaScript
{{EXPERIENCE_YEARS}} → 10
{{STYLE_GUIDE}} → Airbnb JavaScript Style Guide
{{LANGUAGE_SPECIFIC_CHECKS}} →
- var 대신 const/let 사용하고 있는가?
- 콜백 헬 대신 async/await를 사용하고 있는가?
- === 대신 == 를 잘못 사용한 곳은 없는가?
- 미사용 import가 남아있지 않은가?
- TypeScript 타입 정의가 any로 방치된 곳은 없는가?
Python 버전으로 변환하면:
{{LANGUAGE}} → Python
{{EXPERIENCE_YEARS}} → 10
{{STYLE_GUIDE}} → PEP 8
{{LANGUAGE_SPECIFIC_CHECKS}} →
- PEP 8 스타일을 따르고 있는가?
- type hint가 적절히 사용되고 있는가?
- list comprehension을 활용할 수 있는 for 루프는 없는가?
- with 문으로 리소스 관리를 하고 있는가?
- f-string을 일관되게 사용하고 있는가?
한 템플릿에서 두 가지 다른 스킬이 나왔어요! 공통 구조(리뷰 체크리스트, 출력 형식, 톤)는 그대로 유지하면서, 언어별 세부 사항만 바뀐 거죠.
시스템이 제공하는 변수들
직접 정의한 변수 외에, 시스템이 자동으로 제공하는 변수들도 있어요. 이 변수들은 스킬이 실행되는 환경에 따라 자동으로 값이 채워져요.
유용한 시스템 변수
{{PREAMBLE}} — 기본 시스템 프리앰블. Claude Code가 기본적으로 사용하는 설정이에요. 이걸 포함하면 스킬이 기본 동작을 유지하면서 추가 기능만 얹을 수 있어요.
{{BASE_BRANCH_DETECT}} — Git의 기본 브랜치를 자동 감지해요. main인지 master인지 develop인지 — 프로젝트마다 다르니까, 자동 감지가 편하죠.
예를 들어, Git 작업을 하는 스킬에서:
---
description: "PR을 리뷰하고 머지하는 스킬"
allowed-tools: ["Bash", "Read", "Glob", "Grep"]
---
{{PREAMBLE}}
# PR 리뷰 & 머지 스킬
기본 브랜치: {{BASE_BRANCH_DETECT}}
PR을 리뷰할 때는 {{BASE_BRANCH_DETECT}} 브랜치와의
차이를 비교하여 분석하세요.
{{BASE_BRANCH_DETECT}} 덕분에, 프로젝트의 기본 브랜치가 main이든 master이든 상관없이 자동으로 맞춰져요.
솔직한 이야기: 대부분은 아직 안 써도 돼요
여기서 솔직하게 말씀드릴게요.
대부분의 초보자는 템플릿이 필요 없어요.
SKILL.md 직접 작성하는 것만으로 충분해요. 템플릿은 다음과 같은 상황에서 진가를 발휘해요:
- 비슷한 구조의 스킬을 5개 이상 만들어야 할 때
- 팀에서 스킬을 표준화하고 싶을 때
- 환경에 따라 스킬이 자동으로 달라져야 할 때 (예: 브랜치 이름)
그러니까 지금 당장 "템플릿을 써야 해!"라고 부담 갖지 마세요. "아, 이런 게 있구나. 나중에 필요하면 쓰면 되겠다" 정도면 충분해요.
프로 팁
처음에는 SKILL.md를 직접 작성하세요. 그러다 "어, 이 스킬이랑 저 스킬이랑 구조가 90% 같은데?"라는 생각이 들면 — 그때가 템플릿을 도입할 타이밍이에요. 필요를 느끼기 전에 도입하면, 오히려 복잡해져요.
정리: 언제 뭘 쓸까?
선택 가이드
SKILL.md 직접 작성:
- 스킬이 1-2개일 때
- 각 스킬이 독립적일 때
- 초보자일 때 (지금!)
SKILL.md.tmpl 사용:
- 같은 구조의 스킬이 3개 이상 필요할 때
- 팀에서 스킬 구조를 통일하고 싶을 때
- 환경 변수(브랜치 이름 등)를 자동으로 넣고 싶을 때