릴리즈 노트 자동 생성 스킬 — git log를 사용자 언어로 바꾸기

2편에서는 코드 리뷰 스킬을 만들고 트리거 최적화를 봤다. 이번에는 입출력이 가장 명확한 스킬을 만든다. git log → 릴리즈 노트. 기술 용어를 사용자 언어로 “번역”하는 파이프라인이 어떻게 설계되는지가 이 편의 핵심이다.


누가 커밋 메시지를 읽는가

fix: null pointer in auth middleware

이 커밋 메시지를 이해할 수 있는 사람은 개발자뿐이다. 그런데 릴리즈 노트를 읽는 사람은 PM이고, 마케팅팀이고, 사용자다. “null pointer in auth middleware”를 읽고 “아, 로그인 오류가 고쳐졌구나”를 유추하는 건 개발자만 가능한 번역이다.

대부분의 스타트업에서 릴리즈 노트 작성은 이렇게 이루어진다:

  1. 시니어가 git log를 훑는다
  2. 머리속에서 “이건 사용자에게 해당되고, 이건 아니고…”를 분류한다
  3. 기술 용어를 사람 말로 바꿔 쓴다
  4. 30분~1시간 소모. 매번.

이 작업은 반복적이고, 입출력이 명확하며, 대부분의 팀에서 구조도 비슷하다. 그래서 skill-creator가 가장 빛나기 쉬운 후보이기도 하다.

여기서 더 깊은 질문을 해보자. 왜 개발자와 사용자는 같은 사건을 다른 언어로 말하는가?

커밋 메시지는 개발자가 자기 자신을 위해 쓴다. “나중에 이 변경의 이유를 추적하기 위해.” 릴리즈 노트는 사용자를 위해 쓴다. “나에게 어떤 변화가 있는지 알기 위해.” 같은 조직 안에서 같은 사건에 대한 두 개의 언어가 존재하는 것 — 이건 조직의 커뮤니케이션 구조의 문제다. 이 스킬이 자동화하는 건 단순한 텍스트 변환이 아니다. 더 정확히는, 조직 안에서 서로 다른 언어를 쓰는 사람들 사이의 자동 통역이다.


프롬프트는 이게 전부였다

릴리즈 노트를 자동 생성하는 스킬을 만들어줘.

입력: git log 또는 커밋 메시지 목록
출력: 사용자(비개발자)가 읽을 수 있는 릴리즈 노트

규칙:
- 커밋 메시지의 기술 용어를 사용자 언어로 번역한다
- "fix: null pointer in auth middleware" → "로그인 시 간헐적으로 발생하던 오류를 수정했습니다"
- feat, fix, chore, refactor 등 conventional commit prefix를 기능추가/버그수정/내부개선으로 그룹핑한다
- chore, ci, build 같은 사용자에게 무의미한 커밋은 릴리즈 노트에서 제외한다
- Breaking change가 있으면 최상단에 경고로 표시한다
- 한국어로 작성한다

이 스킬은 다음 상황에서 발동해야 한다:
- "릴리즈 노트 작성해줘"
- "이번 버전 변경사항 정리해줘"
- "changelog 만들어줘"
- git log 결과가 주어지고 정리를 요청할 때

이 스킬은 다음 상황에서 발동하면 안 된다:
- "커밋 메시지 작성해줘" (작성 ≠ 정리)
- "git log 보여줘" (조회 ≠ 변환)
- "이 커밋 뭘 고친 거야?" (분석 ≠ 릴리즈 노트)

2편과 같은 패턴이다. 규칙과 번역 예시 하나, 발동/비발동 조건. 포맷, 필터링 기준, 카테고리 순서는 지시하지 않았다.


176줄짜리 번역 시스템이 나왔다

2편의 코드 리뷰 스킬이 169줄, 5-Phase였다면, 이번 릴리즈 노트 스킬은 176줄, 4-Phase 변환 파이프라인이다.

구조가 2편과 다르다. 코드 리뷰 스킬은 “검사 → 판정”이었다면, 이 스킬은 **“파싱 → 필터링 → 번역 → 포맷팅”**이다. ETL(Extract-Transform-Load) 파이프라인과 같은 구조. 데이터를 넣으면 정제된 결과물이 나오는 공장이다.


Phase 1: 커밋 파싱 — Conventional Commit 분해기

첫 번째 단계부터 프롬프트에 없던 설계가 나왔다. Conventional Commit 형식(type(scope): description)을 4개 필드로 분해하는 파서:

