Husky, lint-staged 프로젝트에 적용하기

ESLint, Prettier 로 프로젝트 관리하기 - 3편

2022-05-03

이전 편에서 프로젝트에 ESLint 와 Prettier 를 적용하는 방법에 대해서 알아봤습니다. 이번 편에서는 프로젝트에 적용한 ESLint 와 Prettier 를 자동으로 실행시키는 방법에 대해 알아보도록 하겠습니다.

이번 편에서는 편의상 ESLint 와 Prettier 를 실행하는 것을 '최적화’라고 부르도록 하겠습니다.

ESLint, Prettier 실행 자동화 하기

앞 두편에서 살펴본 내용으로도 프로젝트를 최적화할 수 있지만 이를 위한 ESLint, Prettier 를 직접 실행해 줘야한다는 번거로움이 있었습니다. 실수로 최적화를 실행하지 않고 커밋해버릴 위험도 있습니다.

자동화를 통해 이런 위험을 제거하고 좀 더 효율적으로 프로젝트 최적화를 수행할 수 있도록 할 수 있습니다.

'자동화’란 최적화를 위한 스크립트를 직접 실행시켜줄 필요 없는 환경을 말합니다.

프로젝트에서 자동화를 설정할 수 있는 포인트는 아래와 같이 두군데가 있습니다.

  1. Editor, IDE 에 eslint, prettier 자동화 설정하기
  2. git hook 을 활용하여 commit 실행하기 전에 eslint, prettier 실행하기

첫번째 방법은 vscode(Editor), webstorm(IDE) 같은 툴에서 제공하는 eslint, prettier 플러그인을 설치하고 설정에서 format on save, run eslint on save 와 같은 관련 옵션을 활성화 시켜주는 방법입니다.

관련한 방법은 구글링으로 쉽게 찾을 수 있기 때문에 이정도로만 알아보고 두번째 방법에 대해 알아보도록 하겠습니다.

두번째 방법은 git 으로 버전관리하는 경우에 유효한 방법입니다. (git 을 사용하지 않는 프로젝트는 거의 없을거라 대부분 경우에 적용할 수 있을 것 같습니다.)

git 에서 어떤 이벤트가 발생했을 때 특정 스크립트를 실행할 수 있도록 훅을 제공해 줍니다. 저장소에서 .git/hooks 디렉토리를 보면 많은 훅 sample 파일이 존재합니다.

1
2
3
4
5
6
applypatch-msg.sample     pre-merge-commit.sample
commit-msg.sample pre-push.sample
fsmonitor-watchman.sample pre-rebase.sample
post-update.sample pre-receive.sample
pre-applypatch.sample prepare-commit-msg.sample
pre-commit.sample update.sample

위 훅들 중에서 최적화를 실행하기 가장 좋은 훅은 커밋 워크플로 훅으로 분류되는 pre-commit 훅입니다. 커밋할 때 가장먼저 호출되는 훅으로 커밋 메시지를 작성하기 전에 호출되기 때문에 최적화 스크립트를 실행하기에 적합한 훅 입니다.

훅 파일을 직접 설정하는 방법은 번거롭기 때문에 저희는 huskylint-staged 라는 패키지를 사용해 보도록 하겠습니다. (git hook 에 대한 자세한 내용이 궁금하시다면 git hook 공식문서를 참고해 주세요.)

husky & lint-staged

husky 는 모든 git hook 을 지원하며 손쉽게 git hook 사용할 수 있게해주는 패키지입니다.

이전에는 husky 설치 이후에 npm script 에 prepare 스크립트 추가 및 .husky/ 디렉토리 하위에 hook 파일 생성등 다양한 작업을 해줘야 했었는데 이번에 찾아보니 husky 설치, 설정은 물론 lint-staged 까지 한방에 처리해주는 패키지가 있어 해당 패키지를 활용해 보도록 하겠습니다.

참고로 lint-staged 는 staged 된 파일을 대상으로 특정 스크립트를 실행할 수 있게 해주는 패키지 입니다.

Install

아래 명령어를 사용하여 lint-staged 패키지를 설치합니다. husky 도 함께 설치 됩니다.

1
npx mrm@2 lint-staged

패키지 설치가 완료되면 package.json 에 아래와 같은 내용이 추가됩니다.

1
2
3
4
5
6
7
8
9
10
11
12
{
"scripts": {
"prepare": "husky install"
},
"devDependencies": {
"husky": "^7.0.4",
"lint-staged": "^12.4.1"
},
"lint-staged": {
"*.js": "eslint --cache --fix"
}
}

그리고 아래 이미지와 같이 프로젝트 root/pre-commit 스크립트가 담겨져 있는 .husky/ 디렉토리가 생성됩니다.

Configuration File

최종적으로 자동화를 위한 설정 파일들을 작성해 보도록 하겠습니다.

package.json

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
{
"scripts": {
"lint:fix": "eslint --fix './src/**/*.{js,jsx,ts,tsx}'",
"prettier:fix": "prettier --write './src/**/*.{js,jsx,ts,tsx}'",
"check-conflict-formatting-rules": "npx eslint-config-prettier './src/**/*.{js,jsx,ts,tsx}'",
"prepare": "husky install"
},
"devDependencies": {
"eslint": "^8.13.0",
"eslint-config-airbnb": "^19.0.4",
"eslint-config-prettier": "^8.5.0",
"eslint-plugin-prettier": "^4.0.0",
"husky": "^7.0.4",
"lint-staged": "^12.4.1",
"prettier": "2.6.2"
},
"lint-staged": {
"./src/**/*.{js,jsx,ts,tsx}": [
"npm run check-conflict-formatting-rules",
"npm run prettier:fix",
"npm run lint:fix"
]
}
}

.eslintrc.js

1
2
3
4
5
6
7
8
9
10
module.exports = {
extends: ["airbnb", "prettier"],
rules: {
"no-unused-vars": [
"error",
{ vars: "all", args: "after-used", ignoreRestSiblings: false },
],
"no-console": ["error"],
},
};

.prettierrc.js

1
2
3
4
5
module.exports = {
semi: true,
tabWidth: 4,
singleQuote: true,
};

Practice

모든 설정이 완료되었습니다. src/ 디렉토리 아래 스크립트 파일 수정 후 git add --a, git commit -m"message" 실행시 husky 에 의해 pre-commit 훅이 실행되고, 훅에 의해 lint-staged 에 설정한 스크립트가 동작하면서 아래와 같이 최적화 자동화가 실행됩니다.

End

궁금한 점이나 잘 못된 내용이 있으면 피드백 부탁드립니다.
읽어주셔서 감사합니다.