
Claude Code Skills의 안티패턴 — 「왜 Skills인가」부터 다시 생각하는 설계의 함정
요약
Claude Code의 Skills 메커니즘이 가진 설계 의도와 구조적 안티패턴을 분석합니다. 컨텍스트 윈도우의 비용과 정밀도 문제를 해결하기 위한 '단계적 개시' 원칙을 바탕으로, 잘못된 Skill 설계가 초래하는 기술 부채를 다룹니다.
핵심 포인트
- Skills는 컨텍스트 윈도우 비용과 정밀도 저하를 막기 위한 설계임
- 단계적 개시(Progressive Disclosure) 원칙이 핵심 메커니즘임
- 무분별한 Skill 사용은 작동 후 인지하기 어려운 기술 부채를 생성함
- 효율적인 Skill 설계를 위해 컨텍스트 경제학 관점의 접근이 필요함
- Claude Code Skills는 편리하지만, 1개월 정도 운용하다 보면 「성공 사례의 이면」에서 조용히 쌓여가는 부채가 보이기 시작합니다.
- 안티패턴을 단순히 나열하는 것이 아니라, 애초에 「왜 Skills라는 메커니즘이 탄생했는가」, 「왜 안티패턴이 구조적으로 발생하는가」를 먼저 파악하면 대응 우선순위가 달라집니다.
- 핵심이 되는 사상은 「단계적 개시 (progressive disclosure)」이며, 컨텍스트 윈도우 (context window)의 경제학 관점에서 역산해 보면 비대화, 다중 책임, 모호한 발화 조건이 왜 문제인지 하나의 선으로 연결됩니다.
Claude Code에 Skills가 등장한 이후, X나 Zenn에서는 「편리한 Skill 20선」이나 「자기 개선 루프 구축」 등 성공 사례 소개가 급격히 늘어났습니다. 저 또한 1개월 정도 업무와 개인 프로젝트에서 Skills를 운용해 오며, 개발 방식 자체가 바뀌었다고 느끼고 있습니다.
한편, 운용이 진행됨에 따라 「이것은 설계를 잘못했다」라고 생각되는 장면도 늘어났습니다. Skills는 CLAUDE.md와 달리 필요할 때만 로드되기 때문에 비용을 억제할 수 있지만, 그렇기 때문에 「작동하고 나면 알아차리기 어려운 부채」가 조용히 쌓여갑니다.
다만, 안티패턴을 그냥 나열하기만 하면 「주의합시다」라는 말로 끝나버려, 막상 자신의 Skill을 수정할 때 우선순위를 정하기 어렵다고 느꼈습니다. 그래서 이 기사에서는 먼저 **「왜 Skills라는 메커니즘이 탄생했는가」, 「왜 안티패턴이 구조적으로 발생하는가」**라는 배경부터 시작하여, 그 위에서 각 안티패턴이 「왜 문제를 일으키는지」라는 메커니즘을 통해 설명해 보겠습니다.
앞으로 Skills를 사내에 전개하려는 테크 리드(Tech Lead)나, Skills를 만들기 시작한 지 1~3개월 된 분들에게 참고가 된다면 좋겠습니다. 참고로 여기서 다루는 내용은 어디까지나 제 운용 과정에서 보인 경향일 뿐이며, 프로젝트의 규모나 이용 형태에 따라 해당하지 않는 케이스도 있을 것이므로 그 점은 감안하여 읽어 주시기 바랍니다.
안티패턴 이야기를 하기 전에, 조금 돌아가는 것처럼 보일 수도 있지만 Skills가 어떤 과제를 해결하기 위해 탄생했는지 정리하겠습니다. 이 부분을 공유해 두면, 후반부의 안티패턴이 「왜 문제인지」를 더 쉽게 이해할 수 있을 것이라 생각합니다.
LLM을 사용한 개발에서 가장 먼저 부딪히는 제약은 컨텍스트 윈도우 (context window)입니다. 모델이 한 번에 읽을 수 있는 정보량에는 상한이 있으며, 읽게 하는 정보에는 대략 다음 두 가지 비용이 발생합니다.
금전적 비용— 입력 토큰 (input token)에 비례하여 과금됩니다. 매 턴마다 동일한 대량의 전제를 읽게 한다면 그만큼 비용이 쌓여갑니다 -
정밀도의 비용— 이 부분이 간과되기 쉬운데, 컨텍스트에 정보를 가득 채울수록 모델이 「지금 이 순간 정말로 필요한 정보」를 추출하는 정밀도는 떨어지는 경향이 있습니다. 긴 문맥 속에서 중요한 지시가 묻혀버리는, 이른바 주의력 희박화 (attention dilution)와 같은 현상입니다
즉 「일단 전부 프롬프트나 CLAUDE.md에 써두면 된다」라는 접근 방식은 비용과 정밀도 양면에서 수지가 맞지 않게 되기 쉽다는 뜻입니다. 항상 전부를 읽게 하는 설계는 지식이 늘어나면 늘어날수록 불리해지는 것입니다.
여기서 등장하는 발상이 「단계적 개시 (progressive disclosure)」입니다. 한마디로 말하면 **「필요해졌을 때, 필요한 만큼만 지식을 읽어 들인다」**라는 설계 사상입니다.
Skills는 이 사상을 상당히 충실하게 구현한 메커니즘이라고 느낍니다. 구체적으로는 대략 다음과 같은 다단계 구조로 되어 있습니다.
항상 보이는 것은— Skill의 본체는 로드되지 않은 상태이며, 「이 Skill은 무엇을 위한 것이고 언제 사용하는가」라는 헤더 정보인 description (및 when_to_use)만 Claude에게 보입니다 -
발화하면 SKILL.md 본체가 읽힘— 사용자의 요청이나 문맥이 description에 매치되어 비로소 SKILL.md의 내용이 컨텍스트에 올라갑니다 -
더 필요하다면 참조 파일이 읽힘— SKILL.md 안에서 references/security.md와 같은 별도의 파일을 가리키고 있다면, 정말로 필요해진 단계에서 그 부분만 추가로 읽힙니다 -
이러한 3단계 구성 덕분에 「지식의 총량」은 무한히 늘릴 수 있으면서도, 「실제로 컨텍스트 (Context)를 압박하는 양」은 최소한으로 억제할 수 있습니다. 도서관의 장서를 모두 머릿속에 넣어둘 필요 없이, 책등 (description)을 보고 필요한 책만 펼치면 된다는 이미지에 가깝습니다.
이 부분이 가장 중요한데, 후술할 안티패턴 (Anti-pattern)의 상당수는 이 「단계적 공개 (Progressive Disclosure)」라는 전제를 깨뜨리는 데서 발생합니다. 비대해진 SKILL.md는 「책등을 보고 펼쳤더니 관련 없는 장까지 전부 읽어야 하는 책」과 같습니다.
「단계적 공개」의 발상을 이해하면, Claude Code 주변의 각 요소가 「언제 호출되는가」에 따라 역할 분담이 되어 있다는 점도 보입니다. 제 이해로는 대략 다음과 같이 정리할 수 있습니다.
| 요소 | 담당 역할 | 컨텍스트에 올라가는 시점 |
|---|---|---|
| 프롬프트 (Prompt) / CLAUDE.md | 항상 적용하고 싶은 「사실」 「전제」 「제약」 | 상시 |
| ... |
포인트는 각각이 「컨텍스트에 올라가는 시점」이 다르다는 것입니다. 항상 적용하고 싶은 전제라면 CLAUDE.md, 특정 상황에서 읽히게 하고 싶은 절차라면 Skills, 메인 문맥을 더럽히고 싶지 않은 조사라면 서브 에이전트 (Sub-agent)와 같이, 컨텍스트에 올리는 방식에 따라 구분하여 사용하는 설계 의도라고 받아들이고 있습니다.
역으로 말하면, 이 역할 분담을 무시하고 「절차인데 CLAUDE.md에 상시 배치한다」거나 「무거운 조사를 메인 Skill에 직접 작성한다」와 같은 행동을 하면 단계적 공개의 장점이 사라져 버립니다.
이 구분법은 엄격한 규칙이라기보다, 제가 운용하면서 정리한 결과입니다. 팀이나 용도에 따라서는 다른 구분 방식이 더 적합할 수도 있습니다.
공식 문서에서는 SKILL.md는 500행 미만으로 유지하고, 상세한 참조 자료는 별도 파일로 옮길 것이라고 권장하고 있습니다. 다만, 이 「500행」이라는 숫자의 이면을 이해해 두면 안티패턴 ① (비대화)에 대응하는 방식이 달라집니다.
제1부에서 언급했듯이, SKILL.md가 발화(Trigger)되면 그 내용은 컨텍스트에 올라가며 턴 (Turn)을 넘어서도 계속 남아 있습니다. 즉, SKILL.md의 행수는 곧 「발화되어 있는 동안 계속 지불해야 하는 토큰 비용 (Token Cost)」이 됩니다. 500행이라는 상한선은 단계적 공개의 효과를 유지할 수 있는 현실적인 라인으로서 설정된 가이드라인이라고 이해하고 있습니다.
또 하나 중요한 점은, description이 「발화 판정의 재료」라는 점입니다. Claude는 Skill 목록의 description (및 when_to_use)을 보고 어떤 Skill을 읽어들일지 판단합니다. 사양상 이 판정용 텍스트는 Skill 목록에서 1,536자 정도로 압축됩니다.
여기서 역산해 보면, 발화 판정에 효과적인 것은 본문의 내용이 아니라 description 쪽이라는 결론에 도달합니다. 본문을 아무리 정성스럽게 써도 description이 부실하면 애초에 펼쳐지지 않습니다. 후술할 안티패턴 ③이 「모호한 발화 조건」이 되는 것은 바로 이 구조에 기인합니다.
행수와 관련하여 구체적인 사례는 @haru0416 님이 보고하신 「Codex가 SKILL.md를 220행에서 끊어버렸다」는 관찰입니다 (참조 링크 확인). 이는 Codex CLI 측의 고정값이라기보다, 모델이 학습 데이터로부터 이끌어낸 「SKILL 파일의 전형적인 길이」를 바탕으로 sed -n '1,220p'와 같은 형태로 읽어 들였다는 견해였습니다.
여기서 읽어낼 수 있는 점은, SKILL.md가 어떻게 읽히는지는 도구 (모델)에 따라 차이가 있다는 것입니다. 공식 사양에서 500행까지 허용하더라도, 다른 AI 도구에서 읽힐 것을 전제로 한다면 본문은 200행 정도로 맞춰두는 것이 안전합니다.
저의 경우에도 사내용으로 만든 리뷰 Skill이 350행 정도가 되었는데, 나중에 보니 뒷부분에 작성한 「보안 관점」 내용이 거의 참조되지 않고 있었다는 사실을 깨달았습니다. 500행 이내에 들어와 있더라도 실제로 읽히지 않았다면 의미가 없었던 것입니다.
「SKILL.md에는 읽히지 않는 부분이 있을 수도 있다」는 전제로 설계하는 것이 안전하다고 느낍니다. 도입부 200행에 「사용 상황 · 최소 절차 · 최소한의 예시」를 몰아넣고, 상세 내용은 별도 파일 (references/ 등)로 분리해 두면 안심할 수 있습니다.
이 부분이 이 글에서 가장 쓰고 싶었던 내용입니다. 안티패턴(Anti-pattern)은 주의 깊지 못한 개인이 우연히 일으키는 것이라기보다, 인센티브의 미스매치 (Incentive Mismatch) 로 인해 구조적으로 발생하기 쉬운 것이라고 느낍니다.
Skill을 만드는 순간, 작업을 수행하는 사람의 합리성은 대개 다음과 같습니다.
일단 동작하면 된다 — 눈앞의 태스크를 처리하는 것이 최우선이며, 재사용성이나 발화 정밀도(Trigger Accuracy)는 뒷전이 되기 쉽습니다 -
나중에 고치겠지만, 오지 않는다 — "나중에 리팩터링(Refactoring)하자"라고 생각한 비대화나 다중 책임(Multi-responsibility)은, 동작하는 한 우선순위가 올라가지 않아 방치되기 쉽습니다 -
공유 설계보다 개인 최적화 — 자신의 리포지토리에서 자신이 사용하는 용도라면, 공통화나 명명 규칙(Naming Convention)보다 지금 당장 동작하는 것이 더 가치 있게 느껴집니다
하나하나를 떼어놓고 보면 합리적이지만, 이것들이 쌓이면 조직 전체적으로는 "비대해지고, 다중 책임을 가지며, 발화 조건이 모호하고, 공통화되지 않은 Skill 군"이라는 운영 부채가 됩니다. 코드의 기술적 부채(Technical Debt)와 완전히 같은 구도로, 게다가 Skills는 "Markdown이니까 가볍게 만들 수 있다"라는 분위기가 있는 만큼, 부채가 쌓이는 속도는 오히려 더 빠를지도 모른다고 느낍니다.
이러한 미스매치가 있다는 전제에 선다면, 대책은 "주의합시다" 정도로는 부족합니다. 각 안티패턴에 대해 "방치하면 어떤 메커니즘으로 어떤 실질적인 피해가 발생하는가"를 이해해 두면, 바쁠 때라도 "이것은 뒤로 미룰 수 없다"라는 판단을 내리기 쉬워집니다.
이하에서는 각 안티패턴을 "증상"이 아니라 "왜 문제를 일으키는가"라는 메커니즘 관점에서 설명하겠습니다.
비대화가 낳는 실질적인 피해는 크게 두 가지입니다.
하나는 발화 정밀도의 저하입니다. 앞서 언급했듯이, 행수가 늘어난다고 해서 그것이 직접 description의 정밀도를 높이는 것은 아니며, 오히려 본체에 "언제 사용하는가"에 대한 정보를 매립해 버리면 판정 재료가 분산되어 오히려 발화(Triggering)를 읽기 어려워집니다. 나아가 모델에 따라서는 중간에 끊겨서, 후반부에 작성한 중요한 지시(제 경우에는 보안 관점이었습니다)가 사실상 참조되지 않는 일이 발생합니다.
또 다른 하나는 비용 증가입니다. 발화되는 동안 본체의 모든 행이 컨텍스트(Context)에 계속 포함되므로, 긴 SKILL.md는 그대로 매 턴의 토큰 비용이 됩니다. "모두 때려 넣기"는 단계적 공개(Progressive Disclosure)라는 본래의 설계 의도를 저버리는 형태가 되어, 비용과 정밀도 양쪽 측면에서 수지가 맞지 않게 되기 쉽습니다.
도입부 200행에 "사용 상황 · 최소 절차 · 최소한의 예시"를 모으고, 상세 내용은 references/ 등에 분리합니다. 본체는 "목차와 최소 절차", 참조 파일은 "필요할 때 여는 상세 내용"이라는 역할 분담을 해두면 단계적 공개의 효과를 유지할 수 있습니다.
예를 들어 "릴리스(Release)"라는 Skill에 덤으로 테스트 실행 · 체인지로그 생성 · Slack 알림 · 사내 문서 업데이트까지 전부 넣어버리는 케이스를 사내에서도 보았습니다. 처음에는 편리해 보이지만, 다중 책임이 낳는 실질적인 피해는 재사용 불가능으로 귀결된다고 느낍니다.
- 일부만 실행하고 싶을 때, 불필요한 처리까지 돌아가 버린다
- 실패했을 때 원인 파악(Troubleshooting)이 어려워진다
- 수정하고 싶은 부분의 리뷰가 파일 전체의 리뷰가 되어 버린다
책임이 섞여 있으면 "테스트 실행만 다른 상황에서 쓰고 싶다"라고 생각해도 분리해낼 수 없습니다. 재사용하고 싶은 단위와 사용자가 일괄적으로 호출하고 싶은 단위가 일치하지 않는 것이 근본적인 문제라고 생각합니다.
@misakiito 님의 글에서는 엔트리 포인트(Entry Point) 층 · 규칙(Rule) 층 · 에이전트(Agent) 층을 분리하는 3층 구조가 소개되어 있었습니다. 발상이 비슷하다고 생각하며, /release와 같은 통제 스킬은 "순서와 사용자 승인의 게이트(Gate)" 역할에만 책임을 맡기고, 개별 처리는 별도의 Skill이나 서브 에이전트(Sub-agent)에 위임하는 설계가 훨씬 다루기 쉽다고 느낍니다.
제 경우도 처음에 만든 "기사 집필 Skill"이 트렌드 수집 · 구성안 · 본문 집필 · 제목 생성 · 공개 체크까지 한 번에 하려고 하다 보니, 중간에 언제든 멈출 수 없는 사용하기 불편한 것이 되어 있었습니다. 나중에 /trend-check, /write-draft, /title-gen과 같이 분리하고 나니 조합의 자유도가 높아졌고, Skill 단일의 책임도 명확해졌습니다.
your-app/.claude/skills/
├── trend-check/SKILL.md # 트렌드 수집에만 책임을 가짐
├── write-draft/SKILL.md # 초안 생성에만 책임을 가짐
...
다만, 지나치게 세밀하게 나누면 이번에는 호출하는 측이 복잡해집니다. "사용자가 1개의 명령으로 완결하고 싶은 단위"와 "내부에서 재사용하고 싶은 단위"를 어디서 나눌지는, 운영하면서 조정해 나간다는 전제로 두어도 좋다고 생각합니다.
Skill의 자동 발화 (Auto-trigger)를 기대하고 있는데, 왠지 호출되지 않는 상황은 자주 발생합니다. 제2부에서 다루었듯이, Claude는 본체가 아니라 description (설명) (및 when_to_use (사용 시점))을 보고 발화를 판정합니다. 이 부분이 부실하면 발화 판정 자체가 성립하지 않습니다.
이 안티패턴이 낳는 실질적인 피해는 양방향으로 나타납니다.
- 불발화 —
description: 코드 리뷰용과 같이 짧고 추상적이면, Claude 측에서 어느 상황에 발화시켜야 할지 판단하지 못해 공들여 만든 Skill이 호출되지 않습니다. - 오발화 — 반대로 범위를 너무 넓게 작성하면, 관계없는 상황에서 발화하여 다른 Skill과 충돌하거나 예상치 못한 절차가 실행됩니다.
너무 긴 description 또한 중요한 유스케이스 (Use case)가 후반부에 배치되어 생략될 경우, 핵심적인 발화 트리거 (Trigger)가 보이지 않게 되므로 피해야 할 부분입니다.
제가 직접 운영해 보며 효과가 좋았던 방식은, description에 "무엇을 하는가"뿐만 아니라 "언제 사용해야 하는가", "어떤 키워드에 반응해야 하는가"까지 명시하는 작성법이었습니다.
---
description: |
PR의 차분에 대해 보안 관점의 리뷰를 수행합니다.
...
@kamome_susume 님의 글에서도 Skills는 "팀의 암묵지 (Tacit knowledge)를 형식지 (Explicit knowledge)로 바꾸는 도구"라고 표현되었지만, 발화 조건이야말로 그 암묵지의 중심에 있다고 느낍니다. "언제 사용하는가"라는 판단은 숙련된 사람의 머릿속에만 있는 경우가 많으며, 그것을 description에 글로 써 내려가는 작업 자체가 가치라고 생각합니다.
Skills에는 ! 명령어를 통해 동적으로 명령어 출력을 삽입하거나, allowed-tools로 허용 도구를 확장하는 기능이 있습니다. 이는 강력한 반면, 작성만 해두고 방치하면 사고의 원인이 됩니다.
여기서의 메커니즘은 제1부의 "Skills는 발화했을 때만 동작한다"는 성질과 "Claude가 자동으로 발화를 판단할 수 있다"는 성질이 결합되는 데 있습니다. 즉, 부작용 (Side effect)이 있는 처리를 자동 발화 가능한 Skill에 작성해 두면, Claude가 "코드가 정리된 것처럼 보이니까"라고 판단하여, 사용자의 의도하지 않은 타이밍에 외부로 영향을 주는 조작을 실행해 버릴 여지가 생깁니다.
특히 주의해야 할 패턴은 다음과 같습니다.
git push나gh pr merge와 같이 외부에 영향을 주는 명령어를 Skill 내에 직접 작성해 두는 경우allowed-tools에 Bash를 넓게 허용하여, 사용자 승인 없이 임의의 명령어를 실행할 수 있는 상태가 된 경우- Claude가 자동으로 발화할 수 있는 Skill에 배포 관련 처리를 포함하고 있는 경우
공식 문서에서도 배포 등 타이밍을 제어하고 싶은 워크플로우에는 disable-model-invocation: true를 설정하여, 사용자가 /skill-name으로 명시적으로 호출할 것을 권장하고 있습니다. 이는 위의 "정리된 것처럼 보이니까 배포를 판단해 버리는" 상황을 피하기 위한 장치입니다.
저도 처음에는 개인 저장소에서 /commit Skill에 자동 발화를 허용했다가, 의도하지 않은 타이밍에 커밋 메시지 초안 실행이 돌아간 적이 있었습니다. 그 이후로는 부작용이 있는 것은 모두 수동 발화로 돌리고, Skill의 서두에도 "이 스킬은 외부에 영향을 줍니다"라고 코멘트를 남기도록 하고 있습니다.
부작용이 있는 조작은 disable-model-invocation: true로 발화를 수동으로 제한한 뒤, allowed-tools를 최소한으로 좁히는 이중 구조로 설계해 두면 안심할 수 있습니다. 읽기 계열과 쓰기 계열로 Skill을 나누는 것도 유효했습니다.
Skills가 늘어나다 보면 "테스트를 실행한다", "Git의 차분을 확인한다", "PR을 만든다"와 같은 동일한 절차가 여러 Skill에 복사-붙여넣기(Copy-paste)로 흩어지게 됩니다. 이는 제3부의 인센티브 이야기와도 맞닿아 있는데, "지금 복사해서 붙여넣는 게 더 빠르다"라는 개인 최적화가 쌓인 결과입니다.
이 안티패턴의 실질적인 피해는 단일 정보원 (Single source of truth)이 상실되는 것입니다.
- 특정 Skill만 구형인 상태: 다른 것들은
pnpm test --filter로 업데이트되었지만, 어떤 Skill은 여전히pnpm test인 상태 - 보안 체크 절차가 Skill마다 조금씩 다름
- 한 곳에서 운영 규칙을 변경해도 다른 Skill에 전파되지 않음
절차가 분산되어 있으면, 규칙을 바꿀 때마다 "어떤 Skill을 수정해야 하는가"를 알 수 없게 되어 수정 누락이 반드시 발생합니다.
@inari111 님의 글에서 소개된 feature-dev와 같은 Skill이 매력적인 이유는, 리서치(Research)·계획(Planning)·구현(Implementation) 단계가 명확히 나누어져 있고, 각각이 공통된 관례를 따르고 있기 때문이라고 생각합니다. 마찬가지로 @misakiito 님의 3층 구조(Entry point / Rule / Agent)도 공통 규칙을 한 곳에 모으는 메커니즘으로서 기능하고 있습니다.
제가 시도해 본 것은 공통 절차를 ~/.claude/rules/ 하위에 두고, 각 Skill에서는 "이 규칙을 따르세요"라고 참조하는 형태였습니다. SKILL.md 자체는 얇게(Thin) 유지하면서, 공통화하고 싶은 지식은 별도 파일로 집약할 수 있기 때문에 변경의 영향 범위를 파악하기 쉬워집니다.
your-app/
├── .claude/
│ ├── skills/
...
단, 공통화를 너무 과하게 진행하면 "어디를 봐야 해당 동작의 근거를 알 수 있는가"가 역으로 파악하기 어려워집니다. 공통화와 국소 최적화(Local optimization) 사이의 균형은 팀의 규모와 Skill 수에 따라 판단해야 할 부분입니다.
일반적인 애플리케이션 코드라면 CI에서 테스트가 실행되고, PR(Pull Request) 리뷰에서 체크가 이루어지는 것이 당연합니다. 반면, Skills는 "마크다운(Markdown)이니까"라는 가벼움 때문에 리뷰를 거치지 않고 직접 push되는 경우가 적지 않습니다.
여기서 발생하는 실질적인 피해는, 지금까지 언급한 안티패턴 ①~⑤가 감지되지 않은 채 증식하는 것입니다. description의 아주 작은 업데이트만 하려다가 발화 조건(Trigger condition)이 바뀌어 다른 Skill과 충돌하는 일도 발생합니다. 리뷰 메커니즘이 없으면 비대화(Bloating)도, 다중 책임(Multiple responsibilities)도, 모호한 발화 조건도 누구의 체크도 거치지 않고 운영 환경에 반영되어 버립니다. Skills의 부채가 쌓이는 속도가 빠른 것은, 이러한 "가벼움"과 "체크의 부재"의 조합이 크다고 느끼고 있습니다.
@hiropon22 님의 글에서는 "발견 → 판정·적용 → 무인 운전"이라는 3단계 자기 개선 루프(Self-improvement loop)가 소개되어 있었으며, 그 안에서 verify-diff / skill-review / publicity-review라는 세 가지 품질 게이트(Quality gate)를 직렬로 배치하는 설계가 제시되어 있었습니다. 13일 동안 40건 이상의 자동 수정 커밋이 생성되었다고 하는데, 이 정도로 자동화할 것인가를 떠나서 그 사고방식은 매우 참고가 됩니다.
제 팀에서 도입하고 있는 것은 훨씬 단순한 수준이며, 다음 3가지를 운영 규칙에 넣은 정도입니다.
- Skills의 변경은 일반적인 코드와 마찬가지로 PR 기반으로 리뷰한다.
- PR에서는
description의 차분(Diff)을 반드시 확인한다 (발화 범위가 변하기 때문). - 부작용(Side effect)이 있는 Skill은 샌드박스(Sandbox)적인 리포지토리에서 실행 확인을 거친 후 머지(Merge)한다.
이것만으로도 발화 조건의 의도치 않은 변경이나, 부작용이 강한 커맨드의 혼입은 상당히 방지할 수 있었습니다.
지금까지의 안티패턴을 바탕으로, 제가 현재 Skills를 재검토할 때 사용하고 있는 지침을 간단히 정리합니다. 이 모든 것은 "단계적 공개(Progressive disclosure)를 깨뜨리지 않는다"라는 하나의 선으로 연결되어 있다고 느낍니다.
- 얇게 유지하기:
SKILL.md본체는 200행 이하를 목표로 하고, 상세 내용은references/하위로 (단계적 공개 유지) - 책임 분리하기: 1 Skill 1 책임을 기본으로 하여, 통제 계열과 개별 처리 계열을 분리 (재사용성 확보)
- 발화 조건 명시하기:
description에는 "무엇을"과 "언제"를 모두 쓰고,when_to_use를 활용 (발화 판정의 정밀도) - 부작용 분리하기: 쓰기 계열·외부 영향 계열은
disable-model-invocation: true+ 최소한의allowed-tools(사고 예방) - 공통화하기: 절차·규칙은
rules/등에 분리하여 Skills에서 참조 (단일 정보원, Single source of truth) - 리뷰 프로세스 돌리기: description 차분 확인과 부작용 Skill의 실행 확인을 규칙화 (부채 감지)
참고를 위해, 제가 안착한 구조의 예시를 올려둡니다 (프로젝트명은 범용적인 이름으로 대체했습니다).
your-app/
├── .claude/
│ ├── skills/
...
CLAUDE.md에는 '사실'을, Skills에는 '절차'를, rules/에는 '공통의 작법'을 두는 것이 현재로서는 가장 적절하다고 느껴지는 구분 방식입니다. 이는 제1부에서 다루었던 '언제 컨텍스트(context)에 올라가는가'의 역할 분담을 디렉터리 구조로 구현한 것이라고 이해하고 있습니다.
Claude Code Skills는 실제로 운용해 보면 정말로 개발 방식 자체를 바꿔주는 도구라고 느낍니다. 반면, 편리하기 때문에 어느샌가 '작동은 하고 있지만 내부는 엉망진창인' 상태에 빠지기 쉽다는 것도 사실입니다.
이 글에서 반복적으로 돌아온 것은 '단계적 공개 (progressive disclosure)'라는 설계 사상과, '개인의 합리성이 전체의 부채가 된다'는 인센티브의 미스매치 (mismatch) 두 가지였습니다. 안티패턴의 대부분은 전자의 전제를 깨뜨리는 것에서 발생하며, 후자의 구조에 의해 방치됩니다. 역으로 말하면, 이 두 가지를 의식하고 있으면 개별적인 대책들이 파편화된 지식이 아니라 하나의 선으로 연결되어 보일 것이라고 생각합니다.
본 기사에서 다룬 안티패턴은 모두 제가 직접 겪었거나 사내에서 목격한 범위 내의 것들입니다. 모든 현장에 적용되는 것은 아니겠지만, 사내에서 Skills를 늘려가는 단계에 있는 분들이라면 몇 가지라도 해당되는 부분이 있을 것이라 생각합니다.
만약 이 글 중에서 "우리도 이 패턴을 저지르고 있었다"라고 느껴지는 것이 있다면, 우선 SKILL.md의 줄 수와 description의 작성 방식부터 재검토해 보시는 것을 추천합니다.
- 일상적인 개발에서 사용 중인 Claude Code Skills (@inari111): https://zenn.dev/inari111/articles/4f9dc787b6c191
- 스킬이 매일 스스로 개선되는 메커니즘 (@hiropon22): https://zenn.dev/hiropon22/articles/claude-code-self-improving-loop
- 1시간 만에 개발을 완료하는 Claude Code Skill (@misakiito): https://zenn.dev/misakiito/articles/e5fd7f54433d3d
- Codex가 SKILL.md를 220줄로 끝냈던 이야기 (@haru0416): https://zenn.dev/haru0416/articles/codex-skill-md-220-lines
- Claude Code의 skills 아이디어 대전 20선 (@kamome_susume): https://qiita.com/kamome_susume/items/d8919d94f55d86e9881c
- Claude 공식 Skills 문서: https://code.claude.com/docs/en/skills
- Anthropic: Equipping agents for the real world with Agent Skills: https://www.anthropic.com/engineering/equipping-agents-for-the-real-world-with-agent-skills
- Anthropic: Effective context engineering for AI agents: https://www.anthropic.com/engineering/effective-context-engineering-for-ai-agents
AI 자동 생성 콘텐츠
본 콘텐츠는 Qiita AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기