필드추출 대상예시
typeprefix 키워드feat, fix, refactor
scope괄호 안 모듈명auth, payment
description콜론 이후 본문add social login support
breakingBREAKING CHANGE: 또는 !feat!: redesign auth flow

흥미로운 건 Conventional Commit 형식이 아닌 커밋도 처리한다는 점이다. “최대한 의도를 추론하여 분류”한다고 명시되어 있다. 현실적인 설계다 — 모든 팀이 Conventional Commit을 완벽하게 지키지는 않으니까.


Phase 2: 필터링 — “chore는 사용자에게 무의미하다”

프롬프트에서 “chore, ci, build는 제외하라”고 했다. AI가 이걸 10가지 커밋 타입별 포함/제외 매트릭스로 확장했다:

타입포함 여부이유
feat✅ 포함사용자가 체감하는 새 기능
fix✅ 포함사용자가 겪던 버그 해소
perf✅ 포함체감 성능 향상
refactor⚠️ 조건부사용자 체감 변화가 있을 때만
docs⚠️ 조건부사용자 대상 문서 변경 시에만
chore❌ 제외
ci❌ 제외
build❌ 제외
style❌ 제외
test❌ 제외

여기서 가장 날카로운 판단은 refactor를 조건부로 처리한 것이다:

refactor를 무조건 제외하지 마십시오. UI 구조 변경이나 API 응답 형태 변경 등 사용자 체감이 있는 리팩토링은 “내부 개선” 카테고리에 포함합니다.

프롬프트에서 refactor에 대해 아무 말도 안 했다. 그런데 AI는 “refactor라고 다 같은 refactor가 아니다”를 알고 있었다. extract payment service는 사용자에게 무의미하지만, redesign settings page layout은 사용자가 체감한다. 이 구분을 스스로 설계한 것이다.


Phase 3: 번역 — 이 스킬의 심장

여기가 핵심이다. 프롬프트에서 번역 예시를 1개 줬다. AI가 번역 원칙 4개 + 예시 6개로 확장했다.

번역 원칙

  1. 구현 디테일 제거 — 모듈명, 함수명, 변수명은 삭제
  2. 사용자 체감 영향으로 의역 — “무엇을 고쳤는가”가 아니라 “사용자에게 어떤 변화가 있는가”
  3. 한국어 경어체 — “~했습니다” 통일
  4. 한 줄 한 항목 — 한 문장으로 끝

번역 예시 — 직역 vs 의역 비교

원본❌ 나쁜 번역 (직역)✅ 좋은 번역 (의역)
fix: null pointer in auth middlewarenull pointer 에러를 auth middleware에서 수정로그인 시 간헐적으로 발생하던 오류를 수정했습니다
feat(payment): add kakao pay integrationpayment에 kakao pay integration 추가카카오페이 결제를 지원합니다
fix(ui): button overflow on mobileui에서 모바일 버튼 오버플로우 수정모바일에서 버튼이 화면 밖으로 밀려나던 문제를 수정했습니다
perf: lazy load images on feed피드에서 이미지 레이지 로드 적용피드 화면의 로딩 속도가 빨라졌습니다
refactor: extract payment servicepayment service 추출(제외 — 사용자 체감 없음)

이 테이블이 특히 좋은 이유는 “나쁜 번역”과 “좋은 번역”을 병치해 판단 기준을 학습시킨다는 점이다. 프롬프트에서는 좋은 예시 하나만 줬는데, AI는 거꾸로 나쁜 번역까지 스스로 상정해 금지선을 만들었다. 1편에서 봤던 skill-creator의 네거티브 패턴이 여기서도 드러난다.

마지막 줄이 특히 좋다: refactor: extract payment service(제외 — 사용자 체감 없음). Phase 2의 “조건부 제외” 규칙이 Phase 3의 번역 예시에서 실전으로 연결된다. Phase 간 일관성이 유지되고 있다.


Phase 4: 포맷팅 — 카테고리 순서까지 고정

최종 출력 형태도 프롬프트에 없던 설계다:

순서카테고리이모지
0⚠️ 주요 변경 사항 (Breaking)⚠️
1🚀 새로운 기능🚀
2🐛 버그 수정🐛
3⚡ 개선 사항
4📝 기타📝

Breaking Change가 항상 최상단이라는 규칙이 프롬프트의 “Breaking change가 있으면 최상단에 경고로 표시한다”를 정확하게 구현했다. 여기에 이모지까지 붙여서 시각적 스캐닝을 돕는다.

