๐Ÿถ Husky๋กœ ์ปค๋ฐ‹ ์‹ค์ˆ˜ ์ค„์ด๊ธฐ

zimablueยท2025๋…„ 6์›” 15์ผ

GIT

๋ชฉ๋ก ๋ณด๊ธฐ
4/5
post-thumbnail

Husky๋Š” Git hook์„ ์‰ฝ๊ฒŒ ์„ค์ •ํ•  ์ˆ˜ ์žˆ๋„๋ก ๋„์™€์ฃผ๋Š” ๋„๊ตฌ์˜ˆ์š”.

๋ณดํ†ต pre-commit, commit-msg, pre-push ๋“ฑ Git์˜ ํŠน์ • ์‹œ์ ์— ์ž๋™์œผ๋กœ ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์‹คํ–‰ํ•˜๊ฒŒ ํ•ด์ค˜์š”.

์˜ˆ๋ฅผ ๋“ค์–ด:

  • ์ปค๋ฐ‹ ์ „์— Lint ๊ฒ€์‚ฌ๋ฅผ ๊ฐ•์ œํ•˜๊ฑฐ๋‚˜
  • ์ปค๋ฐ‹ ๋ฉ”์‹œ์ง€๋ฅผ ๊ฒ€์‚ฌ(commitlint)
  • ํ…Œ์ŠคํŠธ๊ฐ€ ์‹คํŒจํ•˜๋ฉด ์ปค๋ฐ‹/ํ‘ธ์‹œ๋ฅผ ๋ง‰๋Š” ์‹์˜ ํ๋ฆ„ ์ œ์–ด๊ฐ€ ๊ฐ€๋Šฅํ•ด์š”

git workflow hook

Husky ์„ค์น˜

npm install --save-dev husky

Husky ์ดˆ๊ธฐํ™”

npx husky init

์„ค์น˜ํ•˜๋ฉด package.json์˜ prepare ์Šคํฌ๋ฆฝํŠธ์— "husky"๊ฐ€ ์ถ”๊ฐ€๋ผ์š”:

"scripts": {
  "prepare": "husky"
},

.husky ํด๋”๊ฐ€ ์ƒ๊ธฐ๊ณ , .husky/pre-commit ํŒŒ์ผ๋„ ํ•จ๊ป˜ ์ƒ๊ฒจ์š” (npm test ์‹คํ–‰ ์ฝ”๋“œ ํฌํ•จ).

.husky/pre-commit ํŒŒ์ผ์— ์‹คํ–‰ ๊ถŒํ•œ์„ ์ค˜์š”.

Husky ํ›… ํŒŒ์ผ์€ ์‹ค์ œ๋กœ '์‹คํ–‰๋˜๋Š” ์Šคํฌ๋ฆฝํŠธ'์ด๊ธฐ ๋•Œ๋ฌธ์—, ์šด์˜์ฒด์ œ์—์„œ "์‹คํ–‰ ๊ฐ€๋Šฅํ•œ ํŒŒ์ผ"๋กœ ์ธ์‹์‹œํ‚ค๋Š” ๊ถŒํ•œ ์„ค์ •์ด ํ•„์š”ํ•ด์š”.

chmod +x .husky/pre-commit

lint-staged

Prettier, Stylelint ๊ด€๋ จ ์ƒํƒœ๊ณ„์—๋„ ๊ธฐ์—ฌํ•˜๊ณ  ์žˆ๋Š” ๊ฐœ๋ฐœ์ž๊ฐ€ ๋งŒ๋“ค์—ˆ์–ด์š”.
Git staging ์˜์—ญ(= ์ปค๋ฐ‹ํ•  ํŒŒ์ผ๋กœ ์„ ํƒ๋œ ์ƒํƒœ)์— ์˜ฌ๋ผ๊ฐ„ ํŒŒ์ผ๋งŒ ๋Œ€์ƒ์œผ๋กœ lint๋‚˜ ํฌ๋งท์„ ์ ์šฉํ•  ์ˆ˜ ์žˆ์–ด์š”.
์ „์ฒด ํ”„๋กœ์ ํŠธ๋ฅผ ๊ฒ€์‚ฌํ•˜์ง€ ์•Š์•„์„œ ์†๋„๋„ ๋น ๋ฅด๊ณ , ๊ผญ ์ปค๋ฐ‹ํ•  ํŒŒ์ผ๋งŒ ๊ฒ€์‚ฌํ•˜๋‹ˆ ํšจ์œจ์ ์ด๊ธฐ ๋•Œ๋ฌธ์— Husky์˜ pre-commit ํ›…๊ณผ ํ•จ๊ป˜ ์‚ฌ์šฉํ•ด์š”.

