치춘짱베리굿나이스

Husky 사용해보기 (+ lint-staged) 본문

ClientSide/라이브러리

Husky 사용해보기 (+ lint-staged)

치춘 2023. 9. 12. 15:14

Husky

설치

$> npm i husky --save-dev
$> yarn husky --dev
  • 개발 과정에서만 사용하는 툴이므로 devDependency에 추가하는 것을 잊지 말자

설명

git hook을 쉽게 도입해줄 수 있게 해 주는 툴이다

조금만 설정해 주면 팀원 전체에게 깃 훅이 적용되어 커밋이나 푸시 등의 이벤트 발생 전에 특정 로직을 수행하게끔 할 수 있다

강제로 특정 로직을 수행하게 하는 이유?

가장 큰 이유 중 하나는 통일성이 되겠다

eslint, prettier를 아무리 열심히 설정해도 팀원들이 매번 지키지 않으면 린터 또는 포매터가 적용되지 않은 (통일성에 어긋나는) 코드가 레포지토리에 올라가므로 설정한 의미가 사라진다

이를 강제로 git hook을 통해 커밋 전이나 푸시 전에 특정 동작을 수행하게끔 하여 팀원들의 코드 간 통일성을 지킬 수 있는 것이 후술할 git hook과 husky이다

git hook?

특정 깃 이벤트 (커밋, 푸시 등…) 가 발생하기 전후로 동작을 수행시킬 수 있는 기능이다

특정 깃 이벤트가 발생하기 전후로 특정 스크립트를 실행시킬 수 있는 기능이라고 보면 된다

 

.git/hooks 폴더에 들어가 보면 샘플 파일이 이렇게나 많다

대충 해석해보면 업데이트 이후, 리베이스 직전, 커밋 직전, 머지 커밋 직전, 푸시 직전…

각 파일 뒤의 .sample 확장자를 지우고, 내부에 쉘 스크립트를 작성하면 이벤트 전후로 해당 스크립트가 실행되는 방식이다

 

깃 훅은 원격 레포지토리에 올릴 수 없어, 설정 파일을 팀원들끼리 공유해서 각자 설정해 주어야 한다

한 명이라도 설정을 잊어버렸을 경우? 원하는 동작이 실행되지 않은 채로 원격 레포지토리에 업로드될 것이다

만약 린터를 통해 코드를 교정해주는 동작을 넣어 놨을 경우, 어느 한 명이라도 설정을 안 할 경우 린터가 적용되지 않은 코드가 푸시될 수도 있는 것이다

그래서 husky

원격 레포지토리에 푸시되지 않아 한 명 한명이 각자 설정해주어야 하는 git hook 과 달리, husky는 원격 레포지토리에 설정 파일을 업로드할 수 있어 그것을 pull 받고 husky를 install 하기만 하면 팀원 전원이 같은 설정의 husky를 사용할 수 있다

format on save 등은 내 파일에만 적용되고 팀원의 파일에는 적용되리라는 보장이 없는데, git hook은 모든 팀원의 깃 커밋 - 푸시 사이클에 강제적용할 수 있으므로 코드의 품질이 보장된다는 장점이 있다

적용하기

.husky 폴더 설정

이 부분은 만약 이미 .husky 폴더가 있다면 건너뛰어도 된다

 

$> npx husky install // 설정 폴더 생성

위의 명령을 입력하면 husky - Git hooks installed 문구가 출력된다

npm (또는 yarn) 을 통해 node_modules에 설치한 husky를 이용하여 installation 작업을 수행하는 것이다

 

작업 폴더를 보면, .husky 폴더가 추가되었음을 확인할 수 있다

여기서 우리는 팀원들과 함께 hook 들을 관리하고 깃에 푸시할 수 있다

 

// package.json

"scripts": {
    ...
    "postinstall": "husky install" 
}

물론 어떤 팀원은 husky install 과정을 잊어버릴 수도 있다는 것을 염두에 두어야 한다

그것을 위해 우리는 package.json에서 postinstall 설정을 해 줄 수 있다