그리고 프롬프트에 없던 추가 규칙 3가지:

  1. 버전 번호 자동 추론git describe --tags로 최신 태그 조회
  2. 항목 수 제한 — 카테고리당 10개 초과 시 “외 N건”으로 축약
  3. 날짜 포맷 — “YYYY년 M월 D일” 한국어 표기

10개 초과 시 축약하는 규칙은 실무적이다. 릴리즈 노트가 커밋 50개를 나열하면 아무도 안 읽는다. **“지나치게 길어지는 것을 방지한다”**는 한 줄이 사용자 경험을 지키는 장치다.


2편과 무엇이 달랐나

비교 항목2편 (코드 리뷰)3편 (릴리즈 노트)
구조5-Phase 검사 파이프라인4-Phase 변환 파이프라인
목적위반 적발 + 판정데이터 변환 + 포맷팅
핵심 PhasePhase 5 (종합 판정)Phase 3 (번역)
입력git diff (코드)git log (텍스트)
출력APPROVE / REQUEST_CHANGES마크다운 릴리즈 노트
패턴Guard / ValidatorETL / Transformer

같은 skill-creator를 썼는데도, 도메인이 달라지자 구조가 완전히 달라졌다. 코드 리뷰는 판정 시스템이고, 릴리즈 노트는 번역 시스템이다. 이 차이를 별도 지시 없이 반영했다는 점이 바로 skill-creator의 힘이다.


솔직한 평가

잘된 것:

  • 번역 예시의 “나쁜 번역 vs 좋은 번역” 대비가 강력하다. 이 테이블만으로도 스킬의 가치가 증명된다.
  • refactor 조건부 처리가 실무적이다. 무조건 포함도, 무조건 제외도 아닌 “사용자 체감 여부”라는 기준을 세운 것.
  • 카테고리당 10개 제한은 작은 규칙이지만 사용자 경험에 큰 차이를 만든다.

아쉬운 것:

  • 커밋 → 기능 매핑이 1:1이다. feat(auth): add social login button, feat(auth): add google oauth flow, feat(auth): add login redirect — 이 3개 커밋은 사용자에게 “소셜 로그인이 추가되었습니다” 한 줄이다. 현재 스킬은 커밋 단위로 1:1 변환하는데, N:1 매핑(여러 커밋 → 하나의 기능)이 없다. 릴리즈 노트의 진짜 어려움은 이 그룹핑이다.
  • release-pleasesemantic-release와 비교가 필요하다. 이미 성숙한 도구가 있다. 차이점: 기존 도구는 커밋 메시지를 그대로 나열한다. 이 스킬은 의역한다. “fix: null pointer in auth middleware” → “로그인 오류 수정”. 이 번역 레이어가 기존 도구에는 없는 고유 가치지만, 필터링과 포맷팅은 release-please가 더 안정적이다. 이상적으로는 기존 도구의 출력을 이 스킬의 번역 Phase에 넣는 하이브리드 구조가 최선일 수 있다.
  • 번역 품질은 결국 AI의 도메인 이해도에 달려있다. fix: race condition in websocket reconnect 같은 커밋을 “웹소켓 재연결 시 경합 조건 수정”으로 직역할지, “실시간 알림이 가끔 누락되던 문제를 수정했습니다”로 의역할지는 AI가 비즈니스 컨텍스트를 알아야 가능하다. 스킬만으로는 한계가 있다.

규칙 6줄 → 번역 시스템 176줄

입력: 번역 규칙 6줄, 예시 1개, 발동/비발동 조건.

출력: Conventional Commit 파서, 10-타입 필터링 매트릭스, 4원칙 번역 엔진, 카테고리 자동 정렬, 버전 추론, 항목 수 제한까지 갖춘 176줄짜리 스킬.

2편에서 “5줄 → 169줄”이었고, 이번에는 “6줄 → 176줄”이다. 입력의 양이 아니라 도메인의 깊이가 출력을 결정한다. skill-creator는 짧은 프롬프트에서 도메인 지식을 끌어내 구조화하는 데 일관되게 강하다.

다음 편에서는 가장 까다로운 스킬 — 온보딩 문서 자동 생성 — 을 만들고, 1편에서 skill-creator가 가장 경계한 문제 **“과적합”**과 정면으로 부딪힌다.


관련 링크


개발자의 커밋 메시지는 개발자를 위해 쓴다. 릴리즈 노트는 사용자를 위해 쓴다. 같은 사건, 다른 언어. 그 번역을 시스템화한 것이 이 스킬이다.