Skill
2025년 12월 05일

내 프로젝트에 CI/CD를 적용해보자 (1) 코드 품질 자동 검증

위대하신 AI 가 추천해준 CI/CD 순서중에 첫번째 코드품질 자동 검증을 적용시켜보려고한다.

Gemini : Github 레포를 vercel로 배포하고있기 때문에 Github Actions 를 통해 타입체크 와 린트 검증 및 PR 품질 체크를 하고 Husky + lint-staged 를 통해 커밋전 자동 검증을 추가하면 더 좋을거야 (Level 1)

  • GitHub Actions - 타입체크 & 린트
# PR이나 Push마다 자동 실행 - TypeScript 타입 에러 체크 - ESLint 코드 스타일 검사 - 빌드 성공 여부 확인
  • Git Hooks (Huskey + lint-staged)
# Git commit 전에 자동 실행 - Staged 파일만 린트 체크 - 포맷팅 자동 수정 - 문제 있으면 커밋 차단

이렇게 하면 된다는데 그래서 하나씩 알아보자….

Git Hooks 란?

commit, push 등 git 이벤트가 발생했을때 특정 스크립트를 실행할 수 있게 하는 기능으로 이를 활용해 코드 스타일 검사테스트 등을 자동화 할 수 있음

Husky, Lefthook 과 같은 npm package로 일관성 있게 Git Hooks를 적용하는게 일반적

Huskey vs LeftHook

기술 스택의 차이 (Node.js vs. Go)

  • Husky: Husky는 Node.js 환경에서 작동하도록 설계되었으며, 훅이 실행될 때 Node.js 스크립트를 통해 작업을 처리합니다.
  • LeftHook: LeftHook은 Go 언어로 작성된 단일 바이너리 파일입니다. 훅이 실행될 때 복잡한 런타임 환경을 로드할 필요가 없기 때문에 실행 속도가 훨씬 빠릅니다.

설정의 간결성

  • Husky: Git Hooks를 설정할 때, .husky 폴더 내부에 pre-commit 등 각 훅 이름의 파일을 만들고 그 안에 스크립트를 정의해야 합니다.
  • LeftHook: 모든 훅의 설정과 실행할 명령어는 lefthook.yml이라는 단일 YAML 파일 내에서 명확하게 정의됩니다. 이는 설정을 파악하고 관리하기 쉽게 만듭니다.

✅ 그래서 LeftHook을 선택한 이유?

  1. 실행 속도 : LeftHooks은 Go기반의 컴파일된 바이너리로, 실행 시 지연 시간이 거의 없어 개발자가 체감하는 워크플로우 속도가 매우 빠르고 쾌적
  2. 병렬 실행 지원 : LeftHook은 YAML 설정 내에서 parallel: true 옵션을 사용해 여러 명령어들을 병렬로 실행


그러면 lint-staged는 뭐야?

lint-staged의 역할은 다음과 같습니다.

커밋 직전 (pre-commit 훅)에, Git의 '스테이징(Staged)' 영역에 올라와 있는 파일들만 골라 정해진 명령어(린트, 포맷팅, 테스트 등)를 실행해주는 도구

  • lint-staged가 필요한 이유? : lint-staged 없이 Git Hook을 사용한다고 가정했을때, 프로젝트 내의 모든 파일을 대상으로 검사를 진행하게되는데, 이때 프로젝트의 크기가 클수록 시간이 너무 오래걸림

  • lint-staged의 역할? : git add 명령어로 커밋 대상이 되기위해 대기하고 있는 파일들에 한해서만 검증을 실행한다.

💡따라서, Git hooks 와 lint-staged를 결합하여 작업하는 파일에 한해서 빠르게 검증을 실행할 수 있다.


LeftHook + lint-staged 적용 과정

동작 과정

1. npx lefthook install 실행 2. .git/hooks/pre-commit 파일 생성 3. git commit 시도 4. Git이 자동으로 .git/hooks/pre-commit 실행 5. pre-commit 파일이 lefthook을 호출 6. lefthook이 .lefthook.yml 읽기 7. .lefthook.yml에 설정된 명령 실행 (lint-staged)

Step1. 패키지 설치

npm install -D lefthook lint-staged npx lefthook install

Step2. 파일 생성

  • .lefthook.yml 파일을 root 경로에 생성하여 작성
  • pre-commit: 커밋 전에 실행되는 훅
  • parallel: true: 병렬 실행으로 속도 향상
  • stage_fixed: true: 자동 수정된 파일을 다시 staged에 추가

Step3. Package.json에 lint-staged 설정 추가

# package.json { "scripts": { "prepare": "lefthook install" }, "lint-staged": { "*.{ts,tsx,js,jsx}": [ "eslint --fix", "prettier --write --ignore-path .prettierignore" ], "*.{json,css,md}": [ "prettier --write --ignore-path .prettierignore" ] } }
  • prepare 스크립트: npm install 시 자동으로 lefthook 설치
  • lint-staged: staged된 파일만 검사

Step4. prettierignore에 CI/CD 설정 파일 추가

// .prettierignore // CI/CD config files ... ... .lefthook.yml .github/workflows/*.yml ...
  • 여기서 설정을 안하면 여기에 설정되지 않은 파일들이 다시 새로운 커밋으로 남게된다.

Step5. 테스트

  • 이제 git commit 시에 자동으로 lefthook이 동작하며 설정한 prettier와 lint 검사를 사전에 실행하게 해준다.
  • 마찬가지로 푸시/PR 시에도 GitHub Actions 로 인해 동작

  • 커밋시
git commit 시도 .git/hooks/pre-commit 실행 lefthook 실행 lint-staged 실행 (staged 파일만) ESLint + Prettier 검사 문제 없으면 커밋 성공 ✅
  • Push / PR 시
git push / PR 생성 GitHub Actions 실행 타입 체크 → 린트 → 빌드 검증 성공 → Vercel 배포 ✅ 검증 실패 → 배포 차단 ❌