최근에 회사에서 팀원들과 개발자의 원칙
이라는 책을 읽고 토론을 했다. 책 내용 중 가장 기억에 남았던 부분은 항상 협업 모드로 작업하기
이다. 회사에 개발자가 몇 명이 없고, 개발 문화가 자리 잡고 있지 않다 보니 협업의 기회가 많지 않았다. 하지만 이럴수록 나와의 협업
이 중요하다고 말하는 구문이 있었다. 혼자 하는 작업 이더라도 다른 이, 혹은 미래의 나와 협업하는 상황을 고려하여 작업하면 도움이 된다는데.. 내가 놓치고 있던 부분이라 반성하게 되었다. 최대한 나와의 협업 모드로 개발하자!

협업에 관련된 자료를 공부 하던 중 Husky에 대해 궁금해졌다. 근데 Husky를 알기 위해서는 git hook이라는 지식도 필요했고, 이것 저것 찾아보니 내가 모르고 있었던 부분이 매우 많았다. 이번 기회에 다 알아보자!
배경부터 알아보자 ( feat. 정책을 지키기는 쉽지 않다)
개발 프로세스를 확립하면 배포와 테스트가 흐르듯 흘러간다 생각했지만 현실은 그렇지 않다. ESLint 와 prettier 등 팀별로 정책을 정했다 하더라고 사람이 하는 일이라 실수가 생기기 마련이고, 이를 다시 고치기 위해 코드리뷰를 하며 설명해야 한다.
즉, 팀원들이 정한 정책들을 강제적으로 지키도록 하고자 했다. master 에 직접 밀어넣으려고 하면 작업을 중단해버리고 메세지를 띄워주는 Git Hooks 이라는 좋은 방법이 있었다. (대신 팀원들이 git을 사용한다는 가정 했을 때 이다.)
Git Hooks 란
-
Git Hooks 는 Git 과 관련한 어떤 이벤트가 발생했을 때 특정 스크립트를 실행할 수 있도록 하는 기능을 말한다. (ex. commit, push)
-
크게 클라이언트 훅과 서버 훅으로 나뉜다.
-
클라이언트 훅 : commit, merge, push 발생 전 클라이언트에서 실행됨.
-
서버 훅 : git repo로 push가 발생되었을 때 서버에서 실행됨.
-
-
git hook 설정은 까다롭고, 모든 팀원들이 사전에 repo를 클론받고 메뉴얼하게 사전 과정을 수행해야지만 hook이 실행됨을 보장할 수 있는데 실수로라도 사전 과정을 시행하지 않는다면 hook이 실행되지 않는다.
클라이언트 훅
- pre-commit : commit 을 실행하기 전에 실행
- prepare-commit-msg : commit 메시지를 생성하고 편집기를 실행하기 전에 실행
- commit-msg : commit 메시지를 완성한 후 commit 을 최종 완료하기 전에 실행
- post-commit : commit 을 완료한 후 실행
- pre-rebase : Rebase 하기 전에 실행
- post-rewrite : git commit –amend, git rebase 와 같이 커밋을 변경하는 명령을 실행한 후 실행
- post-merge : Merge 가 끝나고 나서 실행
- pre-push : git push 명령 실행 시 동작하며 리모트 정보를 업데이트 하고 난 후 리모트로 데이터를 전송하기 전에 실행. push 를 중단시킬 수 있음
Git Hooks 적용하기
Git Hook
.git/hooks
디렉토리 안에 저장한다. hook 은 실행가능한 스크립트이며, 설정하고자 하는 훅 이름을 확장자 없이 파일명으로 지정하면 Git Hooks
를 적용할 수 있다.
위 방법대로 궁금해서 .git 파일을 찾아보았다. (숨겨진 파일 찾기 : Mac의 경우 Finder 또는 데스크탑에서 shift +command + . 키를 누르면 숨겨진 파일 .git 을 찾을 수 있다. )

오잉? 이미 있네 ?
찾아보니 .git/hooks 디렉토리에 가보면 Git이 자동으로 넣어준 매우 유용한 스크립트 예제가 몇 개 있다고 한다. 스크립트를 열어보면 어떤 값인지 파일 안에 자세히 설명돼 있다. 예제 스크립트의 파일 이름에는 .sample
이라는 확장자가 붙어 있다. 그래서 이름만 바꿔주면 그 훅을 바로 사용할 수 있다고 한다!
githook 실행 오류 발생 🚨
오키 ~ 한번 테스트 해보자.커밋을 해보니 엥 ? 후크가 실행 가능하도록 설정되어있지 않다고 에러가 발생했다. 🤔

