2023. 1. 18. 01:04ใCI, CD/Etc
Eslint๋ฅผ ์ฌ์ฉํ๋ฉด ์ฌ์ ์ ์ค์ ํ๋๋ก ํ๋ก์ ํธ ๋ด ์ฝ๋ ์คํ์ผ์ ๊ฐ์ ํด์ฃผ์ด ์ฝ๋์ ์ผ๊ด์ฑ์ด ์๊ธฐ๊ณ ๊ฒฐ๊ณผ์ ์ผ๋ก๋ ํ๋ก์ ํธ ๋ด ์ฝ๋ ํ์ง์ด ํฅ์๋๋ค. ์ด๋ ํนํ ํ์ ํ๊ฒฝ์์ ๋์ฑ ๋๋๋ผ์ง๋ค.
์ผ๋ฐ์ ์ผ๋ก ๋ค์์ ๋ช ๋ น์ด๋ฅผ ์ํํ์ฌ ์ฝ๋ ์คํ์ผ์ ๋ํ ๊ฒ์ฌ๋ฅผ ์ํํ๋ค.
# --fix ์ต์
์ Eslint๊ฐ ์๋ฐ์ ์ผ๋ก ์์ ํ ์ ์๋ ์์ค์ ์คํ์ผ ์ค๋ฅ์ ๋ํด์๋
# ์๋์ผ๋ก ์์ ์ ํ๋ ๊ฒ์ ์๋ฏธํ๋ค.
eslint --fix
๋ณดํต, ํ์ ์์๋ ํ๋ก์ ํธ ์ ์ฅ์์ ์ ์ฝ์ ๋์ด Merge ์ Lint ํ ์คํธ๋ฅผ ์๋์ผ๋ก ์ํํ๊ณ ํ ์คํธ๋ฅผ ํต๊ณผํ์ง ๋ชปํ ์ ์ฝ๋๊ฐ Merge๋์ง ์๋๋ก ์ค์ ํ๋๋ฐ, ์ด์ ๋ฐ๋ผ ๋ก์ปฌ์์ ์์ฑํ ์ฝ๋๋ฅผ ์๊ฒฉ ์ ์ฅ์๋ก pushํ ๋ Lint ํ ์คํธ๋ฅผ ๊ณ์ํด์ ์ํํด์ฃผ์ด์ผ ํ๋ค. ์ด๋ ๋ฌผ๋ก ํฐ ์์ ๋จ์๋ ์๋์ง๋ง ๋งค๋ฒ ์ํํ๊ธฐ์๋ ๊ฝค๋ ๋ฒ๊ฑฐ๋ก์ด ์์ ์ด๊ณ , ๋ ๊ฐํน ํ ์คํธ๋ฅผ ์์ด๋ฒ๋ฆฌ๋ ๊ฒฝ์ฐ๋ ์กด์ฌํ๋ค.
์ด๋ฅผ ์ํด ๊ฐ๋ฐ์๋ Husky์ ๋์ ์ ๊ณ ๋ คํ ์ ์๋ค.
Husky
Husky๋ ํ์ ํ๊ฒฝ์์ Git Hooks์ ์ฝ๊ฒ ๊ณต์ ํ ์ ์๊ฒ ๋์์ฃผ๋ NodeJS ๊ธฐ๋ฐ ๋ชจ๋์ด๋ค.
์ฌ๊ธฐ์ Git Hooks๋ ํน์ Git ์ด๋ฒคํธ ์คํ ์ , ํ์ ์ถ๊ฐ์ ์ธ ์์ ์ ์๋์ ์ผ๋ก ์ํํ๋ ๊ธฐ๋ฅ์ ์ ๊ณตํ๋ ๋๊ตฌ์ด๋ค. Git Hooks์ ์ข ๋ฅ๋ก๋ ํด๋ผ์ด์ธํธ ํ , ์๋ฒ ํ ์ผ๋ก ๋๋๋ฉฐ ๊ทธ ์์์๋ ์ปค๋ฐ ์ํฌํ๋ก์ฐ ํ , ์ด๋ฉ์ผ ์ํฌํ๋ก์ฐ ํ , ์๋ฒ ํ ๋ฑ์ผ๋ก ๋๋๋ค. ์ฌ๊ธฐ์์๋ ์ปค๋ฐ ์ ์๋์ผ๋ก Lint ์ฒดํฌ๋ฅผ ์ํํ๋ ๋ก์ง์ ์์ฑํด์ผํ๊ธฐ ๋๋ฌธ์ ์ปค๋ฐ ์ํฌํ๋ก์ฐ ํ ์ ๋ํด์๋ง ์กฐ๊ธ ๋ ์์๋ณด์.
Commit Workflow Hooks
์ปค๋ฐ ์ํฌํ๋ก์ฐ ํ ์ ํตํ๋ฉด ์ปค๋ฐ ์ด๋ฒคํธ ์ , ํ๋ก ํ ์ ์๋์ํฌ ์ ์๋ค. ์ปค๋ฐ ์ํฌํ๋ก์ฐ ํ ์ ์ข ๋ฅ๋ ๋ค์๊ณผ ๊ฐ๋ค.
- pre-commit (์ปค๋ฐ ์ ๊ฐ์ฅ ๋จผ์ ์คํ)
- prepare-commit-msg (git์ด ์ปค๋ฐ ๋ฉ์์ง๋ฅผ ์์ฑํ๊ณ ํธ์ง๊ธฐ๋ฅผ ์คํํ๊ธฐ ์ง์ ์คํ)
- commit-msg (์ปค๋ฐ์ด ๋ฐ์ํ๊ธฐ ์ง์ ์คํ)
- post-commit (์ปค๋ฐ์ด ๋ฐ์ํ ์งํ ์คํ)
์ด ์ค pre-commit ํ ์ ํตํ๋ฉด ์ปค๋ฐ ์ด๋ฒคํธ ๋ฐ์ ์ ๋จผ์ ํน์ ํ ์คํธ๋ฅผ ๊ฐ์ ํ๊ณ , ํ ์คํธ ์คํจ ์ ํด๋น ์ปค๋ฐ ์ด๋ฒคํธ๋ฅผ ์ทจ์์ํค๋ ๊ฒ์ด ๊ฐ๋ฅํ๋ค.
์ด๋ฅผ ์์ฑํ๋ ๊ฒ๋ ์ด๋ ต์ง ์์๋ฐ, ์๋์ผ๋ก ํ๋ก์ ํธ ํด๋์ ์์ฑ๋๋ .git ๋๋ ํฐ๋ฆฌ ๋ด๋ถ์ hooks ๋๋ ํฐ๋ฆฌ๋ฅผ ์ฌ์ฉํ๋ฉด ๋๋ค. ํด๋น ๊ฒฝ๋ก์ ๊ฐ๋ณด๋ฉด Git์์ ์๋์ผ๋ก ์์ฑํ ์ํ ํ ํ์ผ๋ค์ด ์กด์ฌํ๋ค. ์ด๋ฅผ ์ ์ฉํ๊ณ ์ถ๋ค๋ฉด ๋จ์ํ ํ์ผ๋ช ์์ .sample์ ๋นผ์ฃผ๋ฉด ๋๋ค. ๋ก์ง์ ์์ฑํ๋ ๊ฒ๋ ์ด๋ ต์ง ์์๋ฐ, shell, Perl ๋ฟ ์๋๋ผ Ruby, Python์ผ๋ก๋ ์์ฑํ ์ ์๋ค.
์ง๊ธ๊น์ง์ ๋ด์ฉ๋ง ๋๊ณ ๋ดค์ ๋, Husky๊น์ง ๊ฐ ํ์ ์์ด ๋จ์ Git Hook๋ง์ผ๋ก๋ ์ถฉ๋ถํด๋ณด์ธ๋ค. ํ์ง๋ง ๊ธฐ๋ณธ Git Hook์๋ ํฐ ๋ฌธ์ ์ ์ด ์กด์ฌํ๋ค. ๋ฐ๋ก, ์์ ๊ฐ์ด ์์ฑ๋ Git Hook ํ์ผ์ Git์ ํตํด ์๊ฒฉ ์ ์ฅ์, ํน์ ๋ค๋ฅธ ์ฌ์ฉ์์ ๊ณต์ ํ ์ ์๋ค๋ ๋ฌธ์ ๋ค. Git ๋ช ๋ น์ด๋ค์ ํตํด์๋ .git ๋๋ ํฐ๋ฆฌ์ ํ์ผ๋ค์ ๊ณต์ ํ ์ ์๊ธฐ ๋๋ฌธ์ธ๋ฐ, ํด๋น ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด Husky๊ฐ ์ฐ์ธ๋ค.
Husky๋ฅผ ํตํ Git Hook ๊ณต์
Husky๋ฅผ ํตํ๋ฉด ํ์ ํ๊ฒฝ์์ Git Hook ๊ด๋ จ ์ธํ ์ ๊ต์ฅํ ํธํ๊ฒ ์ํํ ์ ์๋ค. Husky ์ธํ ์ ์ํํ ํ๋ก์ ํธ๊ฐ Git ๋ช ๋ น์ด๋ฅผ ํตํด ๊ณต์ ๋๋ฉด, ๋ค๋ฅธ ํ๊ฒฝ์์ ์์กด์ฑ ์ธํ (npm i) ์ ์ ์ ๋ก Git Hook์ด ์ ์ฉ๋๋ ๋ฐฉ์์ด๋ค.
ํ๋ก์ ํธ์ Husky๋ฅผ ์ ์ฉํด๋ณด์. ์ต์ข ์ ์ผ๋ก๋ Husky์ Lint-staged๋ฅผ ์ด์ฉํ์ฌ ๋งค ์ปค๋ฐ๋ง๋ค eslint --fix ๋ช ๋ น์ ๊ฐ์ ํ๊ณ ํ ์คํธ๊ฐ ์คํจํ ์ ์ปค๋ฐ์ ๋ฐ๋ คํ๋ ๊ฒ์ ๋ชฉํ๋ก ํ๋ค.
์ฐ์ , Husky๊ฐ ์ฌ์ฉ๋๋ ํ๊ฒฝ์ ํฌ๊ฒ 2๊ฐ๋ก ๋๋๋ค. ๊ฐ๊ฐ์ ๊ฒฝ์ฐ์ ๋ํด Husky์ Lint-staged ์ค์ ์ด ์กฐ๊ธ์ฉ ๋ค๋ฅด๊ฒ ์งํ๋๋ค.
- .git ๋๋ ํฐ๋ฆฌ์ package.json ํ์ผ์ด ๋์ผ ๋๋ ํฐ๋ฆฌ์ ์์นํ๋ ๊ฒฝ์ฐ
- .git ๋๋ ํฐ๋ฆฌ์ package.json ํ์ผ์ด ์๋ก ๋ค๋ฅธ ๋๋ ํฐ๋ฆฌ์ ์์นํ๋ ๊ฒฝ์ฐ
.git ๋๋ ํฐ๋ฆฌ์ package.json ํ์ผ์ด ๋์ผ ๋๋ ํฐ๋ฆฌ์ ์์น
ํด๋น ๊ฒฝ์ฐ์๋ ์ค์ ๊ณผ์ ์ด ๊ฐ๋จํด์ง๋ค.
๋จผ์ , ๋ค์์ ๋ช ๋ น์ด๋ฅผ ํตํด Husky์ ์ค์น์ ์ค์ ์ ์ํํ์.
npx husky-init -y && npm install
์ ๋ช ๋ น์ด๋ฅผ ์ํํ๋ฉด ํ๋ก์ ํธ ์์กด์ฑ์ Husky๊ฐ ์ถ๊ฐ๋จ๊ณผ ๋์์, .husky ๊ฒฝ๋ก๊ฐ ์์ฑ๋๊ณ ๊ทธ ์์ pre-commit ํ์ผ์ด ์์ฑ๋๋ค. ์๋์ผ๋ก ์์ฑ๋ ํ์ผ์ ๋ด์ฉ๋ฌผ์ ๋ค์๊ณผ ๊ฐ๋ค.
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
npm test
์ด ๋ npm test ๋ช ๋ น์ด๋ Husky๊ฐ ์๋์ผ๋ก ์ถ๊ฐํ ๋ช ๋ น์ด์ด๋ค. Husky๋ฅผ ํตํด ๋ ๋ค๋ฅธ ๋ช ๋ น์ด๋ฅผ ์ถ๊ฐํ๊ณ ์ถ๋ค๋ฉด ๋ค์์ ๋ช ๋ น์ด๋ฅผ ์ฌ์ฉํ ์ ์๋ค.
npx husky add {Husky ํ์ผ์ ๊ฒฝ๋ก} "{์ํํ ๋ช
๋ น์ด}"
์ปค๋ฐ ์ Shell์ Hello, Husky! ๋ผ๋ ๋ฌธ์์ด์ ์ถ๋ ฅํ๋๋ก, ๋ค์๊ณผ ๊ฐ์ด ๋ช ๋ น์ด๋ฅผ ์ฌ์ฉํ ์ ์๋ค.
npx husky add .husky/pre-commit "echo 'Hello, Husky!'"
๋ช ๋ น์ด ์ํ ํ ๋ค์ .husky/pre-commit ํ์ผ์ ๊ฐ๋ณด๋ฉด, ๋ค์๊ณผ ๊ฐ์ด ๋ช ๋ น์ด๊ฐ ์ถ๊ฐ๋ ๊ฒ์ ํ์ธํ ์ ์๋ค.
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
npm test
echo 'Hello, Husky!'
์ด์ ์ปค๋ฐ์ ์คํํ๋ฉด ์ ๋ก์ง์ด ์ํ๋๋ค.
์ด ๋, ๋ง์ฝ package.json์ npm test ๋ช ๋ น์ด๋ฅผ ๋ฐ๋ก ๊ฑด๋ค์ง ์์๋ค๋ฉด ์ผ๊ด์ ์ผ๋ก exit 1 ์ด ์ํ๋๊ธฐ ๋๋ฌธ์ ๊ทธ ๋ค์ echo ๋ฌธ์ ์คํ๋์ง ์๊ณ ๊ณง๋ฐ๋ก ์ปค๋ฐ์ด ๋ฐ๋ ค๋๋ ๊ฒ์ ๋ณผ ์ ์๋ค.
Lint-staged ์ ์ฉ
Lint-staged๋ฅผ ์ด์ฉํ๋ฉด ํ์ฌ staging ์ํ์ ์ฝ๋๋ค์ ๋ํด์๋ง Lint ์ฒดํฌ๋ฅผ ์ํํ ์ ์๋ค. ์ฆ, ํน์ ์ปค๋ฐ์ ๋ณ๋ ์ฌํญ์ ๋ํด์๋ง Lint ์ฒดํฌ๊ฐ ์ํ๋๋ ๊ฒ์ด๋ค. ๋งค ์ปค๋ฐ ์ ์ ์ฒด ์ฝ๋์ ๋ํ Lint ์ฒดํฌ๊ฐ ์ํ๋๋ฉด ์ด๋ฏธ ๋ฃฐ์ ํต๊ณผํ ์ฝ๋๋ค์ ๋ํ ์ฌ๊ฒ์ฌ๊ฐ ์ด๋ฃจ์ด์ ธ ์์ฒญ๋ ๋นํจ์จ์ด ๋ฐ์ํ๋๋ฐ, Lint-staged๋ ์ด๋ฌํ ๋นํจ์จ์ ์ ๊ฑฐํด์ค๋ค.
๋ํ Lint-staged๋ฅผ ํตํด eslint --fix ๋ช ๋ น์ด๋ฅผ ์ฌ์ฉํ ๊ฒฝ์ฐ, eslint๊ฐ --fix ์ต์ ์ ์ํด ์์ ํ ์ฌํญ๋ ์๋์ผ๋ก ์ปค๋ฐ์ ํฌํจ์์ผ์ค๋ค.
Lint-staged๋ฅผ ์ค์นํ๊ธฐ ์์, ๋จผ์ ํด๋น ํ๋ก์ ํธ์ eslint์ prettier ์์กด์ฑ์ ์ถ๊ฐํ๊ณ ์ค์ ์ ์๋ฃํด์ฃผ์ด์ผ ํ๋ค.
๊ทธ ๋ค์, Lint-staged๋ฅผ ์ค์นํด์ฃผ์.
npm i -D lint-staged
๊ทธ ํ package.json ๋ด lint-staged๋ฅผ ์ถ๊ฐํด์ค๋ค.
{
...,
"lint-staged": {
"*.{ts,tsx}": [
"eslint --fix"
]
}
}
๋ง์ง๋ง์ผ๋ก, .husky/pre-commit ํ์ผ์ ๋ค์๊ณผ ๊ฐ์ด ์์ ํด์ฃผ๋ฉด Husky, Lint-staged๋ฅผ ํตํ pre-commit ํ ์ค์ ์ด ์๋ฃ๋๋ค.
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
npx lint-staged
์ฌ๋ด์ผ๋ก, ์ ๋ชจ๋ ์ค์ ์ ์๋์ ๋ช ๋ น์ด ํ์ค์ ํตํด์๋ ๊ฐ๋ฅํ๋ค. ๋จ, ์๋ ๋ช ๋ น์ด๋ .git ๋๋ ํฐ๋ฆฌ์ package.json ํ์ผ์ด ๊ฐ์ ๊ฒฝ๋ก์ ์กด์ฌํ ๋๋ง ์ ์ ์๋ํ๋ค.
npx mrm@2 lint-staged
.git ๋๋ ํฐ๋ฆฌ์ package.json ํ์ผ์ด ์๋ก ๋ค๋ฅธ ๋๋ ํฐ๋ฆฌ์ ์์น
ํด๋น ๊ฒฝ์ฐ๋ ์์์ ์ธ๊ธํ npx mrm@2 lint-staged ๋ช ๋ น์ด๋ฅผ ํตํด husky์ lint-staged๋ฅผ ํ๋ฒ์ ์ค์ ํ ์ ์๊ณ , ๊ฐ๊ฐ ์ค์ ํด์ฃผ์ด์ผํ๋ค.
๋ ์ฌ์ด ์ค๋ช ์ ์ํด ํ๋ก์ ํธ๋ ๋ค์์ ๋๋ ํฐ๋ฆฌ ๊ตฌ์กฐ๋ฅผ ๋ฐ๋ฅธ๋ค๊ณ ๊ฐ์ ํ๊ฒ ๋ค.
/project
/.git
/client
...
/package.json
/server
...
/package.json
๋ํ ์์ผ๋ก Shell์ ์์ฑํ๋ ๋ชจ๋ ๋ช ๋ น์ด๋ .git ๋๋ ํฐ๋ฆฌ๊ฐ ์กด์ฌํ๋ project ๋๋ ํฐ๋ฆฌ๋ฅผ ๊ธฐ์ค์ผ๋ก ์ด๋ฃจ์ด์ง๋ค๊ณ ๊ฐ์ ํ๋ค.
๋จผ์ Husky๋ฅผ ์ค์นํด์ฃผ์. client ๋๋ ํฐ๋ฆฌ์ server ๋๋ ํฐ๋ฆฌ ์ค ํ๋๋ฅผ ์ ํํ์ฌ ํ ๊ณณ์๋ง ์ค์น๋ฅผ ์งํํ๋ค. ์ฌ๊ธฐ์์๋ server ๋๋ ํฐ๋ฆฌ๋ฅผ ์ ํํ๊ฒ ๋ค.
# /project ๊ฒฝ๋ก์์ ์คํ
cd server && npm install -D husky
๊ทธ ํ ๋ค์ ๋ช ๋ น์ด๋ฅผ ํตํด Husky ์ค์ ์ ์ํํ๋ค.
# ์์ ๋ช
๋ น์ด ๋๋ฌธ์ ํด๋น ๋ช
๋ น์ด ์ํ๋๋ ๋๋ ํฐ๋ฆฌ๋ /project/server
cd .. && npx husky install server/.husky
๊ทธ ๋ค์ /server/package.json ํ์ผ ๋ด scripts ๋ถ๋ถ์ ๋ค์์ ์ถ๊ฐํ๋ค.
{
"scripts": {
...,
"prepare": "cd .. && husky install server/.husky"
}
}
๋ค์์ Lint-staged ๊ด๋ จ ์ค์ ์ด๋ค.
Lint-staged๋ฅผ ์ค์นํ๊ธฐ์ ์์ /client ๋๋ ํฐ๋ฆฌ์ /server ๋๋ ํฐ๋ฆฌ์ ๊ฐ๊ฐ eslint, prettier๋ฅผ ์ค์นํด์ฃผ๊ณ , ์ค์ ๋ ์๋ฃํด์ค๋ค.
์ค์ ์ด ์๋ฃ๋์๋ค๋ฉด, ๊ฐ๊ฐ์ ๊ฒฝ๋ก์ ๋ชจ๋ Lint-staged๋ฅผ ์ค์น์ ์ค์ ์ ํด์ฃผ์ด์ผ ํ๋ค.
Lint-staged๋ฅผ /server, /client ๋๋ ํฐ๋ฆฌ์ ๋ชจ๋ ์ค์นํด์ฃผ์.
npm i -D lint-staged
๊ทธ ๋ค์, ์ญ์ ๋ง์ฐฌ๊ฐ์ง๋ก /server, /client ๋๋ ํฐ๋ฆฌ ๋ด package.json์ ๋ค์์ ์ถ๊ฐํด์ฃผ์.
{
...,
"lint-staged": {
"*.{ts,tsx}": [
"eslint --fix"
]
}
}
๋ง์ง๋ง์ผ๋ก, /server/.husky/pre-commit ํ์ผ์ ๋ค์๊ณผ ๊ฐ์ด ์์ ํด์ฃผ์.
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
cd client && echo 'Client Check' && npx lint-staged && cd ..
cd server && echo 'Server Check' && npx lint-staged && cd ..
์ ์ค์ ์ ํตํด, ์ปค๋ฐ ์ client, server ๊ฒฝ๋ก์ ๋ํด ๊ฐ๊ฐ Lint ํ ์คํธ๋ฅผ ์๋์ผ๋ก ์ํํ๊ณ ํ ์คํธ๊ฐ ์คํจํ์ง ์๋๋ค๋ฉด ์ปค๋ฐ์ด ์ํ๋๊ณ ๊ทธ๋ ์ง ์์ ๊ฒฝ์ฐ ์ปค๋ฐ์ด ๋ฐ๋ ค๋๋ pre-commit ํ ์ด ์๋ํ๊ฒ ๋๋ค.