Git Hooks를 내 프로젝트에 통합해주는 Husky
August 2, 2021 12:41 AM:git
hooks
라고 구글에 검색해보면 갈고리 모양의 이미지가 여러 개 나온다. 리액트에서도 hooks
라는 용어를 사용하고 깃에서도 hooks
라는 개념이 존재한다. Vue에서는 인스턴스 라이프 사이클 훅이라는 말로 hooks
를 사용하는데, 각 컴포넌트에서 어떤 시점마다 이벤트가 발생하면 훅이 실행된다. 예를 들어 컴포넌트가 생성될 때의 시점을 뜻하는 created
훅이 있고 DOM에 부착되는 시점인 mounted
가 있다. (Composition API에서는 onMounted
)
각각의 훅에서는 전역적으로 지정된 어떤 함수가 실행되고 여기에 우리는 갈고리처럼 훅마다 실행되는 함수에 내 함수를 얹어 이 시점에 내 함수가 돌아가게끔 할 수 있다. 깃에서는 이런 hooks
들이 여러 종류가 있다.
모든 hooks
의 종류는 여기에서 참고할 수 있고, 여기에서는 아주 간단한 그리고 매우 중요한 몇 가지의 hooks
만 정리한다.
우리가 깃을 통해서 프로젝트의 버전 관리를 하고 있다면 프로젝트 루트 디렉터리 내 .git
이라는 디렉터리가 존재한다. 에디터상에서는 안보이지만, explorer
, terminal
혹은 finder
를 통해 해당 디렉터리가 존재한다는 것을 확인할 수 있다. 해당 디렉터리의 기본적으로 hooks
라는 디렉터리에 깃에 존재하는 여러 가지 클라이언트 훅에 대한 샘플이 존재하는데, ****.sample
형태로 작성되어 있고, 예제 및 해당 hooks
가 실행됬을 때 어떠한 매개변수를 취할 수 있는지, 어떤 행위를 하는지에 대한 자세한 내용이 기술되어 있다.
기본적으로 쉘 스크립트 혹은 Perl
언어로 작성되어있는 스크립트인데, 개인적으로 익숙한 스크립트 언어를 사용해서 해당 hooks
를 커스텀할 수 있다. .sample
이라는 확장자를 지우면 바로 사용할 수도 있다.
여기서 살펴볼 hooks
는 pre-commit
과 pre-push
가 되겠다. 각각 commit
을 찍기 전과 원격 저장소에 push
하기 전에 대한 hooks
인데, 해당 스크립트를 잘 짜면 커밋 메세지가 찍기 전 코드 스타일을 점검할 수 있고, 정적 타입 분석 도구를 통해 타입 오류를 검사할 수도 있다. 그렇게 하면 실제로 일어날 수 있는 실수를 덜기 쉽다.
간단히 스크립트 수정을 통해 Git Hooks를 제어할 수 있다면 왜 이런 오픈 소스가 필요할까?
이유는 어떤 작업을 수행하게 하도록 하기 위해서 일련의 스크립트를 수정하는 작업은 매우 지겨울 수 있다. 그리고 새로운 프로젝트를 시작할 때 이러한 템플릿을 구성하기가 귀찮다.
개발을 할 때에 각 컴포넌트에 대해 테스트가 이미 존재하고 로직을 수정하고 개발할 때에 기존의 테스트가 실패하면 커밋을 찍고 저장소에 푸시하면 안된다. 하지만 이러한 과정은 꼭 필요한 작업이긴 하지만 놓칠 때가 있고 항상 확인하기가 어렵지 않으나 종종 실수를 한다.
export function add(a, b) {
return a + b
}
// .... Test Case
describe('Test add function', () => {
test('Add A and B', () => {
expect(add(1, 2)).toBe(3)
expect(add(2, 2)).toBe(4)
expect(add(3, 2)).toBe(5)
expect(add(3, 3)).toBe(6)
expect(add(5, 2)).toBe(7)
})
})
예를 들어서 두 개의 인자를 받아 더한 뒤 값을 반환하는 함수인 add
함수가 있다. 그리고 하단과 같이 해당 함수에 대한 테스트 케이스가 존재한다. (매우 극단적일순 있지만) 그런데, 수정의 수정을 거듭하여 인자로 오는 값이 number
타입이 아닌 어떤 객체로 변했다고 하자. 그러면 이 테스트 케이스는 실패할 수 밖에 없으며 해당 테스트 케이스를 수정하거나 로직을 다시 수정해야 한다.
언제나 사림이 완벽할 순 없는 법... 테스트를 직접 돌려보지 않고 그대로 커밋을 찍어 푸시했을 수도 있다. 물론 저장소에 푸시되면 web hook이 트리거 되어 자동으로 테스트를 진행하여 실패한 케이스에 대해서 알림이 전송되는 시스템이 구축되어 있다면 이해가 되지 않을 수도 있다. 그런 시스템을 구축해서 개발해야 되는 것이 맞다고 보지만, 만약 테스트 케이스가 몇 백개가 되고, 몇 천개가 되어 모든 테스트 케이스를 돌리기에 충분한 시간이 없어 미쳐 다른 의존성이 있는 테스트가 실패할 때를 생각하면 이해가 된다.
위와 같은 예제에서 커밋 메세지를 찍기 전 어떠한 작업을 할 수 있게 도와주는 오픈 소스가 바로 Husky다. 바로 설치해보자.
npm i -D husky
npx husky install
npm set-script prepare "husky install"
husky
의존성을 설치하고 husky
에서 기본적으로 git hooks를 제어하기 위한 코드를 생성하기 위해서 npx husky install
명령어를 쳐준다. 그리고 prepare
라는 명령어를 지정한다. prepare
에 대한 자세한 내용은 npm lifecycle을 참고한다.
이제 지정할 훅을 만들면 되는데 이 것 또한 명령어를 통해 손쉽게 만들 수 있다.
npx husky add .husky/pre-commit "npm test"
git add .husky/pre-commit
이제 pre-commit
훅에 대한 행위가 만들어졌고, 커밋 메세지가 찍기 전 npm test
를 실행하고 테스트가 실패하면 커밋 메세지가 찍히지 않는다. 핵심적인 기능은 이게 다이고 여기에 여러 훅을 섞거나 아니면 코드를 lint하거나, 타입 분석을 하거나 테스트를 하는 등 여러 가지 명령을 묶을 수 있다.