AI··7 min read·

AI 코딩 에이전트에게 '우리 팀 방식'을 가르치기 — 스킬 시스템 운영기

AI가 똑똑해질수록 규칙 문서는 필요 없어질까? 실제 프로젝트에서 AI 코딩 에이전트용 스킬 시스템을 만들고 운영하며 얻은 결론을 정리했다. 점진적 공개, 계층 분리, 금지영역, 그리고 공식 Agent Skills와의 비교까지.

AI 코딩 에이전트에게 '우리 팀 방식'을 가르치기 — 스킬 시스템 운영기

"AI가 이렇게 똑똑한데, 굳이 규칙 문서를 만들어야 하나?"

우리 팀이 AI 코딩 에이전트를 본격 도입하면서 가장 많이 한 질문이다. 결론부터 말하면 — 절반은 맞고 절반은 틀렸다.

모델은 "코드 잘 쓰는 법"은 알아서 한다. 관용적인 React/TypeScript, 흔한 라이브러리 사용법, 일반적인 베스트 프랙티스. 이런 건 굳이 가르칠 필요가 없다. 하지만 우리 팀이 어떤 결정을 내렸는지, 어떤 코드를 건드리면 안 되는지는 절대 모른다. 학습 데이터에 있을 리가 없으니까.

이 글은 그 간극을 메우는 "스킬 시스템"을 어떻게 설계하고 운영하는지에 대한 기록이다. 실제로 운영 중인 Next.js 기반 프론트엔드 모노레포의 사례를 그대로 가져왔다.

1. 스킬이 푸는 진짜 문제: 품질이 아니라 일관성

똑똑한 모델에게 규칙 없이 "목록 페이지 만들어줘"를 다섯 번 시키면, 다섯 개 다 동작하지만 미묘하게 다른 페이지가 나온다. 페이징을 서버에서 하기도 하고 클라에서 하기도 하고, 상세 페이지 진입을 Row 버튼으로 만들기도 하고 이름 링크로 만들기도 한다. 여러 명이 작업하면 더 심하다.

스킬의 가치는 "코딩을 가르치는 것"이 아니다. 결과물이 매번 '우리 정답'으로 수렴하게 만드는 것이다. 코드가 valid한지가 아니라 우리 컨벤션과 같은지가 중요하다. 일관성 그 자체가 제품이다.

그래서 스킬이 효과적인 조건은 분명하다.

  • 반복적이고 보일러플레이트가 많은 작업 (CRUD 목록/상세/폼 페이지 양산)
  • 팀 컨벤션이 빡세고, 작업하는 사람이 여럿
  • "여기는 건드리면 안 됨" 같은 지뢰밭이 있는 코드베이스

반대로 혼자 하는 탐색성 작업이나 일회성 디버깅이라면 스킬은 순수 오버헤드다. 적합성이 전부다. 우리 프로젝트는 도메인마다 똑같은 모양의 페이지를 계속 찍어내는 구조라, 스킬의 ROI가 매우 컸다.

2. 핵심 원리: 점진적 공개 (Progressive Disclosure)

좋은 스킬 설계의 원리는 딱 하나다.

항상 로드되는 건 가볍게, 자세한 건 필요할 때만 불러온다.

LLM의 컨텍스트 윈도우는 한정 자원이고, 매 요청마다 거대한 규칙 문서를 통째로 들고 있으면 토큰도 느려진다. 그래서 우리는 "진입점은 얇게, 상세는 온디맨드로" 구조를 잡았다.

text
항상 로드 (가벼움)              필요할 때만 (무거움)
─────────────────             ──────────────────
진입점 문서 (약 100줄)    ──►   상세 룰북 (수백~수천 줄)
 = 라우팅 표 + 전역 룰           templates / standards / docs
 = "무엇을 언제 펴라"만           = 실제 절차와 복붙용 코드

진입점 문서에는 이런 라우팅 표만 둔다.

요청 유형먼저 읽을 문서
List 페이지 생성list.md
Modal 생성/연결modal.md
Detail 페이지 생성detail.md
Form 페이지 생성form.md

에이전트는 요청을 받으면 이 표를 보고 해당 룰북만 읽는다. "목록 페이지"를 요청했는데 모달 룰북 수백 줄을 같이 읽지 않는다.

흥미로운 건, 이게 Anthropic의 공식 Agent Skills가 동작하는 방식과 정확히 같은 뼈대라는 점이다. 공식 스킬도 description(짧은 메타데이터)만 항상 들고 있다가, 트리거되면 본문을, 더 필요하면 번들 파일을 그때그때 불러온다. 우리는 그걸 모르고 손으로 같은 메커니즘을 재발명한 셈이었다. (이 비교는 6장에서 자세히 다룬다.)

3. 계층 분리: 한 파일에 다 넣지 마라