lint-staged ์„ค์น˜

npm install --save-dev lint-staged

.husky/pre-commit์— lint-staged ์‹คํ–‰ ์ฝ”๋“œ๋ฅผ ๋„ฃ์–ด์ค˜์š”.

echo 'npx lint-staged' > .husky/pre-commit

package.json์— ์„ค์ •๋„ ์ถ”๊ฐ€ํ•ด์ค˜์š”.

"lint-staged": {
  "**/*.{js,ts,tsx}": [
    "prettier --write",
    "eslint --fix"
  ]
}

commitlint

semantic-release, standard-version ๊ฐ™์€ ๋ฆด๋ฆฌ์ฆˆ ์ž๋™ํ™” ๋„๊ตฌ๋„ ํ•จ๊ป˜ ๊ด€๋ฆฌํ•˜๋Š” Conventional Changelog ํŒ€์—์„œ ๋งŒ๋“  ์ปค๋ฐ‹ ๋ฉ”์‹œ์ง€ ๊ฒ€์‚ฌ ๋„๊ตฌ ํŒจํ‚ค์ง€์—์š”.

์ปค๋ฐ‹ ๋ฉ”์‹œ์ง€๋ฅผ ๊ฒ€์‚ฌํ•ด์„œ ์ •ํ•ด์ง„ ๊ทœ์น™์— ๋งž์ง€ ์•Š์œผ๋ฉด ์ปค๋ฐ‹์„ ๋ง‰๊ธฐ ๋•Œ๋ฌธ์— ํŒ€ ํ”„๋กœ์ ํŠธ์—์„œ ์ปค๋ฐ‹ ๋ฉ”์‹œ์ง€ ๊ทœ์น™์„ ํ†ต์ผํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉํ•ด์š”.

husky์˜ commit-msg ํ›…๊ณผ ํ•จ๊ป˜ ์—ฐ๊ฒฐํ•ด์„œ ์‚ฌ์šฉํ•ด์š”.

commitlint ์„ค์น˜

npm install --save-dev @commitlint/cli @commitlint/config-conventional

commitlint ์„ค์ • ํŒŒ์ผ์„ ๋งŒ๋“ค๊ธฐ

.commitlintrc.json ํŒŒ์ผ์„ ์ƒ์„ฑํ•˜์—ฌ "@commitlint/config-conventional" ๊ทœ์น™์„ ๋ถˆ๋Ÿฌ์™€์„œ ์ ์šฉํ•ด์š”.

echo '{ "extends": ["@commitlint/config-conventional"] }' > .commitlintrc.json

commit-msg ํ›… ๋งŒ๋“ค๊ธฐ

echo 'npx --no -- commitlint --edit "$1"' > .husky/commit-msg

.husky/commit-msg์— ์‹คํ–‰ ๊ถŒํ•œ์„ ์ค˜์š”.

chmod +x .husky/commit-msg

์ปค๋ฐ‹ ๋ฉ”์‹œ์ง€ ๊ฐ€์ด๋“œ ์ถœ๋ ฅ (prepare-commit-msg)

์ปค๋ฐ‹ ๋ฉ”์‹œ์ง€๋ฅผ ์ž…๋ ฅํ•  ๋•Œ๋งˆ๋‹ค, ํ„ฐ๋ฏธ๋„์— ๋ฉ”์‹œ์ง€ ๊ฐ€์ด๋“œ๋ฅผ ์ถœ๋ ฅํ•ด์ค˜์š”.
๋งค๋ฒˆ ํ—ท๊ฐˆ๋ฆฌ์ง€ ์•Š๋„๋ก ๋„์™€์ฃผ๋Š” ์ดˆ๋ณด์ž ์ „์šฉ ์•ˆ์ „์žฅ์น˜์˜ˆ์š”.

