skill-creator로 코드 리뷰 스킬을 만들어봤다 — 팀 컨벤션을 AI에 이식하기

이 글은 1편의 후속이다. 1편에서 skill-creator의 구조를 분석했다면, 이 글부터는 직접 돌린다. 첫 번째 실험: 팀 코드 리뷰 스킬.


왜 코드 리뷰인가

코드 리뷰는 모든 개발 팀에서 매일 일어나는 일이다. 그리고 매일 같은 말을 반복하는 일이기도 하다.

“여기 any 쓰지 마세요.” “Early return 쓰세요.” “이 로직은 컴포넌트에서 빼세요.”

시니어가 주니어 PR에 남기는 코멘트의 70%는 팀 컨벤션 위반 지적이다. 아키텍처 논쟁이 아니라 규칙 위반 체크. 이건 사람이 계속 할 일이 아니다.

문제는 범용 AI 리뷰 도구로는 안 된다는 점이다. 팀마다 규칙이 다르다. 어떤 팀은 if-else를 허용하고, 어떤 팀은 삼항 연산자를 강제한다. “코드 리뷰해줘”라고 GPT에 던지면 일반론만 나온다. 우리 팀의 규칙을 아는 리뷰어가 필요하다.

그래서 skill-creator로 만들어봤다.


프롬프트는 이게 전부였다

PR 코드 리뷰를 자동화하는 스킬을 만들어줘.

우리 팀의 컨벤션:
- TypeScript strict mode, any 금지
- 함수명은 동사+명사 (parseRssFeed, validatePostSchema)
- utils, helpers, common 같은 쓰레기통 네이밍 금지
- 비즈니스 로직은 View 레이어에 넣지 않는다
- Early return 패턴 사용, 불필요한 else 금지

이 스킬은 다음 상황에서 발동해야 한다:
- "이 PR 리뷰해줘"
- "코드 리뷰 부탁해"
- git diff가 주어졌을 때

이 스킬은 다음 상황에서 발동하면 안 된다:
- "이 코드 설명해줘" (설명 ≠ 리뷰)
- "버그 찾아줘" (디버깅 ≠ 리뷰)
- "리팩토링해줘" (수정 ≠ 리뷰)

팀 컨벤션 5개, 발동 조건 3개, 비발동 조건 3개. 이 정도면 충분하다고 봤다. 구현 방법은 일절 지시하지 않았다. “5단계로 나눠라”도, “테이블 형태로 보여줘”도, “심각도를 CRITICAL/WARNING으로 분류하라”도 말하지 않았다.


169줄이 나왔다

skill-creator가 생성한 결과물: SKILL.md 169줄. 입력은 컨벤션 5줄이었는데, 출력은 5단계 파이프라인으로 구조화된 리뷰 시스템이었다.

프롬프트에서 말한 적 없는 것들이 스스로 설계되어 있었다:

  • 심각도 3단계 — 🔴 CRITICAL, 🟡 WARNING, 🔵 NITPICK
  • 자동 판정 기준 — CRITICAL 0건 + WARNING 2건 이하 = APPROVE, 나머지 = REQUEST_CHANGES
  • diff의 + 라인만 리뷰 — 삭제된 코드를 태클하지 않는다는 규칙
  • 수정 코드 필수 첨부 — “대안 없는 참견 금지 원칙”

이건 프롬프트에 적어준 적이 없다. skill-creator가 “코드 리뷰”라는 행위를 단순 코멘트 나열이 아니라, 실무에서 굴러가는 운영 프로세스로 이해하고 구조를 세운 것이다.


5-Phase 파이프라인 해부

생성된 스킬은 PR 코드를 5단계로 순차 검사한다. 각 Phase는 독립적이고, 위반이 없어도 “위반 없음”을 명시적으로 출력한다. CI 파이프라인의 job과 같은 구조다.

Phase 1: TypeScript Strict Mode 감사

🔴 CRITICAL: any 타입, as 캐스팅, @ts-ignore(사유 없음), @ts-nocheck
🟡 WARNING: 파라미터 타입 누락 (암묵적 any)

내가 “any 금지”라고 한 줄 쓴 걸, AI가 5가지 위반 패턴으로 분해했다. as SomeType 캐스팅까지 잡은 건 의외였다. 프롬프트에는 없었지만, “strict mode”에서 논리적으로 도출한 것이다.

Phase 2: 네이밍 컨벤션 감사

🔴 CRITICAL: utils.ts, helpers/ 같은 쓰레기통 네이밍
🟡 WARNING: 동사+명사 패턴 미준수
🔵 NITPICK: Boolean에 is/has/should 접두사 누락