package.json에서는 사전 정의된 몇몇 스크립트 (특정 이벤트가 발생했을 때 실행시킬 수 있는 스크립트) 를 사용할 수 있는데, 그 중 하나가 postinstall으로, 이름에 걸맞게 installation 직전, 즉 npm i, yarn 등의 직후에 실행시킬 스크립트를 정의할 수 있다

  • npm i axios 이후에는 실행이 되지 않았다
  • .husky 폴더가 이미 있는 경우에도 실행되지 않았다
  • npm i 이후에는 실행되었다

결국 postinstall은 최초 node_modules에 의존성을 설치하려 하는 시점에 실행되는 것을 목적으로 한 키워드라고 할 수 있겠다

이 스크립트를 고의로 누가 지워버리거나 하는 게 아니라면 모든 팀원들에게 실행될 수 있다는 것

스크립트 작성하기

"scripts": {
    "start": "react-scripts start",
    "format": "prettier --write --cache .",
    "lint": "eslint --cache .",
    "postInstall": "husky install" 
}

린터와 포매터를 작동시키는 스크립트를 작성하자

npm run format 을 입력하면 포매터가, npm run lint를 입력하면 린터가 작동되게끔 스크립트를 작성하였다

이 스크립트를 이용하여 husky에 쉽게 훅을 걸어줄 수 있다

훅 추가하기

$> npx husky add .husky/pre-commit "npm run format && git add ."
$> npx husky add .husky/pre-push "npm run lint"

커밋 전 (pre-commit) 에는 npm run format 로 포매팅 후 git add .을 해 준다

푸시 전 (pre-push) 에는 npm run lint 로 린터를 작동시켜 본다

이제 우리는 커밋 전이나 푸시 전에 린터나 포매터를 매번 돌릴 필요가 없어졌다

 

린터에서 오류가 날 경우 (규칙을 어겼을 경우) 해당 시점에서 다음 스크립트를 실행하지 않으므로, pre-push에서 린터를 구동시켰을 때 오류가 날 경우 push에 실패하게 된다

따러서 린터에서 오류가 난 채로 push 가 실행되는 불상사를 막을 수 있다

덤: lint-staged

https://github.com/okonet/lint-staged#reformatting-the-code

$> npm install --save-dev lint-staged

husky와 함께 자주 사용되는 라이브러리

git staged 된 파일에만 린터를 돌려주는 라이브러리로, git staged 된 파일에만 린터를 돌려주므로 git add .을 해 줄 필요가 없다는 장점이 있다

또한 자동으로 git add . 해주는 기능도 있다고 한다

husky 설정

#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"

npx lint-staged

.husky 폴더 내의 원하는 이벤트 (예시: pre-commit 등) 에 해당하는 파일에 위와 같이 npx lint-staged 를 설정하자

이렇게 하면 node-modules 내에 설치된 lint-stagedpre-commit 시마다 실행한다

스크립트 설정

"lint-staged": {
    "*.{ts,tsx}": [
      "prettier --writes .",
      "eslint --quiet --fix ."
    ]
  },

특정 확장자 (ts, tsx) 에 대해서 prettier 와 eslint 를 실행시키는 설정을 적용해 주자

배열 안에 여러 줄의 명령어를 설정할 수 있다

git commit 해보기

커밋을 하면 lint-staged 가 자동으로 수행되면서 설정한 동작들을 차례로 수행한다

체크 표시로 어떤 동작이 완료됐는지 알려주기 때문에 알아보기도 쉽다

 

린터에서 에러가 나올 경우 후속 동작으로 이어지지 않으므로 커밋에 실패한다

이렇게 린터를 통과하지 못하면 커밋을 막는 식으로 모든 코드에 린터를 적용할 수 있는 것


참고 자료

https://techblog.woowahan.com/2530/

https://stackoverflow.com/questions/12222186/are-git-hooks-pushed-to-the-remote-when-i-git-push

https://github.com/okonet/lint-staged#reformatting-the-code

Comments