모노레포 pnpm으로 husky + lint-staged 적용하기

dobby·2025년 11월 6일
0
post-thumbnail

husky + lint-staged 설정

이전 프로젝트를 진행하면서, 팀원이 lint 에러를 수정하지 못하고 push를 해서 수정된 코드를 pull 받은 팀원이 해결해야 하는 문제가 있었습니다.

그리고 prettier가 버그로 인해 동작하지 않았을 때 (IDE or 특정 폴더에서는 동작하지 않는 등) push를 해서 다른 팀원이 pull로 코드를 받았을 때 파일의 모든 부분이 변경되는 문제점도 있었습니다.

이 문제들을 해결하기 위해 husky + lint-staged를 설정하기로 결정했습니다.
설정 후엔 위의 문제들이 해결되고, 깜빡하고 넘어갔던 lint 에러도 해결이 되어 배포시 발생했던 lint 오류도 훨씬 줄어들었습니다.

이번 그룹 스프린트에서도 협업이기에 비슷한 문제가 발생할 경우를 대비해 husky + lint-staged 를 설정하기로 했습니다.

먼저, 모노레포로 프로젝트가 설정되어 있기에 이를 고려해 진행했습니다.

- app/
   |- frontend/
   |- bacnend/

설치하기

husky는 깃의 특정 이벤트가 발생할 때 자동으로 원하는 스크립트를 실행할 수 있게 해주는 역할을 합니다.

공식 문서 설치가이드를 통해 husky를 각 패키지 매니저로 설치할 수 있습니다.

저희는 pnpm 을 사용하고 있기에, 다음의 명령어를 입력해 설치 및 초기화했습니다.

pnpm install -D husky lint-staged -w

-w 는 pnpm의 모노레포 환경 보호 기능을 끄기 위해서 추가한 옵션입니다.
pnpm을 사용하면 루트 디렉토리는 워크스페이스의 중앙 관리 지점입니다.

pnpm install -D husky lint-staged 를 루트에서 실행하면, pnpm은 이 의존성이 모든 서브 프로젝트에서 사용될지, 아니면 루트에서 관리되는 도구로만 사용될지 명확하지 않다고 판단합니다.

그렇기에 이 의존성을 워크스페이스 루트에 추가하는 것이 의도한 것이라면 -w 플래그를 사용해 명시적으로 알려달라고 요청합니다.

 ERR_PNPM_ADDING_TO_ROOT  Running this command will add the dependency to the workspace root, which might not be what you want - if you really meant it, make it explicit by running this command again with the -w flag (or --workspace-root). If you don't want to see this warning anymore, you may set the ignore-workspace-root-check setting to true.

위의 문제를 해결하기 위해 -w 옵션으로 의도한 것이라는걸 알려주는 것입니다.

이제 초기화를 시키기 위해 다음의 명령어를 입력합니다.

pnpm exec husky install

위의 명령어를 입력하면 루트 폴더에 .husky 폴더가 생기는 것을 볼 수 있습니다.


설정하기

이제 커밋을 하게 될 때 자동으로 lint와 prettier가 작동되도록 설정해야 합니다.

husky 가 버전이 업그레이드되면서 CLI로 pre-commit 훅을 설정하는 방식이 DEPRECATED 되었습니다.

그렇기에 직접 pre-commit 파일에 접근해서 코드를 작성해주어야 합니다.

다음과 같이 작성해주었습니다.

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

pnpm exec lint-staged
  • #!/usr/bin/env sh : 이 파일이 쉘 스크립트임을 선언하고, 시스템 환경 변수를 사용해 sh 인터프리터로 실행되도록 지정합니다.
  • . "$(dirname -- "$0")/_/husky.sh" : husky가 제공하는 실행 환경을 불러와 훅을 실행할 준비를 합니다. husky가 올바른 환경에서 실행되도록 보장하는 필수 초기화 코드입니다.
  • pnpm exec lint-staged : 스테이징된 파일만 검사하고 수정하는 lint-staged 도구를 실행합니다.

husky만 적용하면 변경된 파일뿐만 아니라 모든 파일에 대해 매번 수행을 하기 때문에 시간이 오래걸리며 불필요한 작업이 수행되게 됩니다.

lint-staged는 이 문제를 해결해줍니다.
커밋하기 전에 변경된 파일에 대해서만 린트와 포맷팅 작업을 수행하도록 트리거합니다.

lint-staged 를 설정해주었으니, package.json에 lint-staged 가 실제로 어떤 파일을 검사하고 어떤 명령을 실행할지에 대한 규칙을 정의하는 블록을 작성해주어야 합니다.

  // package.json
  "lint-staged": {
    "app/frontend/**/*.{js,jsx,ts,tsx}": [
      "pnpm exec eslint --fix --cwd app/frontend",
      "pnpm exec prettier --write"
    ],
    "app/backend/**/*.{js,ts}": [
      "pnpm exec eslint --fix --cwd app/backend",
      "pnpm exec prettier --write"
    ],
    "*.{json,css,md,yaml,yml}": [
      "pnpm exec prettier --write"
    ]
  },

위의 "lint-staged" 를 추가해줍니다.

저희는 app/frontendapp/backend 로 분리했기에 위처럼 작성해주었습니다. 각 팀의 폴더 구조에 맞게 작성해주시면 됩니다.

이제 커밋을 하게 될 때마다 린트와 포맷팅 작업을 수행하게 됩니다.


(브랜치 이름은 오타가 맞습니다 ㅎㅎ..)

여기서 경고 메시지가 보입니다.

husky - DEPRECATED

Please remove the following two lines from .husky/pre-commit:

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

They WILL FAIL in v10.0.0

이는 husky가 v10에서 스크립트 실행 방식이 변경될 예정임을 미리 알려주는 단순 경고 메시지입니다.

husky 버전이 올라가면서 스크립트 실행 환경을 초기화하는 방식을 더 단순화하고 있기에 알려주는 경고 메시지입니다.

아직은 v9이기 때문에 안전하지만, v10으로 변경될 때 지원을 중단할 예정이며 문제가 발생할 수 있으니 미리 삭제하라고 권장합니다. (안바꿔도 됩니다! v10으로 업그레이드 할 계획이 없다면)

메시지는 pre-commit 에서 설정한 . "$(dirname -- "$0")/_/husky.sh" 명령어를 없애라고 합니다.

#!/usr/bin/env sh

pnpm exec lint-staged

위처럼 pre-commit 을 바꿔 다시 커밋을 날려보면 lint-staged가 동작하지 않습니다!

v10 버전부터 제거해야하는거고, 현재 husky 버전(v9.1.7)에서는 이 줄이 필수적인 초기화 코드이기 때문이다.

그러니, 다시 붙이자….

profile
성장통을 겪고 있습니다.

0개의 댓글