흔한 실수는 모든 규칙을 진입점 문서 하나에 욱여넣는 것이다. 금방 비대해지고, 매 요청마다 토큰을 잡아먹으며, 무엇보다 사람이 유지보수하기 싫어진다. 우리는 역할별로 쪼갰다.

  • 라우터 — "이 요청은 어느 문서를 펴라"만. 전역 원칙도 여기.
  • 룰북 — 실제 생성 절차, 질문해야 할 항목, 조립 순서
  • 표준 (Standards) — 어기면 안 되는 MUST / MUST NOT
  • 배경 (Docs) — 왜 이렇게 하는지 (패턴의 근거)
  • 템플릿 (Templates) — 복붙 가능한 baseline 코드 + patch

각 계층의 강제력도 다르다. 라우터(전역 룰)가 가장 세고, 그 아래 표준이 "위반 금지"를 담당한다. 룰북에 "이렇게 해라"라고 써 있어도 전역 룰이 "그건 건드리지 마라"라고 하면 후자가 이긴다.

템플릿은 baseline + patch로

특히 템플릿 설계에서 한 가지 원칙이 결정적이었다. 기능 조합마다 새 파일을 만들지 않는다.

목록 페이지에는 펼치기(Expand), 체크박스, Row 액션, 검색 필터 같은 기능이 붙는다. 조합마다 전용 템플릿을 만들면 2⁴ = 16개의 파일이 필요하다. 조합 폭발이다. 대신 baseline 하나에 patch를 순차로 쌓는다.

text
baseline.tsx
   ├─(+) patches/expand/    →  목록 + 펼침
   ├─(+) patches/checkbox/  →  목록 + 펼침 + 선택
   └─(+) patches/action/    →  목록 + 펼침 + 선택 + 케밥 메뉴

조합이 N개여도 patch는 선형으로만 늘어난다. 유지보수 폭발을 막는 정석이다.

4. 가장 오래 살아남는 자산: "금지영역"

여기서부터가 이 글의 핵심이다.

모델이 더 똑똑해질수록 any 타입 쓰지 마라, 날짜는 ISO 포맷으로 직접 만들지 마라 같은 일반 규칙은 점점 쓸모없어진다. 모델이 알아서 하니까. 하지만 절대 안 사라지는 게 있다.

바로 모델이 valid해 보이지만 사고 나는 행동을 하는 영역이다.

우리 프로젝트의 실제 사례를 보자. 우리는 전역 Redux 슬라이스 하나로 모달을 관리한다. modalType이라는 문자열 하나로 어떤 모달을 띄울지 결정하고, 모달 타입 정의는 중앙 상수 파일 한 곳에 모여 있다. 그런데 이 파일이 어느새 100개가 넘는 모달 타입을 담은 거대한 사전이 됐고, 이걸 소비하는 도메인별 컨트롤러가 수십 개 생겼다.

이 구조에서 에이전트에게 새 모달을 만들라고 하면, 모델은 아주 자연스럽게 이렇게 행동한다.

ts
// 모델이 "깔끔하다"고 판단하고 추가하려는 코드
export const MODAL_TYPE = {
  // ...기존 100여 개...
  MY_NEW_FANCY_MODAL: { type: "MY_NEW_FANCY_MODAL", title: "..." }, // ← 무심코 추가
};

문법 오류도 아니고 나쁜 코드도 아니다. 오히려 모델이 자신 있게 할 "좋은 작업"처럼 보인다. 하지만 이 중앙 사전은 전 도메인이 공유하는 단일 병목이라, 함부로 늘리면 머지 충돌과 결합도 문제를 일으킨다. 그래서 우리 전역 룰에는 이렇게 박혀 있다.

MODAL_TYPE에 새 타입 추가 금지. 필요하면 반드시 사람에게 먼저 확인할 것.

비슷한 금지영역이 더 있다.

  • 공용 빌드 산출물 패키지 — 고치면 이 페이지뿐 아니라 다른 앱들도 같이 깨진다. 그런데 모델 입장에선 "여기 이 컴포넌트 고치면 되겠네" 하고 건드리기 딱 좋은 곳이다.
  • 공용 테이블 row 매핑 — 새 row 타입을 추가하면 공용 패키지를 수정해야 해서, "특정 기능만 쓸 땐 기본값으로 두라"는 우회 룰까지 따라붙는다.

이런 규칙의 공통점은, 코드만 봐선 절대 알 수 없다는 것이다. "이건 빌드 산출물이다", "이건 전역이라 위험하다"는 건 과거에 누가 여기서 데인 조직의 경험이다. 모델이 아무리 발전해도 이 "우리만의 지뢰밭 지도"는 추론으로 채울 수 없다.

금지영역이야말로 모델 발전과 무관하게 오래 가는 자산이다.

5. 운영 규율: 단 하나의 질문

