Git 커밋 메시지는 프로젝트의 히스토리를 이해하는 데 중요한 역할을 한다. 하지만 팀원마다 다른 형식으로 커밋 메시지를 작성하면 일관성이 떨어지고 프로젝트 관리가 어려워질 수 있다. 이런 문제를 해결하기 위해 commitizen이 등장!
commitizen은 커밋 메시지를 일관된 형식으로 작성할 수 있도록 도와주는 도구로, 사용자에게 프롬프트를 통해 필요한 정보를 입력받아 정해진 형식의 커밋 메시지를 생성한다. 이를 통해 다음과 같은 이점을 얻을 수 있다.
commitizen을 사용하면서 원하는 커밋 메시지 컨벤션을 쉽게 만들 수 있다.
기본 설정에서 약간의 커스텀만으로 원하는 형식을 구현할 수 있어 아주아주 쉽게 설정 가능하다.
먼저 commitizen을 설치한다.
npm install --save-dev commitizen
프로젝트 루트에 commit-config.js
파일을 생성하고 다음과 같이 작성한다.
특정 어댑터를 사용하지 않고 직접 세팅을 하는 것이기 때문에, typeChoices, questions의 변수 이름은 자유롭게 변경 가능하다. 각 질문지의 키값들만 규칙을 따르면 된다.
나는 라벨, 메시지, 이슈번호를 입력받고 다음과 같은 형태로 만들었다.
그리고 메시지, 이슈번호에는 validate를 추가하여 유효성 체크를 추가했다.
{label}: {message} (#{issue_number})
ex) feat: 커밋 메시지 (#13)
// commit-config.js
module.exports = {
prompter: (cz, commit) => {
const typeChoices = [
{ value: '✨ feat', name: '✨ feat: 새로운 기능' },
{ value: '🐛 fix', name: '🐛 fix: 버그 수정' },
{ value: '📚 docs', name: '📚 docs: 문서 수정' },
// ... 기타 타입들 ...
];
const questions = [
{
type: 'list',
name: 'type',
message: '1️⃣ 커밋 유형을 선택하세요:',
choices: typeChoices
},
{
type: 'input',
name: 'subject',
message: '2️⃣ 커밋 메시지를 입력하세요:',
validate: (input) => input.length > 0 && input.length <= 100
},
{
type: 'input',
name: 'ticketNumber',
message: '3️⃣ 이슈 번호를 입력하세요 (숫자만):',
validate: (input) => /^\d+$/.test(input)
}
];
cz.prompt(questions).then((answers) => {
const { type, subject, ticketNumber } = answers;
const message = `${type}: ${subject} (#${ticketNumber})`;
const divider = '='.repeat(50);
const decoratedMessage = `
${divider}
✅ 커밋 메시지가 다음과 같아요! 커밋할까요?
${message}
${divider}
`;
cz.prompt([
{
type: 'confirm',
name: 'confirmCommit',
message: decoratedMessage,
default: false
}
]).then((confirmAnswer) => {
if (confirmAnswer.confirmCommit) {
commit(message);
} else {
console.log('❌ 커밋이 취소되었습니다.');
}
});
});
}
};
질문지 별 옵션 값들
참고: 모든 옵션이 모든 질문 유형에 적용되는 것은 아니다. 각 type에 따라 사용 가능한 옵션이 다를 수 있다.
type
: 질문의 유형
input
: 텍스트 입력list
: 선택 목록confirm
: 예/아니오 확인checkbox
: 다중 선택name
: 질문의 식별자message
: 사용자에게 표시될 질문 내용
choices
: 선택 가능한 옵션들의 배열
type
이 'list'나 'checkbox'일 때 사용default
: 기본 답변 값
validate
: 유효성 검사 함수
when
: 질문 표시 여부 결정
filter
: 사용자 입력 변환 함수
transformer
: 표시 전 입력값 변환 함수
prefix
: 질문 앞에 추가될 텍스트
suffix
: 질문 뒤에 추가될 텍스트
pageSize
: 한 번에 표시될 선택지의 수
loop
: 선택 목록의 순환 여부
mask
: 입력값 마스킹 문자
package.json
파일에 다음 내용을 추가
{
"scripts": {
"commit": "cz"
},
"config": {
"commitizen": {
"path": "./commit-config.js"
}
}
}
커밋할 때 git commit
대신 다음 명령어를 사용
npm run commit
또는
yarn commit
이렇게 하면 다음과 같이 설정한 프롬프트에 따라 커밋 메시지를 작성할 수 있다.
commitizen은 다양한 어댑터를 제공하여 서로 다른 커밋 메시지 형식을 지원하는데, 가장 자주 쓰이는 것 같은 3가지는 다음과 같다.
cz-conventional-changelog: Angular의 커밋 메시지 가이드라인을 따르는 가장 널리 사용되는 어댑터
cz-emoji: 커밋 메시지에 이모지를 포함시켜 시각적으로 구분하기 쉽게 만듬
cz-customizable: 사용자가 직접 커밋 메시지 형식을 정의할 수 있는 높은 자유도를 제공
하지만 이런 어댑터들을 사용하는 것이 항상 최선은 아니라고 생각한다.
때로는 원하는 컨벤션의 옵션값을 찾기 어렵거나, 불필요하게 복잡할 수 있어, 앞서 설명한 것처럼 기본 설정에서 약간의 커스텀으로 원하는 형식을 만드는 것이 더 효율적일 수 있다.
마지막으로, 팀원들이 항상 commitizen을 통해 커밋하도록 강제하고 싶다면 husky를 사용할 수 있다. husky를 통한 commit message 제어는 다음에 nextjs 프로젝트를 세팅하며 함께 적용해보려고 한다.
commitizen을 사용하면 일관된 커밋 메시지 컨벤션을 쉽게 만들고 유지할 수 있고 아주 편리하다! 기존의 플러그인이나 어댑터를 사용하는 것도 좋지만, 때로는 직접 간단한 커스텀 설정을 만드는 것이 더 효율적일 수 있으며, 불필요하게 많은 패키지를 설치하기보다는, 프로젝트의 필요에 맞는 최소한의 설정으로 시작하는 것도 좋은 것 같다. 이를 통해 프로젝트의 복잡성을 줄이고, 팀원들이 쉽게 이해하고 사용할 수 있는 커밋 프로세스를 구축하거나 수정이 용이해 다양한 커스텀이 가능하다고 생각한다.