여기서도 확장이 일어났다. 프롬프트에는 없었던 Boolean 접두사 규칙모호한 변수명(data, info, temp) 감지가 추가되어 있었다. 팀 컨벤션의 “정신”을 읽고 확장한 셈이다.

Phase 3: 아키텍처 계층 분리 감사

🔴 CRITICAL: 컴포넌트 내 fetch/axios 직접 호출, SQL/ORM 쿼리
🟡 WARNING: 이벤트 핸들러 5줄 이상, 상태 머신 로직

“비즈니스 로직은 View에 넣지 않는다”는 한 줄이 5개 위반 패턴으로 전개됐다. 특히 **“이벤트 핸들러 내부에 5줄 이상”**이라는 구체적인 임계값을 스스로 설정한 것이 흥미롭다. 절대적 기준은 아니지만, 심각도가 WARNING이라 유연성을 남겨둔 판단이다.

Phase 4: 제어 흐름 감사

🟡 WARNING: if-else에서 if가 return인데 else 존재, 3단 중첩 if
🔵 NITPICK: 삼항 연산자 중첩

“Early return 쓰세요”가 3개 위반 패턴으로. Arrow Anti-Pattern(3단 이상 중첩)이라는 정식 명칭까지 붙여서 리뷰 아웃풋의 전문성을 높였다.

Phase 5: 종합 판정

여기가 핵심이다. 사람이 매번 “이 PR 머지해도 되나?”를 판단하는 대신, 기계적인 판정 기준을 설정했다:

  • APPROVE: 🔴 0건 + 🟡 2건 이하
  • REQUEST_CHANGES: 🔴 1건 이상 또는 🟡 3건 이상

🔴 CRITICAL이 단 1건이라도 존재하면, 다른 모든 것이 완벽하더라도 무조건 REQUEST_CHANGES입니다. 타협 없음.

이 부분은 꽤 영리하다. 리뷰어마다 기분과 숙련도에 따라 기준이 흔들리면 팀은 빠르게 피로해진다. 규칙이 사람이 아니라 시스템에 있으면 적어도 같은 문제를 두고 다른 판정이 나오는 일은 줄어든다.


트리거 — 가장 미묘한 부분

생성된 스킬에서 가장 정교한 부분은 발동/비발동 경계다.

설명, 디버깅, 리팩토링은 모두 “코드를 본다”는 점에서 리뷰와 비슷하다. 하지만 본질이 다르다:

행위목적이 스킬의 반응
리뷰피드백 + 판정✅ 발동
설명동작 원리 해설❌ 비발동
디버깅근본 원인 추적❌ 비발동
리팩토링코드 직접 수정❌ 비발동

그리고 경계 사례에 대한 처리까지 들어있었다:

사용자가 “이 코드 봐줘”처럼 모호한 표현을 쓸 경우, 피드백/판정을 기대하는지, 동작 설명을 기대하는지를 판단하십시오. 판단이 불가능하면 “리뷰를 원하시나요, 아니면 코드 설명을 원하시나요?”라고 질문하십시오.

이건 프롬프트에 없었다. “이 코드 봐줘”라는 모호한 요청을 어떻게 처리할지까지 스스로 설계한 것이다. 1편에서 분석한 트리거 최적화 — false positive 방지 — 가 실제로 작동하고 있다.


지시하지 않았는데 나온 것들

정리하면, 프롬프트에 없었지만 AI가 스스로 추가한 설계 요소:

  1. 5-Phase 파이프라인 구조 — 순차 실행, 독립적 보고
  2. 심각도 3단계 분류 — CRITICAL / WARNING / NITPICK
  3. 자동 판정 기준 — APPROVE vs REQUEST_CHANGES의 수치 기준
  4. diff의 + 라인만 대상 — 삭제된 코드에 태클하지 않는 규칙
  5. 수정 코드 필수 첨부 — 대안 없는 참견 금지
  6. 경계 사례 처리 — “이 코드 봐줘” 같은 모호한 요청에 대한 질문 전략
  7. 칭찬 섹션 — “위반만 나열하면 사기가 꺾인다”는 이유로 잘한 점도 언급
  8. 기존 스킬 시너지 표 — 다른 스킬과 병렬 장착 시 역할 분담

이 중 7번이 특히 인상적이다. 코드 리뷰 도구에 “칭찬할 점”을 넣어라고 지시한 사람은 없다. 하지만 실무에서 리뷰가 태클 목록으로만 가득 차면 주니어의 사기가 꺾인다는 걸 AI가 알고 있었다.

