
안녕하세요 웹 OB 한수정입니다.
저는 종종 커밋메시지를 잘못 올리곤 합니다... 종종? 자주? 항상?
그래서 하루 건너 하루 지피티에게 커밋 메시지 수정하는 법에 대해 물어보는 삶을 살고 있었습니다.
이거 하면 수정은 되더라구요 ㅎㅎ
git commit --amend
아무튼, 그런 저에게 한 줄기 빛이 내려왔습니다.

그건 바로 husky

4주차 공유과제에서 husky에 대해 이야기 해보려고 합니다.
husky는 협업에서 코드 스타일, 커밋 메시지 등을 통일해주는 자동화 도구 중 하나입니다.
이번 공유과제에서는 pnpm을 기반으로 husky와 lint-staged, commitlint를 이용해 커밋 전에 린트 자동 실행 및 커밋 메시지 형식 검사에 대해 간단히 알아보겠습니다.
🐶 Husky란?
Husky는 Git 훅(Git hook)을 쉽게 설정하고 관리할 수 있게 도와주는 도구입니다. 예를 들어 pre-commit, commit-msg 훅을 이용해 커밋 전에 자동으로 린트 검사를 실행하거나 커밋 메시지 형식을 검사할 수 있습니다.
📦 pnpm으로 Husky 설치 및 설정
pnpm add -D husky lint-staged @commitlint/cli @commitlint/config-conventional
husky 초기화해줍니다.
pnpm husky install
그 후, package.json을 확인해줍니다.
"devDependencies": {
"@commitlint/cli": "^19.8.1",
"@commitlint/config-conventional": "^19.8.1",
},
해당 내용이 잘 포함되었는지 확인하고, 없는 경우 추가 후 pnpm install을 진행해줍니다.
🛠 Git 훅 추가
.husky 폴더가 프로젝트의 루트에 생기고 여기에 훅 스크립트를 추가합니다.
✅ pre-commit 훅, 터미널을 사용하지 않고 .husky 폴더 바로 아래에 pre-commit이라는 파일을 추가해주어도 문제 없습니다.
npx husky add .husky/pre-commit "pnpm exec lint-staged"
✅ .husky/pre-commit 파일에 아래 내용을 추가해줍니다.
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
pnpm exec lint-staged
✅ commit-msg 훅, 터미널을 사용하지 않고 .husky 폴더 바로 아래에 commit-msg이라는 파일을 추가해주어도 문제 없습니다.
npx husky add .husky/commit-msg "pnpm exec commitlint --edit \$1"
✅ .husky/commit-msg 파일에 아래 내용을 추가해줍니다.
아래 내용은 팀 별로 정한 커밋 컨벤션을 지정해줍니다.
저는 합동세미나 모바일 웹 2조를 기준으로 feat: 진행한 작업 (#이슈번호) 로 지정했습니다.
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
echo "[커밋 메시지 규칙 안내]"
echo "예시: feat: 로그인 기능 추가 (#1)"
echo ""
pnpm exec commitlint --edit $1
🛠 커밋 메시지 규칙 설정
위 세팅이 끝난 후 루트에 commitlint.config.cjs 파일을 생성하고 아래 내용을 추가합니다.
아래 내용도 예시: feat: 진행한 작업 (#이슈번호) 를 기준으로 작성되었습니다.
module.exports = {
// 기본 커밋 메시지 규칙을 정의한 설정을 확장합니다.
extends: ['@commitlint/config-conventional'],
rules: {
// type은 반드시 아래 목록 중 하나여야 함
'type-enum': [
2, // severity: 0 = off, 1 = warning, 2 = error
'always',
[
'feat', // 새로운 기능
'chore', // 빌드/도구 설정 등 기타 작업
'style', // 코드 포맷팅 (기능 변경 없음)
'fix', // 버그 수정
'hotfix', // 긴급 수정
'docs', // 문서 관련 수정
'refactor', // 코드 리팩토링 (기능 변화 없음)
'test', // 테스트 코드 추가/수정
'design', // UI/UX 관련 변경
'build', // 빌드 시스템 수정
'deploy', // 배포 관련 변경
],
],
// subject에 대해 대소문자 등 케이스는 신경 쓰지 않음
'subject-case': [0],
// 커밋 메시지 전체 길이는 100자 이하 권장
'header-max-length': [2, 'always', 100],
// 커밋 메시지 끝에 반드시 이슈 번호를 포함해야 함 (#123 형태)
'header-issue-suffix': [2, 'always'],
},
plugins: [
{
rules: {
// 커밋 메시지 헤더 끝에 (#숫자) 형식의 이슈 번호가 있는지 확인
'header-issue-suffix': (parsed) => {
const { header } = parsed;
const issuePattern = /\(#\d+\)$/; // 예: (#12)
const typePattern = /^(feat|fix|chore|style|docs|refactor|test|design|build|deploy)/;
// 타입이 올바른지 확인
if (!typePattern.test(header)) {
return [
false,
'❌ 커밋 메시지는 feat, fix, chore 등 올바른 타입을 포함해야 합니다.',
];
}
// 이슈 번호가 포함되어 있는지 확인
if (!issuePattern.test(header)) {
return [
false,
'❌ 커밋 메시지는 반드시 이슈 번호로 끝나야 합니다.',
];
}
return [true]; // 통과!
},
},
},
],
};
아래는 주석 없는 코드를 .. 토글로 올리고 싶은데 접은 글로 올려보겠습니다.
🔧 lint-staged 설정
✅ package.json에 다음과 같이 추가합니다. 저는 구분이 쉽게 가장 아래 적어주었습니다.
{
"lint-staged": {
"*.{ts,tsx}": [
"eslint --fix"
]
}
}
❔ 만약 커밋 메시지를 컨벤션과 다르게 올린다면
아래와 같은 결과를 확인할 수 있습니다.
- 커밋 메시지에 이슈번호가 포함되지 않은 경우

- 커밋 메시지에 feat, chore 등 type이 포함되지 않은 경우

- 터미널이 아닌 git 탭에서 커밋을 올리는데, 커밋 컨벤션에 맞춰서 올리지 않은 경우

✅ 마무리
오늘 제가 진행한 husky 설정은 앞으로 커밋할 때마다
- eslint --fix가 자동 실행되고,
- 커밋 메시지가 규칙에 맞지 않으면 커밋이 거부됩니다.
husky는 협업 시 실수를 줄이고, 코드 품질과 기록을 깔끔하게 유지할 수 있는 훌륭한 설정입니다 !!
끝

'4주차' 카테고리의 다른 글
| GIT 브랜치 전략 (1) | 2025.06.13 |
|---|---|
| API 에러 처리: 사용자 경험 향상을 위해서. (0) | 2025.05.15 |
| 대중적인 API instance 세팅과 고려해야할 점! (0) | 2025.05.13 |
| 네이밍 규칙 (1) | 2025.05.13 |
| CommonJS와 ES Modules (0) | 2025.05.13 |