스킬 문서는 방치하면 살이 찐다. 한번 적은 규칙은 잘 안 지워진다. 우리 룰북 중 하나는 어느새 1,600줄을 넘겼다. 게다가 그 거대한 문서가 정작 라우팅 표에는 등록이 안 돼서, 가장 활발히 쓰는 스킬인데 진입로가 막혀 있는 어이없는 상황도 겪었다. (자동 트리거가 아니라 수동 라우팅에 의존하는 방식의 대표적인 함정이다.)

문서가 비대해지는 걸 막기 위해 우리가 쓰는 기준은 질문 하나다.

"이 줄을 모델이 스스로 추론할 수 있나?" - Yes → 빼라. 모델이 알아서 한다. (일반 코딩 규칙) - No → 유지하라. (우리만의 결정 / 경로 / 금지영역)

이 기준으로 거르면 살아남는 것들은 대개 이렇다.

규칙 종류처리예시
일반 베스트 프랙티스깎아냄"any 쓰지 마라"
valid 옵션 중 우리가 고른 결정유지서버/클라 페이징 선택, Row 액션은 케밥으로 통일
어디에 뭐가 있나유지공용 유틸 경로, 쿼리 키 위치
하지 마라 영역유지공용 패키지 수정 금지

모델이 좋아질수록 스킬의 일반적인 부분은 줄어들고, 조직 고유의 부분만 남는다. 스킬은 "어떻게 코딩하나"에서 "우리가 무엇을 정했나 / 무엇이 어디 있나 / 무엇을 하지 마라"로 진화한다.

6. 자체 마크다운 룰 vs 공식 Agent Skills

우리는 위 시스템을 그냥 마크다운 문서 + 진입점 라우터로 직접 만들었다. 그런데 Anthropic은 이걸 표준화한 Agent Skills라는 포맷을 제공한다. SKILL.md 파일에 메타데이터(name, description)를 달면, 모델이 description을 보고 알아서 해당 스킬을 발동한다. 둘은 같은 원리(점진적 공개)를 다른 방식으로 구현한 것이다.

항목자체 방식 (라우터 + 마크다운 룰)공식 Agent Skills (SKILL.md)
트리거라우팅 표를 모델이 읽고 수동 분기description으로 모델이 자동 선택
항상 로드진입점 문서 전체 (라우팅+룰)각 스킬의 name + description만 (수십 토큰)
상세 로드모델이 직접 파일을 읽음트리거 시 본문 → 필요 시 번들 파일 자동
실행 코드❌ 문서뿐 (모델이 코드를 작성)✅ 스크립트 번들 가능 (실제 실행)
portabilityrepo에 종속, 통째로 복사해야 이동폴더 단위 portable, 배포 가능
적용 범위해당 프로젝트 세션여러 Claude 환경 공통
자율성라우팅 표에 없으면 누락됨description만 맞으면 알아서 발동
제어·결정성명시적 → 예측 가능자동 → 가끔 오발동·미발동
셋업 비용낮음 (그냥 .md 작성)중간 (폴더 + 프론트매터 규약)

정리하면 이렇다.

  • 자체 방식의 강점: 명시적 제어, git 일원화, 셋업이 간단. 단점은 수동 라우팅이라 누락 위험이 있고(앞서 말한 1,600줄 orphan 사례), repo에 종속되며, 코드 실행은 못 한다.
  • 공식 Skills의 강점: 자동 트리거, portable, 코드 실행, 멀티 환경. 단점은 트리거가 description 품질에 의존하고 셋업이 약간 무겁다.

전부 옮길 필요는 없다. 현실적인 답은 혼합이다. 전역 룰과 금지영역은 진입점 문서에 얇게 남기고, 반복 작업 룰북은 점차 SKILL.md로 승격해 자동 트리거의 이점을 취하는 식이다. 특히 "라우팅 표에서 누락돼 orphan 된" 문제는 자동 트리거로 구조적으로 해결된다. 다만 이미 수십 개 컨트롤러가 의존하는 시스템을 급히 갈아엎을 이유는 없다. 새로 만드는 스킬부터 적용해보는 게 안전하다.

마치며

AI가 똑똑해진다고 스킬이 필요 없어지는 게 아니다. 필요한 스킬의 종류가 바뀔 뿐이다.

코딩 교본은 버려도 된다. 모델이 알아서 한다. 하지만 우리 팀이 valid한 선택지 중 무엇을 골랐는지, 공용 유틸이 어디 있는지, 어떤 코드가 지뢰밭인지 — 이 "조직 고유의 지식"은 모델이 추론으로 채울 수 없다. 그게 모델 발전과 무관하게 오래 가는 자산이다.

스킬을 만들 때, 그리고 정리할 때, 질문 하나만 기억하면 된다.

"이 줄을 모델이 스스로 추론할 수 있나?"

추론할 수 있으면 지워라. 없으면, 그게 바로 당신 팀의 스킬이다.

Related Posts

같이 읽으면 좋은 글