# Conventional Commits 사용을 중단하라

> Clean Markdown view of GeekNews topic #30224. Use the original source for factual precision when an external source URL is present.

## Metadata

- GeekNews HTML: [https://news.hada.io/topic?id=30224](https://news.hada.io/topic?id=30224)
- GeekNews Markdown: [https://news.hada.io/topic/30224.md](https://news.hada.io/topic/30224.md)
- Type: GN+
- Author: [neo](https://news.hada.io/@neo)
- Published: 2026-06-06T11:02:21+09:00
- Updated: 2026-06-06T11:02:21+09:00
- Original source: [sumnerevans.com](https://sumnerevans.com/posts/software-engineering/stop-using-conventional-commits/)
- Points: 1
- Comments: 1

## Topic Body

- **Conventional Commits**는 `&lt;type&gt;[optional scope]: &lt;description&gt;` 형식으로 커밋 메시지에 의미를 부여하려 하지만, 변경 유형을 앞세우고 범위를 선택사항으로 둬 실제 탐색에 필요한 정보를 뒤로 미룸
- 기여자·디버거·장애 대응자는 커밋 로그에서 변경이 닿은 코드 영역을 찾으며, 버그는 어떤 유형의 변경에서도 생길 수 있어 **범위(scope)** 가 유형보다 중요함
- `fix(compiler): prevent namespaced SVG &lt;style&gt; elements from being stripped`처럼 설명만으로도 버그 수정 성격을 알 수 있고, `refactor(core): Update webmcp support to use document.modelContext`처럼 한 커밋이 수정·리팩터링·기능 추가에 걸칠 수 있어 **type**이 중복적이고 제한적임
- 자동 **CHANGELOG** 생성과 시맨틱 버전 증가 판단은 커밋 로그와 변경 로그의 독자가 다르고, 되돌리기·우발적 하위 호환성 깨짐·나중의 깨짐 해소 때문에 결과가 어긋날 수 있음
- **범위 접두사** 커밋 메시지는 변경 주체를 먼저 보여 주며, 빌드·배포 조건도 제목 유형보다 `git diff`로 바뀐 파일을 기준으로 삼는 편이 낫음

---

### 잘못된 우선순위
- [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/)는 커밋 메시지에 의미를 부여해 개발자와 최종 사용자가 변경을 이해하도록 돕겠다는 목표를 가짐

```text
&lt;type&gt;[optional scope]: &lt;description&gt;

[optional body]

[optional footer(s)]
```

- 제목 줄은 `fix`, `feat`, `chore`, `docs`, `refactor` 같은 `&lt;type&gt;`, 선택적 scope, description으로 구성됨
- 핵심 결함은 변경의 주체인 **scope**보다 변경 종류인 type을 우선하는 구조임
- scope가 선택사항인 구조는 커밋에서 가장 중요한 정보가 빠질 수 있게 만들고, type을 제목 맨 앞에 둬 우선순위를 뒤집음

### scope가 type보다 중요한 이유
- 기여자는 마지막 기여 이후의 변화, 프로젝트의 전체 흐름, pull이나 rebase 때 진행 중인 작업과 충돌할 수 있는 커밋을 찾기 위해 커밋 로그를 읽음
- 디버거는 버그가 드러난 컴포넌트와 관련된 영역을 건드린 변경을 찾으며, 버그는 어떤 type의 변경에서도 생길 수 있어 type 정보가 도움이 되지 않음
- 장애 대응자는 장애 시점 주변의 커밋 로그를 훑어 문제를 일으킨 영역을 찾으며, 인바운드 API 오류 급증 지점에 `auth` scope 커밋이 있으면 유력한 원인 후보가 됨
- 커밋 로그를 읽는 사람에게 중요한 정보는 변경이 어떤 종류였는지가 아니라 어떤 영역을 건드렸는지임

### type의 중복성과 제한
- [`fix(compiler): prevent namespaced SVG &lt;style&gt; elements from being stripped`](https://github.com/angular/angular/commit/ec138c3645f6e28829e69b6da2a839c248bb3bf0)는 description만으로도 버그 수정임을 알 수 있어 `fix` type이 중복됨
- 커밋 제목 줄의 공간은 제한적이므로 description에서 알 수 있는 type에 문자를 쓰는 방식은 도움이 되지 않음
- [`refactor(core): Update webmcp support to use document.modelContext`](https://github.com/angular/angular/commit/683172b39a602ac9ec15db69d22853433a67a084)는 `core` 컴포넌트의 `webmcp` 기능을 `document.modelContext`와 `navigator.modelContext` 모두 지원하도록 업데이트함
- 이 변경은 버그 수정, 리팩터링, 새 기능으로 동시에 볼 수 있지만, 실제로 중요한 정보는 `core/webmcp` 컴포넌트에 대한 변경이라는 점임

### 자동화 약속의 한계
- [git-cliff](https://git-cliff.org/)나 [conventional-changelog](https://github.com/conventional-changelog/conventional-changelog) 같은 도구로 커밋에서 CHANGELOG를 자동 생성하는 발상은 커밋 로그와 변경 로그의 독자가 다르다는 문제를 가짐
- CHANGELOG는 사용자 대상이며 버전 간 기능적·비즈니스적 차이를 이해하는 데 초점이 있음
- 커밋 로그는 개발자 대상이며 코드베이스가 시간에 따라 어떻게 바뀌었는지와 scope 관점의 흐름을 읽는 데 초점이 있음
- 중간 이상의 복잡도를 가진 프로젝트에서는 의미 있는 기능 하나가 여러 커밋으로 들어가며, 개발자에게는 구현 과정이 유용하지만 최종 사용자에게는 새 기능 자체만 중요함
- 되돌리기(revert) 커밋은 개발자에게 커밋 로그의 흐름상 중요하지만, 최종 사용자에게는 되돌려진 변경이 만들어지지 않은 변경과 같음
- 커밋 type에 기반한 시맨틱 버전 증가는 하위 호환성을 깨는 변경이 되돌려졌는데도 major 버전을 올리거나, 나중에야 깨짐을 알아차려 minor/patch로 잘못 올리거나, 후속 커밋과 합쳐져 깨짐이 사라졌는데도 깨짐으로 판단하는 문제를 만들 수 있음
- 이런 상황에서 rebase로 히스토리를 고칠 수는 있지만, 워크플로가 이를 막거나 깨뜨릴 수 있고 커밋 로그가 전하는 흐름의 신뢰성을 낮춤
- 커밋 제목 type으로 빌드·배포 프로세스를 트리거하면 `docs: fix typos`라는 제목의 커밋이 인증 서브시스템에 취약점을 넣는 식으로 자동 도구를 우회할 수 있음
- 빌드·배포 조건은 커밋 제목보다 `git diff`로 변경 파일을 식별해 정하는 편이 낫음

### 적용 문제와 대안
- Conventional Commits는 프로젝트별 type 집합을 정의하게 하지만, 많은 프로젝트가 [commitlint](https://github.com/conventional-changelog/commitlint)의 기본 type을 그대로 가져가며 개별 프로젝트 특성과 잘 맞지 않을 수 있음
- Conventional Commits 명세는 기술적으로 `fix`와 `feat`만 정의하고 추가 type은 프로젝트에 맡김
- 기업 환경에서는 변경 관리와 감사 요구로 모든 커밋 메시지에 티켓 번호를 넣어야 하는 경우가 있으며, `&lt;scope&gt;`가 티켓 번호 자리로 쓰이면 유용한 metadata가 사라짐
- Linux, FreeBSD, Git, Go, NixOS, Node.js는 프로젝트에 맞는 scope 접두사 커밋 메시지를 사용함

| 프로젝트 | 형식 | 예시 |
| --- | --- | --- |
| [Linux](https://www.kernel.org/doc/html/v4.14/process/submitting-patches.html) | `subsystem: description` | [`i2c: virtio: mark device ready before registering the adapter`](https://github.com/torvalds/linux/commit/1d774589f924) |
| [FreeBSD](https://freebsdfoundation.org/wp-content/uploads/2020/11/Writing-Commit-Messages.pdf) | `prefix: Description` | [`linuxulator: Return EINVAL for invalid inotify flags`](https://github.com/freebsd/freebsd-src/commit/f77d37cffdf3) |
| [Git](https://git-scm.com/docs/SubmittingPatches) | `area: description` | [`gitlab-ci: update macOS image`](https://github.com/git/git/commit/62319b49bbe7) |
| [Go](https://go.dev/wiki/CommitMessage) | `package: description` | [`net/http/cookiejar: add godoc links`](https://github.com/golang/go/commit/517d4d3c7976) |
| [nixpkgs](https://github.com/NixOS/nixpkgs/blob/master/CONTRIBUTING.md) | `pkg-name: description` | [`xwayland: 24.1.11 -> 24.1.12`](https://github.com/NixOS/nixpkgs/commit/7bf858875a54) |
| [Node.js](https://github.com/nodejs/node/blob/main/doc/contributing/pull-requests.md#commit-message-guidelines) | `subsystem: description` | [`stream: fast-path stateless transform flush results`](https://github.com/nodejs/node/commit/5f727fdc89c06782652bfbf6a4d05ade1db3d2c8) |

- Linux 커널에서는 subsystem, Go 프로젝트에서는 package path, 마이크로서비스 아키텍처에서는 microservice 이름이 자연스러운 scope가 됨
- [scopedcommits.com](https://scopedcommits.com/)은 커밋 메시지에서 scope 중심 형식으로 돌아가고, CHANGELOG 생성과 커밋 로그 관리를 분리하자는 방향을 다룸
- Conventional Commits의 장점은 실제 이점으로 이어지지 않았고, 오픈소스 프로젝트에서의 인기와 AI의 기본 선택 경향이 안티패턴이 섞인 커밋 메시지 확산을 낳음

## Comments



### Comment 59017

- Author: neo
- Created: 2026-06-06T11:02:23+09:00
- Points: 1

###### [Lobste.rs 의견들](https://lobste.rs/s/oqlpna/stop_using_conventional_commits) 
- **conventional commits**에 대한 반박을 본능적 거부감 말고 논리로 정리한 글이라 반갑다  
  왜 싫은지 깊게 생각해보진 않았고, LLM이 생성한 코드와 연관 짓게 된 탓인가 싶었음. 특히 `chore:`가 제일 싫은데, 헝가리안 표기법을 다시 발명하지 말았으면 함. 애초에 만들어지지 말았어야 함
  - 특히 `chore:`는 더 이상 **Angular 커밋 스타일 가이드**에도 없고, 너무 모호하다는 걸 깨달았는지 `build:`에 흡수됨  
    Angular 스타일에 있던 시절에도 `chore:` 설명은 꽤 구체적인 용도를 제시했는데, 일부 오픈소스 프로젝트에서는 말 그대로 하기 귀찮은 일처럼 느껴지는 작업에 분위기로 붙이는 듯함

- conventional commits를 좋아하진 않지만, 제안된 대안은 **scope가 선택 사항인 이유**를 놓치는 것 같음  
  뚜렷한 모듈이 많지 않은 작은 프로젝트에서는 “scope”라는 개념이 별로 유용하지 않음. 둘 다 빠뜨린 유용한 관행으로, 커밋 제목에 이슈나 티켓 번호를 넣으면 변경의 추가 맥락을 파악하기 쉬워지고 코드 리뷰 때 특히 도움이 됨. 다만 티켓 번호를 필수로 만들면 사소한 변경에도 쓸모없는 티켓이 양산되니 싫고, 특정 버그나 작업을 처리하는 변경이라면 해당 버그나 작업으로 연결돼야 함
  - scope가 필요 없으면 그냥 생략하면 됨  
    제목 줄만 봐도 드러나야 할 중복된 커밋 “type”보다 여전히 낫다
  - 이상적으로는 어떤 **규정된 커밋 스타일**도 없이, 특정 커밋에 맞는 표현을 쓰면 된다고 봄  
    변경이 티켓과 명확히 대응되면 “티켓 번호” 커밋을 쓰고, 그렇지 않으면 다른 방식을 쓰면 됨. 어떤 변경은 type에는 잘 맞지만 scope에는 덜 맞고, 반대도 있으니 scoped commits와 conventional commits를 섞어 쓸 수도 있음

- “문단 텍스트에는 **고정폭 글꼴**을 쓰지 말라”고 말하고 싶음  
  그래도 글의 전제에는 대체로 동의함

- 커밋 메시지가 별로여도 변경 범위를 감잡으려면 `git log --name-only`나 `git log --stat`를 자주 써보는 걸 추천함  
  파일명을 보면 각 커밋을 전부 열어보지 않아도 무엇이 바뀌었는지 아는 데 꽤 도움이 됨

- 정말 마음에 드는 방식은 **PR 제목에 conventional commit 스타일을 강제**하는 것임  
  PR 제목은 병합 후에도 maintainer가 수정할 수 있고, 커밋 기록을 다시 쓸 필요도 없으며, [release-drafter](https://github.com/release-drafter/release-drafter) 같은 도구와 함께 쓰면 GitHub 릴리스에서 의미 있는 변경 로그를 자동화할 수 있음. 작성자가 말한 이해관계자에게 맞는 적절한 입도, 즉 기능·수정·호환성 깨짐을 나눠 보여주고 다음 GitHub 릴리스 초안의 합리적인 semver도 자동으로 처리해 줌  
  `parse-lib` 같은 컴포넌트가 선택 사항이어서는 안 된다는 글의 지적은 맞고, conventional commits를 강제하면 새 기여가 위축된다는 데도 동의함. 하지만 대안들이 딱히 더 낫진 않음  
  그래도 호환성 깨짐 식별자인 `fix!(parse-lib): Don't leave sparse holes when parsing JSON arrays`는 꽤 많은 정보를 줌. 특정 컴포넌트의 버그 수정이고, 그 수정에 불가피하게 따라온 호환성 깨짐이며, minor semver 증가 같은 의미를 담고 있음. 이런 건 PR 제목에 쓸 수 있음

- 커밋 규율을 장려하는 방법으로 conventional commits에 너무 빠졌고, 결국 습관으로 굳어졌음을 인정함  
  지금은 종종 제한적이고 임의적이라고 느낌. 몇몇 프로젝트에서는 그게 실제 관례인지도 모르고 Linux/Go/Node 스타일에 가까워졌는데, 다양한 설정이 있는 monorepo에서는 type을 억지로 만들기보다 `[service]: [what changed]`라고 쓰는 편이 자연스러웠음. 앞으로는 엄격한 관례에 맞추기보다 무엇이 유용해 보이는지 기준으로 개인 커밋 스타일을 더 실험해볼 생각이고, scoped commits는 좋은 출발점처럼 느껴짐

- `chore(lobsters): add my 2 cents on conventionals commits [JIRA-69420]`  
  거의 전부 동의하지만, “커밋 로그가 말하는 이야기의 신뢰성을 낮추는 수정주의적 기록을 기여자에게 보여준다”는 부분은 하나 다르게 봄. 작성자는 주로 공개 브랜치를 말하는 것 같은데, 공개 브랜치라면 합리적인 조언임. 하지만 비공개 브랜치에는 적용되지 않아야 함. 최종 변경을 리뷰하는 사람, 즉 maintainer나 10년 뒤의 내가 이해하기 쉽게 만들면 되지, 앞뒤 안 맞는 사고 흐름이나 더 나쁘게는 `address review` 커밋 묶음을 남길 필요는 없음

- “왜 scope가 선택 사항인가?”에 대한 답은 작은 프로젝트에는 그냥 **프로젝트 전체가 scope**이기 때문임  
  커밋의 “type”이 그다지 유용하지 않다는 데는 동의하지만, scoped commits와 conventional commits 사이에 큰 차이가 있는지도 잘 모르겠음. scoped는 “type”이 빠진 conventional일 뿐이고, fix·feat·refactor·chore 구분은 있어도 괜찮은 구분임  
  다들 commitlint 기본값을 그대로 가져다 쓴다면, 사람들이 더 잘 다루게 만들면 되는 일 아닐까 싶음
