이전 포스팅에서 사내 프로젝트에 ESLint 와 Prettier 를 적용하는 과정을 다뤘었는데,
이번에는 Husky 와 Lint-staged 를 활용해 작업을 자동화한 과정에 대해 짧게 작성해볼 예정이다.
사실 여러 Lint Rule 들이 정의되어 프로젝트에 적용되어 있더라도, 작업 내용의 커밋 전 항상 린트를 실행해야 하는 점은 상당히 번거롭다.
심지어 린트 실행을 생각하지 못하고 커밋하게 되는 순간이 쌓여가면, 프로젝트 코드가 다시 중구난방이 되거나, 결국 프로젝트 전체 소스에 대해 주기적으로 린트를 수행해주어야 하는 불편함이 생기게 된다.
따라서 Husky 와 Lint-staged 를 함께 적용하여, 이렇게 번거로운 작업이 원하는 시점에 수행되도록 자동화하는 것이 일반적인 사용 사례라 볼 수 있다.
Modern native git hooks made easy
Husky improves your commits and more 🐶 woof!
You can use it to lint your commit messages, run tests, lint code, etc... when you commit or push. Husky supports all Git hooks.
공식 문서의 설명에서도 알 수 있듯이, Husky 는 여러 Git Hook 을 제공하여 소스 코드 린트 작업은 물론, 커밋 메시지 린트나 테스트와 같은 다양한 작업들을 자동화할 수 있도록 하는 툴이다.
정리하면, git 에서 특정 이벤트(Commit, Push...)를 실행할 때, hook 을 설정하여 해당 스크립트를 실행할 수 있도록 도와주는 도구라 정리할 수 있겠다.
Run linters against staged git files and don't let 💩 slip into your code base!
Lint-staged 의 문서는 조금 더 강렬한 어조로 설명이 작성되어 있었다.
결국 Lint-staged 는 git 의 Staged(git add 된 상태) 된 파일들에 Lint 와 같은 특정 명령을 실행할 수 있도록 도와주는 도구로, Staged 된 파일을 수정한 후 다시 staging 하지 않아도 문제가 발생하지 않도록 한다.
다시 말해, Staged 된 파일들에 한해서 Lint 와 같은 특정 명령을 실행하기 때문에 효율적인 Lint 가 가능해진다.
이렇게 두 가지 툴을 함께 활용하여, 작업 내용 커밋 시 Lint-staged 가 수행되도록 Husky 에 Hook 을 등록해 놓으면, Staged 된 파일들에 대해서 효율적으로 Lint 작업을 자동 수행할 수 있을 것이다.
Husky 와 Lint-staged 를 설치한다.
yarn add -D husky lint-staged
Huksy version 4 이하에서는 아래와 같이 package.json 에 Husky 스크립트를 작성할 수 있었지만, 이후 버전 부터는 별도의 폴더에 스크립트 파일을 저장하도록 안내하고 있습니다.
// husky 버전 4 이하 사용 사례
"lint-staged": {
"src/**/*.{ts,tsx}": [
"eslint --ext .tsx,ts src/ --fix"
],
"src/**": [
"prettier --check 'src/**/*.ts' 'src/**/*.tsx'"
]
},
"husky": {
"hooks": {
"pre-commit": "lint-staged"
}
}
먼저, 아래 코드를 터미널에서 실행하여 프로젝트 루트에 .husky 폴더가 자동 생성되도록 한다.
npx husky install
아래 스크립트를 package.json 의 npm Lifecycle 에 추가해놓으면,
다른 팀원이 프로젝트 소스를 받아 작업할 때나, 프로젝트를 다시 세팅하는 경우에도 Husky 가 자동으로 세팅되도록 할 수 있다.
"scripts": {
...
"prepare": "husky install",
...
}
npm Lifecycle 에서 prepare 에 대한 설명은 아래와 같다.
인자 없이 npm install 할 때와 git dependencies 를 설치할 때, 이 둘을 패키지가 압축되어 배포되기 전에 실행합니다. 이 명령은 republish 다음 prepublishOnly 전에 실행됩니다.
- NPM docs -
아래 스크립트를 package.json 에 추가한다.
"lint-staged": {
"{src,test}/**/*.{js,ts}": [
"eslint --fix",
"prettier --write"
]
}
이제 Lint-staged 는 위 Glob 에 매칭되는 모든 Staged 파일들에 대해 ESLint 와 Prettier 를 적용하여 수정할 수 있게 되었다.
이제 Husky 설치와 Lint-staged 의 스크립트 작성까지 완료되었다.
남은 작업은 Husky 의 pre-commit Event Hook 에, 작성된 Lint-staged 의 스크립트가 실행되도록 등록해주는 일이다.
npx husky add .husky/pre-commit "npx lint-staged"
위 명령을 터미널에서 실행하면, husky/pre-commit 파일이 생성되고,
파일에는 아래와 같은 내용이 추가되어 있음을 확인할 수 있다.
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
npx lint-staged
이제 소스코드를 수정한 뒤 커밋하면, 아래와 같이 Husky 가 Lint-staged 를 수행하게 된다.
만약 Staged 된 파일이 없다면, Lint-staged 는 수행되지 않는다.
마찬가지로, 수정된 파일 중 Glob 에 매치하는 파일이 없다면 Lint-staged 는 수행되지 않는다.
추가적으로 Lint 작업에 실패하게 되면 git 커밋 또한 실패하게 되기 때문에 로그에 표시된 파일을 수동으로 수정한 뒤에 다시 커밋하여야 한다.