좋은 커밋 메시지는 한눈에 변경 내용의 의도와 범위를 파악할 수 있어야 한다. 기본 구조는 제목(Subject), 본문(Body), 바닥글(Footer)의 3단계 구성을 따른다. 각 영역은 빈 줄(New Line)로 구분한다.
type(scope): 제목 (Subject)
본문 (Body) - 생략 가능
바닥글 (Footer) - 생략 가능
제목은 컨벤션의 핵심이다. 현업에서 가장 많이 쓰이는 7가지 대표 Type을 숙지하고 일관되게 사용한다.
| 타입 (Type) | 언제 사용하는가? |
|---|---|
feat | 새로운 기능(Feature)을 추가할 때 |
fix | 버그를 수정할 때 |
docs | 문서(README, 주석, 위키 등)를 수정할 때 |
style | 코드 의미에 영향을 주지 않는 스타일 변경 (포맷팅, 세미콜론 누락 등) |
refactor | 기능 추가나 버그 수정 없이 코드를 리팩토링할 때 |
test | 테스트 코드를 추가하거나 수정할 때 |
chore | 빌드 업무, 패키지 매니저 설정, .gitignore 등 자잘한 기타 작업 |
💡 Scope(범위) 활용하기 (선택)
변경 사항이 특정 모듈이나 도메인에 국한된다면 괄호를 이용해 범위를 명시한다. 한눈에 파악하기 매우 용이해진다.
- 예:
feat(order): 주문 추가 시 중복 제약 조건 로직 구현- 예:
chore(deps): lodash 라이브러리 버전 업데이트
feat: 내용 (O) / feat:내용 (X).)를 찍지 않는다.변경의 맥락이 복잡하여 제목 한 줄로 서술이 불가능할 때 작성한다. 단순 버그 수정이나 자잘한 수정 시에는 과감히 생략한다.
fix(auth): JWT 토큰 만료 시 간헐적 튕김 현상 수정
- 기존 익스파이어 타임 계산 로직의 시차 밀리초 계산 오류 확인
- 서버 타임존 기준과 브라우저 타임존을 UTC로 통일하여 오차 범위를 제거함
주로 협업 도구와의 연동이나 프로젝트의 중대한 변화를 알릴 때 사용한다.
이슈 번호를 명시하여 해당 커밋이 어떤 태스크와 연결되어 있는지 추적할 수 있게 한다. GitHub의 경우 특정 키워드와 함께 사용하면 푸시 시 이슈가 자동으로 닫힌다.
Fixes, Closes, Resolves규약 키워드: #이슈번호 ➡️ Closes: #124이전 버전과의 하위 호환성이 깨지는 대대적인 API 변경이나 구조적 변경이 있을 때 바닥글 맨 앞에 BREAKING CHANGE:를 붙여 동료 개발자들에게 강력한 경고를 전달한다.
feat(api): V2 주문 인터페이스 스펙 변경
BREAKING CHANGE: 기존 /api/v1/order API가 폐기됨.
이제 모든 클라이언트는 /api/v2/order 헤더 기반 인증 방식을 사용해야 함.
Ref: #204
Closes: #205
feat(cart): 장바구니 상품 수량 변경 API 연동
- 수량 변경 시 즉각적으로 총 금액이 리프레시되도록 훅 연결
- 최소 수량 1개 미만으로 내려갈 시 하단 경고 토스트 팝업 추가
Closes: #42
fix: 데이터베이스 연결 타임아웃 예외 처리 예외 구간 확장
style: 코드 포맷팅 및 사용하지 않는 임포트 구문 제거
Fix: 로그인 고쳤음. (타입 뒤 공백 없음, 마침표 사용, 과거형 서술)
수정 (영어 타입 미사용, 일관성 결여)
feat: 어제 짜다 만 장바구니 기능 마저 구현하고 중간 저장함 (지나치게 감정적이거나 사적인 서술)
컨벤션은 절대적인 정답이 아니라 팀원 간의 약속이다. 위의 Conventional Commits 스타일을 기본 뼈대로 삼고, 팀의 성격에 맞게 조금씩 변형하여 활용한다면 누구나 읽기 편한 깔끔한 히스토리를 유지할 수 있다. 처음에는 어색할지라도 type을 먼저 정의하고 커밋하는 습관을 들이면 코드의 분리(Atomic Commit)도 자연스럽게 이루어지게 된다.