hint: The '.git/hooks/pre-commit' hook was ignored because it's not set as executable.
hint: You can disable this warning with \`git config advice.ignoredHook false\\`.
githook 을 처음에 설정하다보면 아래와 같은 메시지를 볼 경우가 있는데, 이는 권한부여를 해주면 된다.
- 깃 파일 모드 추적 끄기
git config core.filemode false
- 해당 파일에 실행 권한 추가하기
chmod +x .husky/pre-commit
commit-msg 훅 만들기
커멧 메세지에 대한 룰을 지정해보려고 한다! 나는 항상 커밋을 할때 접두어를 붙이는데, 특정 접두어를 붙지지 않을 경우 에러가 발생하도록 스크립트를 만들어보았다.
.git/hooks/commit-msg
#!/bin/sh
commit_msg_file=$1
commit_msg=$(cat "$commit_msg_file")
pattern="^(feat|fix|docs|style|refactor|test|chore|perf) : .+"
if ! [[ $commit_msg =~ $pattern ]]; then
echo "[에러]: 커밋 메세지 포맷이 맞지 않습니다!"
echo "커밋 접두어를 다음과 같이 설정해 주세요"
echo "feat :, fix :, docs :, style :, refactor :, test :, chore :, perf :"
echo "Example : 'feat: Add new feature'"
exit 1
fi
-
에러 발생
-
성공
잘 동작한다 😁
pre-push 훅 만들기
pre-push
훅을 적용하여 직접적으로 main branch에 push를 진행하는 것을 막고자 한다면, 아래와 같이 파일을 생성한다.
- .git/hooks/pre-push
#!/bin/sh
PROHIBITED_REF="refs/heads/main"
if read local_ref local_sha remote_ref remote_sha
then
if [ "$remote_ref" = "$PROHIBITED_REF" ]
then
echo "prevent to push main"
exit 1
fi
fi
exit 0
-
에러 발생
-
성공
-
test 브랜치에서는 성공적으로 push 된다!
-
Git Hooks의 문제점

혼자 개발하는 경우에는 이러한 방법이 나쁘지 않을 수도 있겠지만, 여럿이 개발에 참여하는 경우 아래와 같은 문제가 발생할 수 있다. .git
디렉토리는 버전 관리 대상이 아니므로 레포에 올가가지 않는다. Git 체계 하에서는 Git Hooks 를 공유할 수 없다는 뜻이다.
- hook 스크립트 공유의 어려움.
- 모두가 동일한 버전의 hook을 사용한다는 보장이 없음.
그래서 Husky가 나왔다!

Husky는 git hook 설정을 도와주는 npm package로 번거로운 git hook 설정이 편하다.
또, npm install 과정에서 사전에 세팅해둔 git hook을 다 적용시킬 수 있어서 모든 팀원이 동일한 버전의 Hook 실행이 가능하다.
- Hook 스크립트 공유 가능!
- 모두가 동일한 버전의 Hook을 사용할 수 있음!
Husky 설치 하기
npm install --save-dev husky
Husky 초기 세팅 하기
npx husky init
husky init은 husky의 간단한 초기설정을 도와준다. .husky/에 pre-commit 스크립트를 생성하고 package.json의 prepare 스크립트를 업데이트 해준다. 해당 디렉토리에 가면 아래와 같이 바뀌어 있는 것을 확인할 수 있다.
.husky/pre-commit
npm test
pakage.json
{
"scripts": {
"prepare": "husky"
}
}
다음 과 같이 .husky
디렉토리가 생성되는것을 확인할 수 있다. /.husky 안에 hook 스크립트를 추가하면 된다.
/.husky
└─ _
└─ .gitignore
└─ husky.sh
└─ 내가 추가할 script...
.husky/pre-commit
echo "pre-commit test"
exit 1
위처럼 작성을 하고 commit 을 하면 "pre-commit test"가 찍히는 것을 확인할 수 있다. 😄
husky를 사용해서 commit-msg 훅 만들기
.husky/commit-msg
#!/bin/sh
commit_msg_file=$1
commit_msg=$(cat "$commit_msg_file")
pattern="^(feat|fix|docs|style|refactor|test|chore|perf) : .+"
if ! [[ $commit_msg =~ $pattern ]]; then
echo "[에러]: 커밋 메세지 포맷이 맞지 않습니다!"
echo "커밋 접두어를 다음과 같이 설정해 주세요"
echo "feat :, fix :, docs :, style :, refactor :, test :, chore :, perf :"
echo "Example : 'feat: Add new feature'"
exit 1
fi
echo "pre-commit 훅 테스트 중입니다."
exit 1
-
에러발생
-
성공
그냥 husky 아래에다가 넣어 주면 끝.. 너무 쉽다!
git hook 에서 적용한 것 처럼 규칙에 어긋난 커밋 메세지일 경우 커밋이 잘 거부 되었다! 🚀
마무리
나와의 협업 하기 1탄 이 마무리 됐다. (아직 갈 길이 멀기 때문에 1탄이라고 칭했다.)
만약 husky를 처음부터 공부했다면, husky라는 라이브러리를 만들게 된 이유와 git hook이 내부적으로 어떤식으로 돌아가는지 알 지 못했을 것이다. “와 진짜 편해졌다” 를 느낄 수 있었다. 동시에 편리함에 진심인 개발자들도 정말 많다는 것도 느꼈다.
husky와 함께 사용하면 더욱 빛을 발휘는 라이브러리들도 같이 찾아볼 수 있었다. 커밋 메시지의 규칙성을 관리하는 commitlint와 코드 품질을 자동으로 검사하는 lint-staged 또한 차차 적용시켜 볼 예정이다.
참고
https://git-scm.com/book/ko/v2/Git맞춤-Git-Hooks
https://library.gabia.com/contents/8492/
https://moon-i.tistory.com/entry/GIT-git-hook-commit-msg-적용하기