#!/bin/sh

GREEN=$(tput setaf 2)
BLUE=$(tput setaf 4)
RED=$(tput setaf 1)
BOLD=$(tput bold)
RESET=$(tput sgr0)

echo "
${BOLD}${BLUE}๐Ÿ“ ์ปค๋ฐ‹ ๋ฉ”์‹œ์ง€ ๊ฐ€์ด๋“œ${RESET}

${GREEN}ํ˜•์‹${RESET}: <type>: <message> [#์ด์Šˆ๋ฒˆํ˜ธ]

${GREEN}์˜ˆ์‹œ${RESET}:
  ${BLUE}feat${RESET}: ํšŒ์›๊ฐ€์ž… ๊ธฐ๋Šฅ ์ถ”๊ฐ€
  ${BLUE}fix${RESET}: ๋กœ๊ทธ์ธ ์˜ค๋ฅ˜ ์ˆ˜์ • #123
  ${BLUE}docs${RESET}: README ์—…๋ฐ์ดํŠธ

  ${BOLD}โœ… commitlint ๊ฒ€์‚ฌ ๊ทœ์น™ ์š”์•ฝ:${RESET}
  - ${BOLD}<type>${RESET}์€ ๋ฐ˜๋“œ์‹œ ์žˆ์–ด์•ผ ํ•˜๊ณ , ${BLUE}feat, fix, docs${RESET} ๋“ฑ์œผ๋กœ ์‹œ์ž‘ํ•ด์•ผ ํ•ด์š”.
  - ${BOLD}<message(subject)>${RESET}๋Š” ์†Œ๋ฌธ์ž๋กœ ์‹œ์ž‘ํ•ด์•ผ ํ•˜๊ณ , ๋งˆ์นจํ‘œ(.)๋กœ ๋๋‚˜๋ฉด ์•ˆ ๋ผ์š”.
  - ์˜ˆ์‹œ ๋น„๊ต:
    ${GREEN}fix: login ์˜ค๋ฅ˜ ์ˆ˜์ •${RESET} โ† โœ…
    ${RED}Fix: Login ์˜ค๋ฅ˜ ์ˆ˜์ •.${RESET} โ† โŒ

์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ type ๋ชฉ๋ก:
  ${BLUE}feat${RESET}      ์ƒˆ๋กœ์šด ๊ธฐ๋Šฅ
  ${BLUE}fix${RESET}       ๋ฒ„๊ทธ ์ˆ˜์ •
  ${BLUE}docs${RESET}      ๋ฌธ์„œ ๊ด€๋ จ ๋ณ€๊ฒฝ
  ${BLUE}style${RESET}     ์ฝ”๋“œ ํฌ๋งทํŒ… (์„ธ๋ฏธ์ฝœ๋ก , ๋“ค์—ฌ์“ฐ๊ธฐ ๋“ฑ)
  ${BLUE}refactor${RESET}  ๋ฆฌํŒฉํ† ๋ง (๊ธฐ๋Šฅ ๋ณ€ํ™” ์—†์Œ)
  ${BLUE}test${RESET}      ํ…Œ์ŠคํŠธ ์ถ”๊ฐ€/์ˆ˜์ •
  ${BLUE}chore${RESET}     ๊ธฐํƒ€ ์„ค์ •, ํŒจํ‚ค์ง€ ๋ณ€๊ฒฝ
  ${BLUE}WIP${RESET}       ์ž‘์—… ์ค‘์ธ ์ปค๋ฐ‹ (Work in Progress)

${GREEN}TIP:${RESET} ๊ด€๋ จ๋œ ์ด์Šˆ๊ฐ€ ์žˆ๋‹ค๋ฉด ๋ฉ”์‹œ์ง€ ๋์— ${BOLD}#123${RESET}์ฒ˜๋Ÿผ ์ ์–ด์ฃผ์„ธ์š”.
"

prepare-commit-msg ์‹คํ–‰ ๊ถŒํ•œ์„ ์ค˜์š”.

chmod +x .husky/prepare-commit-msg

0๊ฐœ์˜ ๋Œ“๊ธ€