이건 기술적 설계라기보다 조직 심리학적 설계에 가깝다. 코드 리뷰를 단순 버그 탐지 절차로만 보면 칭찬 섹션은 군더더기다. 하지만 리뷰를 팀의 학습 장치로 본다면, 피드백의 톤과 순서는 기능의 일부가 된다. skill-creator가 “리뷰”를 기술 검사만이 아니라 성장 프로세스로 해석했다는 점이 여기서 드러난다.


그러면 ESLint나 Biome으로는 안 되나?

이 질문을 안 할 수 없다. Phase 1의 any 감지, Phase 4의 불필요한 else 감지는 ESLint나 Biome의 커스텀 룰로도 가능하다. 이 스킬이 기존 린터를 대체하는가?

결론부터 말하면 대체라기보다 보완이다. 역할이 다르기 때문이다.

비교ESLint / Biome이 스킬
감지 방식AST 정적 분석LLM 의미론적 판단
감지 범위문법 수준 (any 존재 여부)의도 수준 (“이 로직이 View 레이어에 있는 게 맞는가?”)
Phase 1✅ 대부분 커버⚠️ 겹친다
Phase 2⚠️ 정규식 기반 네이밍 룰 가능✅ “이 변수명이 모호한가?”는 LLM이 강하다
Phase 3❌ 계층 분리는 추상적 판단✅ “fetch가 컴포넌트 안에 있다”는 감지 가능
Phase 4no-else-return 룰로 커버⚠️ 겹친다

Phase 1과 4는 린터와 겹친다. 이미 Biome을 쓰고 있다면 중복이다. 하지만 Phase 3(아키텍처 계층 분리)은 린터로 절대 못 잡는다. “이벤트 핸들러 안에 비즈니스 로직이 있는가?”는 AST로 판단할 수 없다. 코드의 의미를 읽어야 하는 영역이고, 이게 LLM 기반 리뷰의 고유 가치다.

이상적인 구성: Biome이 Phase 1, 4를 잡고, 이 스킬이 Phase 2, 3에 집중. 린터가 먼저 문법을 잡고, 스킬이 의미를 리뷰하는 2-layer 구조.


솔직한 평가

잘된 것:

  • 5줄의 컨벤션이 19개의 구체적 위반 패턴으로 분해됐다. 사람이 직접 정리하면 30분은 걸릴 작업이다.
  • 판정 기준이 기계적이다. 리뷰어에 따라 기준이 흔들리는 문제가 구조적으로 해소된다.
  • 트리거의 경계 사례 처리가 실무적이다. “이 코드 봐줘”를 고려한 건 범용 도구에는 없는 디테일이다.

아쉬운 것:

  • 이벤트 핸들러 5줄 이상 = WARNING은 너무 기계적이다. 5줄짜리 switch-case는 문제없고, 3줄짜리 중첩 await는 문제일 수 있다. 라인 수보다 복잡도를 봐야 하는데, 현재 스킬은 라인 카운팅에 의존한다.
  • 팀 컨벤션이 하드코딩되어 있다. 다른 팀에서 이 스킬을 쓰려면 Phase 1~4의 테이블을 전부 수정해야 한다. 컨벤션을 외부 파일로 분리하면 재사용성이 올라간다.
  • 실제 PR에 대한 테스트를 아직 안 돌렸다. 이 글은 생성된 스킬의 구조 분석까지다. 실전 테스트는 별도로 진행해야 한다.

5줄 → 169줄

입력: 팀 컨벤션 5줄, 발동 조건 3개, 비발동 조건 3개.

출력: 5-Phase 파이프라인, 19개 위반 패턴, 심각도 3단계, 자동 판정 시스템, 경계 사례 처리, 리포트 포맷까지 갖춘 169줄짜리 스킬.

1편에서 분석한 skill-creator의 메커니즘 — TDD 루프, 과적합 방지, 트리거 최적화 — 이 실제로 작동하는 걸 확인했다. 특히 **“규칙이 아니라 원리를 가르쳐라”**는 철학이, 5줄의 컨벤션을 19개 패턴으로 확장하는 과정에서 그대로 드러났다.

다음 편에서는 입출력이 가장 명확한 스킬 — 릴리즈 노트 자동 생성 — 을 만들고, 기술 용어를 사용자 언어로 번역하는 파이프라인이 어떻게 설계되는지 본다.


관련 링크


컨벤션 위반을 지적하는 건 시니어의 일이 아니다. 시스템의 일이다.