본문으로 건너뛰기

Githook, Husky를 이용한 file name 규칙 검사하기

팀 내부적으로 file naming을 kebab-case(단어 구분을 하이픈으로 짓는 형식) 고정 하자는 규칙을 세웠던 적이 있습니다. camelCase나 PascalCase로 하는 경우에 OS와 git의 기본옵션에 의해 파일명에서 대소문자 구분을 하지 않을 수 있기 때문에, 의도대로 파일명을 구분하지 못 할 수도 있기 때문이였습니다.


문제의 원인

직접 파일명을 작성해야하는 인간에게 문제가 발생합니다. 파일명을 직접 작성해야하기 때문에 파일명을 다른 케이스로 충분히 작성할 위험이 있습니다. 따라서 이런 휴먼 에러를 제거하여 규칙이 잘 적용되도록 해야겠습니다.


해결방안

해당 파일이 commit되기 전에, 파일명을 검사하고 kebab-case가 아니라면 commit을 강제종료시키도록 하여 파일명 수정을 유도하도록 해야겠습니다. 이를 위해 pre commit Git hook을 작성하여 커밋 전에 파일명을 검사하도록 하겠습니다.


Git Hook

Git Hook이란 git과 관련한 이벤트가 발생하는 경우, 특정 Shell Script를 실행할 수 있도록 해주는 기능입니다. 13가지의 클라이언트 hook이 존재하는데 여기에서는 pre-commit을 활용합니다.

.git/hooks/ 폴더 안에 적용할 hook을 이름으로 Shell Script 파일을 생성합니다. .git/hooks/pre-commit 이런식으로 파일이 만들어질 수 있겠네요.

그런데 .git/hooks/ 디텍로티에 스크립트를 위치시키면 git 변경사항에 반영이 되지 않아 원격 레포지토리 push를 통해 팀원들과 해당 스크립트를 공유할 수 없다는 단점이 있습니다.


Husky 사용하기

그러나 이러한 문제를 Husky를 통해서 해결할 수 있습니다. git hook을 .husky 폴더에 작성해두고 팀원과 해당 스크립트를 공유할 수 있도록 해줍니다.

  1. Husky를 설치합니다.
npm install --save-dev husky
  1. Husky 셋업을 실행합니다.
npx husky init

위 두 명령어를 통해 최종적으로 .husky 폴더와 그 안의 스크립트 파일들을 얻을 수 있습니다.


kebab-case를 검사하는 스크립트

pre-commit, 즉 commit이 실행되기 전에 스크립트를 실행시키기 위해서 .husky/pre-commit에 아래와 같이 코드를 작성합니다.

# staged인 모든 파일명들을 가져옵니다.
staged_files=$(git diff --cached --name-only --diff-filter=ACMR)

# kebab-case를 검사하는 정규표현식을 작성합니다.
kebab_case_regex='^[a-z0-9]+(-[a-z0-9]+)*(\.[a-z0-9]+)?$'

# 모든 파일명이 유효한지 검사하는 플래그를 지정합니다.
all_files_valid=true

# staged된 파일명을 순회하며 검사합니다.
# kebab-case가 아닌 파일명은 에러메시지를 보여줍니다.
for file in $staged_files; do
# file의 basename만 가져옵니다.
filename=$(basename "$file")

# filename이 정규표현식에 일치하는지 검사합니다.
if ! [[ $filename =~ $kebab_case_regex ]]; then
echo "Error: File '$filename' is not in kebab case."
all_files_valid=false
fi
done

# 모든 파일명이 유효하지 않다면 프로세스를 종료합니다. (커밋 중단됨)
if [ "$all_files_valid" = false ]; then
echo "Please rename the files to kebab case before committing."
exit 1
fi

exit 0

이제 commit을 진행시 위의 스크립트가 먼저 실행되고 통과되어야 commit 프로세스가 정상적으로 종료됩니다.