
AI가 자동 생성한 커밋 메시지 200건을 분류했더니 규약 준수는 4할뿐이었다
요약
AI가 생성한 커밋 메시지 200건을 Conventional Commits 규약으로 분석한 결과, 완전 준수율은 43%에 불과했습니다. AI는 형식적인 접두사는 잘 갖추지만, 메시지의 길이, 명령형 사용, 단일 논점 유지 등 세부 규약 준수에는 한계를 보였습니다.
핵심 포인트
- AI 생성 커밋 메시지의 Conventional Commits 완전 준수율은 43% 수준
- AI는 외형적 형식(type 접두사)은 잘 갖추나 세부 규약 준수 능력은 낮음
- 형식적 정돈과 실제 규약 만족 사이에는 큰 간극이 존재함
- 버그 추적을 위한 고품질 커밋 히스토리 관리를 위해 주의 필요
먼저 결론부터 말씀드리겠습니다. AI가 자동 생성한 커밋 메시지 200건을 Conventional Commits 규약으로 분류했습니다. 완전히 준수했던 것은 86건, 43%였습니다. 나머지 6할 가까이는 type 선택을 틀리거나, subject가 너무 길거나, 1개 커밋에 여러 변경 사항을 몰아넣고 있었습니다.
"AI에게 맡기면 커밋 메시지는 깔끔해질 것이다". 저는 그렇게 기대했습니다. 확실히 feat:나 fix: 같은 형식을 갖춥니다. 차분(diff)을 보고, 그럴듯한 접두사(prefix)를 붙이고, 그럴듯한 한 문장을 작성합니다. 겉모습만 본다면 인간이 대충 쓰는 것보다 정돈되어 있습니다.
하지만 형식과 내용은 별개였습니다. 반년 뒤에 버그를 추적할 때, 커밋 히스토리는 "무엇을・왜 바꿨는가"를 알려주는 지도가 됩니다. 그 지도로서 사용할 수 있는가라는 기준으로 보면, 4할밖에 합격하지 못했습니다. 이 기사는 그 200건을 한 건씩 분류한 기록입니다.
선을 긋겠습니다. Claude Code의 Git 조작에 대해서는 전에도 썼습니다. git add나 git commit을 배후에서 어떻게 하고 있는가에 대한 조작 설명입니다.
이 기사는 그것과는 다릅니다. 다루는 것은 AI가 내뱉은 커밋 메시지 그 자체의 품질입니다. 규약에 따르고 있는가, type은 올바른가, 내용을 설명하고 있는가. 조작의 메커니즘이 아니라 성과물을 채점합니다.
왜 지금 이것을 측정했느냐 하면, AI에게 커밋까지 맡기는 사람이 단번에 늘어났기 때문입니다. 차분을 전달하면 메시지가 돌아오기 때문에, 나도 모르게 전부 맡기고 싶어집니다. 저도 그랬습니다. 하지만 맡긴 결과가 어떤 품질인지 아무도 세어보지 않았습니다. 그렇다면 직접 세어보자, 라는 것이 이번 검증의 동기입니다.
추측이 아닙니다. 조건을 제시하겠습니다.
- 대상: AI 코딩 툴이 자동 생성한 커밋 메시지 200건
- 수집원: 저의 검증용 리포지토리 여러 개의 히스토리
- 기준: Conventional Commits 1.0.0 사양
- 판정:
type(scope): subject
형식・subject 50자 이내・명령형・1커밋 1논점을 충족하는가 - 분류: 완전 준수 / 부분 일탈 / 비준수의 3단계로 수작업
"부분 일탈"은 type은 붙어 있지만 다른 요소를 놓친 경우입니다. "비준수"는 애초에 type: 형식이 되어 있지 않은 것입니다. 판정은 제가 한 건씩 눈으로 확인했습니다. 자동 판정으로는 "형식은 통과하지만 의도가 어긋난" type 선택 실수를 잡아낼 수 없기 때문입니다. 수작업을 한 이유는 그 부분을 정확하게 세고 싶었기 때문입니다.
| 구분 | 건수 | 비율 | 내용 |
|---|---|---|---|
| 완전 준수 | 86 | 43% | 형식・길이・명령형・1논점 모두 충족 |
| ... | type: 형식이 되어 있지 않음 |
형식만 보면 type:이 붙어 있었던 것은 177건(89%)이었습니다. 대부분 feat:나 fix:는 붙어 있었습니다. 하지만 "형식이 정돈되어 있다"와 "규약을 만족한다"는 별개였으며, 후자는 43%까지 떨어졌습니다. 9할이 "준수하는 것처럼 보임"에도 불구하고, 실제로 준수하고 있는 것은 4할. 이 차이가 AI에게 커밋을 맡겼을 때의 실태였습니다.
구체적인 예를 들겠습니다. 다음 세 가지는 모두 AI가 생성한 실제 패턴에 가까운 것입니다.
# 완전 준수
feat(auth): add password reset endpoint
# 부분 일탈(type은 붙지만 subject가 너무 길거나 명령형이 아님)
...
가운데 예시가 까다롭습니다. fix:가 붙어 있어서 언뜻 보기에는 준수하는 것처럼 보입니다. 하지만 subject는 50자를 초과했고, 명령형도 아니며, 과거형 보고 문장이 되어 있습니다. 접두사(prefix)만으로 판정하면 이것을 "준수"로 세게 됩니다.
AI는 feat: fix:의 외형을 거의 확실하게 붙여옵니다. 하지만 외형이 갖춰지는 것과 규약을 따르는 것은 달랐습니다. 접두사의 유무만으로 "준수하고 있다"고 판단하면 절반 이상을 놓치게 됩니다.
부분 일탈·비준수 114건을 분류하면 원인은 세 가지로 집중되었습니다.
일탈 114건의 내역은 subject 초과 41건, type 선택 실수 38건, 복수 변경 혼재 35건이었습니다. 깔끔하게 세 가지로 나뉘었습니다.
1. subject가 너무 길다 (41건)
가장 많은 일탈 사례입니다. 「fix: 사용자 등록 시 이메일 주소 중복 체크가 작동하지 않던 문제를 수정하고 유효성 검사를 추가」와 같이, 한 줄에 설명을 모두 집어넣습니다. AI는 생략하기보다 망라하는 쪽을 택하기 때문에, subject가 80자를 초과하는 일이 드물지 않았습니다. 50자의 벽을 AI도 알고는 있지만 지키지는 않았습니다.
2. type 선택 실수 (38건)
다음으로 많은 것이 type의 오용입니다. 신기능인데 chore:, 단순 리팩토링인데 fix:, 설정 변경을 feat:로 작성하는 경우입니다. 차분(diff)의 의미를 잘못 읽으면 type도 어긋나게 됩니다. 특히 "동작은 바꾸지 않았지만, 외관을 정돈했다"와 같은 변경을 fix:로 작성하는 경향이 있었습니다. fix는 "버그 수정"을 의미하지만, AI는 "무언가를 고쳤다"는 것을 전부 fix로 몰아가는 경향이 있었습니다. 리네임(rename)이나 주석 추가까지 fix:로 작성된 사례도 있었습니다.
반대의 패턴도 있습니다. 실제로는 버그 수정임에도 chore:나 refactor:로 대충 넘겨버리는 경우입니다. 이런 일이 발생하면, 릴리스 노트(release note)를 feat/fix를 기반으로 자동 생성하는 현장에서는 수정 사항이 노트에서 누락됩니다. type의 실수는 겉보기보다 실질적인 피해가 큽니다.
3. 여러 변경 사항을 한 커밋에 혼재 (35건)
feat:라고 쓰면서 신기능과 버그 수정, 포맷 변경이 한 커밋에 공존하는 케이스입니다. AI는 "세션에서 수행한 작업을 모아서 한 번에 한 커밋으로 만든다"는 경향이 있어, 1논점 1커밋(one issue, one commit) 원칙에서 벗어납니다. type를 하나로 결정할 수 없는 시점에서 이미 규약의 전제가 무너진 것입니다.
이런 현상이 발생하는 이유는 커밋의 단위를 AI에게 맡기고 있기 때문입니다. 한 세션에서 여러 가지 일을 하고 마지막에 한꺼번에 한 커밋으로 만듭니다. 그렇게 되면 그 한 커밋은 여러 종류의 변경 사항을 떠안게 되어, feat:라는 단 하나의 type로는 다 설명할 수 없게 됩니다. 커밋을 나누는 판단은 차분의 의미를 이해하지 못하면 할 수 없습니다. 그리고 그것은 현재로서는 인간이 더 잘하는 작업이었습니다.
완전 준수된 86건의 type를 집계해 보면 확연한 편향이 나타납니다.
| type | 비율 |
|---|---|
| feat | 38% |
| ... |
feat와 fix가 6할을 넘습니다. AI는 판단이 어려우면 무난한 feat나 fix로 치우치는 버릇이 있었습니다. refactor나 test처럼 차분의 의도를 정확히 읽어야만 선택할 수 있는 type는 인간이 작성할 때보다 적었습니다.
실제 현장에서는 테스트를 추가하는 커밋도, 의존성(dependency)을 업데이트하는 커밋도, 문서를 수정하는 커밋도 나름의 빈도로 존재해야 합니다. 그럼에도 test가 4%, docs가 7%밖에 되지 않는 것은, AI가 "테스트 추가"를 feat의 일부로 뭉뚱그려 처리하고 있기 때문이라고 보고 있습니다. type의 분포가 실태와 어긋나 있는 시점에서, 나중에 type별로 이력을 집계하더라도 정확한 수치가 나오지 않습니다.
여기서 아이러니한 연구를 하나 소개하겠습니다. 2026년에 발표된 보안 커밋(security commit) 대규모 조사에 따르면, 규약을 준수한 커밋이 준수하지 않은 커밋보다 정보량이 적은 경향이 보고되었습니다 (On the Informativeness of Security Commit Messages).
즉, fix:라는 틀에 가두다 보면 "무엇을·왜 고쳤는지"가 깎여 나가기 쉽습니다. 형식을 지키는 것 자체가 설명을 빈약하게 만드는 측면이 있는 것입니다. 틀에 맞추려는 의식이 강할수록, 틀 밖으로 나가는 배경 설명은 버려지게 됩니다.
저의 200건 사례에서도 비슷한 일이 일어나고 있었습니다. 완전 준수된 86건의 대부분은 subject는 깔끔하지만 body가 비어 있었습니다. "왜 이 변경을 했는지"가 남아 있지 않았습니다. feat(auth): add password reset endpoint는 규약상으로는 만점입니다. 하지만 "왜 지금 이것을 추가했는지", "어떤 요구사항이 있었는지"는 어디에도 적혀 있지 않았습니다. 규약은 통과했을지 몰라도, 반년 뒤의 자신에게는 불친절했습니다.
여기서 중요한 것은 규약 준수율을 높이는 것 자체를 목적으로 삼지 않는 관점입니다. 준수율은 측정하기 쉽기 때문에 자칫 지표로 삼고 싶어지기 마련입니다. 하지만 우리가 정말로 원하는 것은 "읽었을 때 의도를 알 수 있는 이력"이지, "규약을 통과하는 이력"이 아닙니다. 수단을 목적으로 착각하면, AI가 잘하는 "형태를 다듬는 일"만 진행되고, 인간이 쥐고 있어야 할 "의도를 남기는 일"은 뒷전으로 밀려나게 됩니다.
커밋 메시지의 목적은 규약을 충족하는 것이 아니라, 나중에 읽는 사람(미래의 자신)에게 변경 의도를 전달하는 것입니다. AI에게 맡기면 전자는 올라가지만, 후자는 자동으로 올라가지 않습니다.
지금까지 언급한 일탈 중 형식 관련(subject 초과·type 형식)은 사실 도구로 기계적으로 걸러낼 수 있습니다. commitlint를 사용하면 규약에서 벗어난 커밋을 커밋 시점에 차단할 수 있습니다.
# commitlint로 Conventional Commits 준수를 강제하는 예
echo "fix: 사용자 등록 시 유효성 검사가 작동하지 않던 문제를 수정했습니다" \
| npx commitlint
...
이를 도입하면 형식 준수율은 기계적으로 100% 가까이 올라갑니다. 하지만 여기에 함정이 있습니다. 도구가 지킬 수 있는 것은 형식뿐입니다. type가 내용에 맞는지, body에 「왜(why)」가 적혀 있는지는 commitlint가 판정할 수 없습니다.
즉, 도구를 도입하더라도 「형식은 정돈되어 있지만 의도를 알 수 없는 이력」은 양산될 수 있습니다. 형식의 준수와 이력으로서의 유용성은 별개로 지켜야 합니다.
제 결론은 "AI에게 커밋 메시지를 쓰게 하지 마라"가 아닙니다. **"type과 body만큼은 스스로 쥐어라"**입니다.
구체적으로는 3가지로 정리했습니다.
- 1커밋 1논점으로, 차이(diff) 단계에서 분리한다 (이것은 AI에게 맡기지 않고 스스로 한다)
- AI에게는 subject의 초안을 쓰게 하고, 50자로 줄이는 것은 스스로 한다
- 「왜 이 변경을 했는가」를 body에 한 줄 추가한다. 이 부분은 AI가 쓸 수 없다
세 번째 항목을 보충하겠습니다. AI는 차이(what)는 읽을 수 있지만, 「왜 그것을 했는가(why)」는 이력 외부에 있습니다. 예를 들어 「타임아웃을 30초로 늘렸다」는 AI도 쓸 수 있지만, 「운영 환경에서 외부 API가 지연되어 리트라이(retry) 전에 타임아웃이 발생했기 때문에 늘렸다」는 배경은 그 자리에 있었던 인간만이 압니다. 반년 뒤에 버그를 추적할 때 도움이 되는 것은 후자입니다.
프롬프트(prompt)를 개선하는 방법도 하나 찾아냈습니다. AI에게 커밋 메시지를 부탁할 때, "subject는 50자 이내, 명령형으로. body에는 변경 이유를 한 줄. type이 고민된다면 후보를 2개 제시해줘"라고 덧붙이면 통째로 맡기는 것보다 훨씬 나아집니다. 완벽해지지는 않지만, subject 초과는 눈에 띄게 줄었습니다. 그럼에도 마지막 type과 body의 확정은 제 손으로 직접 쥐고 있습니다.
처음에 "포석을 깔아두면 나중에 편해진다"는 것은 커밋 이력에서도 마찬가지였습니다. 지금 정성스럽게 나누어 두면, 반년 뒤에 버그를 추적할 때 과거의 자신에게 도움을 받을 수 있습니다. 제가 '신장의 야망'이라는 게임을 오래 하면서 몸에 밴 것은, 이 "나중에 효과를 발휘할 한 수를 지금 두는" 감각입니다. 커밋 이력은 미래의 자신을 위한 포석이라고 생각합니다.
- AI 생성 커밋 200건 중 규약에 완전 준수한 것은 43%
type:형식은 89%에 나타나지만, 형식이 정돈되는 것과 규약을 충족하는 것은 별개- 일탈의 3대 패턴은 subject 초과·type 선택 실수·복수 변경의 혼재
- type은
feat/fix에 편중되며, AI는 고민될 경우 무난한 type으로 치우침 - 형식은 commitlint로 지킬 수 있지만, type의 정확성과 body의 「왜(why)」는 지킬 수 없음
- 규약 준수만으로는 정보량이 늘어나지 않음. type과 body는 스스로 쥐는 것이 현실적인 해답
AI에게 맡길 범위와 스스로 쥐어야 할 범위를 나누는 것. 이것은 커밋 메시지에 국한되지 않고, AI와 협업할 때의 기본이라고 생각합니다. 전부 맡기면 품질이 4할로 떨어지고, 전부 스스로 하면 속도의 혜택을 버리게 됩니다. 초안은 AI, 최종 판단은 인간. 이 선긋기가 현재로서는 가장 잘 작동하고 있습니다.
AI는 커밋의 형식을 갖추는 데 능숙합니다. 하지만 「왜」를 남기는 것은 아직 인간의 일이었습니다. 즐겁게 해봅시다.
AI에게 개발을 맡기면서 커밋이나 리뷰의 마지막 1%를 스스로 쥐는 운영 방식에 대해서는 이쪽에 자세히 정리해 두었습니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Qiita AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기