⏱️ 예상 읽기 시간: 18분(전체) / 핵심 파트만: 8분 (pre/post + husky)
🗺️ 이 문서의 흐름
scripts 기본 → pre/post 훅 → 라이프사이클 전체 지도 → 환경변수 → husky & lint-staged → 완성형 설정
🎯 이 문서를 다 읽으면 할 수 있는 것
npm run build 전에 자동으로 타입 체크가 실행되도록 prebuild 를 설정할 수 있다
prepare 훅을 이용해 팀원이 npm install 만 해도 husky 가 자동 세팅되도록 만들 수 있다
Windows/Mac/Linux 모두에서 동작하는 환경변수 설정을 cross-env 로 구현할 수 있다
lint-staged 로 커밋할 파일에만 린트와 포맷을 실행하도록 설정할 수 있다
🗺️ 이 문서의 배경 세계관: '영수네 커뮤니티'
🐣 영철 ( 신입 ): "리드 님, 팀원들이 ESLint 에러 있는 코드를 자꾸 커밋해요. 저도 가끔 깜빡하고요. 빌드 때마다 린트 에러 잡는 게 너무 번거로워요. 그리고 NODE_ENV=production next build 이렇게 스크립트 작성했는데, 팀에 Windows 유저가 있어서 그 분 환경에서만 실패한대요. 어떻게 하면 되나요?"
🦁 영호 ( 리드 ): "두 문제 모두 해결 방법이 있어요. 환경변수는 cross-env 로, 린트 자동화는 husky + lint-staged 로요. husky 는 git hook 에 연결해줘서 git commit 할 때 자동으로 린트가 실행돼요. prepare 훅을 쓰면 팀원이 npm install 만 해도 자동으로 설정이 완료돼요."
🤔 왜 알아야 하는가
코드 리뷰에서 실제 비즈니스 로직이 아닌 "ESLint 경고 있어요", "세미콜론 빠졌어요" 같은 피드백이 올라오면 시간 낭비다. 또한 CI 에서 린트 검사를 하면 "왜 미리 잡지 않았나요?" 하는 피드백이 나온다.
husky + lint-staged + pre-commit 훅 을 설정하면 커밋하는 순간 자동으로 린트와 포맷이 실행되어, 깨끗하지 않은 코드는 아예 커밋이 안 된다. 팀 전체의 코드 품질이 자동으로 유지된다.
scripts 는 단순한 명령어 모음이 아니다. 개발 워크플로 전체를 자동화하는 파이프라인이다.
📜 scripts 기본 문법과 실행 방법
{ "scripts": { "dev": "next dev", // 🐯 개발 서버를 띄울 때 가장 많이 치게 될 명령어예요. "build": "next build", // 프로덕션 용으로 최적화된 결과물을 만듭니다. "start": "next start", // 빌드된 결과물을 실제 서버로 돌릴 때 씁니다. "lint": "next lint", // 린트(코드 스타일) 체크를 합니다. "type-check": "tsc --noEmit", // 🦁 타입스크립트 에러가 없는지만 딱 확인합니다. (파일 생성 X) "test": "jest" }}
npm run dev # 개발 서버npm run build # 빌드npm run type-check # 타입 체크# run 을 생략할 수 있는 특수 명령어npm test # jest 실행npm start # next start 실행
scripts 안에서 다른 script 참조
{ "scripts": { "lint": "next lint", "type-check": "tsc --noEmit", "validate": "npm run lint && npm run type-check" }}
npm run validate # lint → type-check 순서로 실행
⏪⏩ pre / post 훅 — 자동 실행 체이닝
pre<script> 와 post<script> 는 특정 스크립트 전후에 자동으로 실행된다.
{ "scripts": { // 💡 [선수 필승] 빌드 전에 타입 에러가 하나라도 있으면 빌드를 시작도 안 하고 멈춥니다! "prebuild": "npm run type-check", "build": "next build", // 🦁 [뒷정리] 빌드가 성공하고 나면 사이트맵을 자동으로 생성하도록 예약합니다. "postbuild": "node scripts/generate-sitemap.js" }}
npm run build 실행 시 자동으로:prebuild (타입 체크) ↓build (Next.js 빌드) ↓postbuild (사이트맵 생성)
🔥 실무 활용 패턴:
{ "scripts": { "pretest": "npm run type-check", "test": "jest", "posttest": "echo '✅ 모든 테스트 통과'" }}
pre/post 훅은 언제 쓰면 좋은가:
상황
훅
스크립트
빌드 전 타입 에러 사전 차단
prebuild
tsc --noEmit
빌드 후 사이트맵/번들 분석
postbuild
분석 스크립트
배포 전 최종 검증
predeploy
lint + test
🗺️ 라이프사이클 훅 전체 지도
npm 은 특정 명령어 실행 시 자동으로 트리거되는 내장 라이프사이클 훅을 제공한다.
npm install 라이프사이클
npm install 실행 시:
preinstall
↓
install / postinstall
↓
prepublish (deprecated)
↓
prepare ← 가장 중요! npm install 후 항상 실행
↓
prepublishOnly ← npm publish 시만 실행
prepare — 팀 자동화의 핵심
{ "scripts": { "prepare": "husky install" }}
prepare 는:
npm install 후 자동 실행
npm publish 전 자동 실행
git 에서 클론 후 npm install 시 자동 실행
효과: 팀원이 처음 프로젝트를 클론하고 npm install 만 하면 husky install 이 자동 실행되어 git 훅이 세팅된다. 별도 문서 없이 자동으로!
npm install 후 자동으로 prisma generate 가 실행되어 Prisma Client 가 생성된다.
npm install 실행 → 의존성 설치 완료 → postinstall 자동 실행 → prisma generate
팀원이 클론 후 겪는 공통 문제 해결:
{ "scripts": { // 🦁 팀원이 처음으로 이 프로젝트에 들어왔을 때, npm install만 치면... // 1. husky가 자동 설치되고 (.prepare) "prepare": "husky", // 2. 프리즈마 클라이언트가 자동 생성됩니다 (.postinstall) "postinstall": "prisma generate" }}
이 두 줄이 있으면 팀원은 npm install 만으로:
git 훅 자동 설정 (husky)
Prisma Client 자동 생성
완료된다.
🌍 환경변수와 scripts — cross-env 패턴
문제 — OS 별 환경변수 문법 차이
# Linux / macOS (동작)NODE_ENV=production next build# Windows (동작 안 함!)NODE_ENV=production next build # ← 에러set NODE_ENV=production && next build # ← Windows 문법
{ "scripts": { "build:prod": "NODE_ENV=production next build" // Windows 팀원 PC 에서 실패! }}
해결 — cross-env
npm install -D cross-env
{ "scripts": { // 💡 Windows와 Mac/Linux는 환경변수 문법이 달라서 가끔 싸워요. // 'cross-env' 앱이 중간에서 통역사 역할을 해주어 모두가 행복해집니다. "build:prod": "cross-env NODE_ENV=production next build", "build:analyze": "cross-env ANALYZE=true next build", "test:prod": "cross-env NODE_ENV=test jest" }}
cross-env 는 OS 에 상관없이 환경변수를 설정해준다.
Next.js 에서 환경변수와 scripts 패턴
{ "scripts": { "dev": "next dev", "dev:turbo": "next dev --turbo", "dev:debug": "cross-env NODE_OPTIONS='--inspect' next dev", "build": "next build", "build:analyze": "cross-env ANALYZE=true next build", "build:prod": "cross-env NODE_ENV=production next build", "start": "next start", "start:prod": "cross-env NODE_ENV=production next start -p 8080" }}
🐶 husky & lint-staged — 코드 품질 자동화
설정 과정
# 1. 설치npm install -D husky lint-staged# 2. husky 초기화npx husky init# → .husky/ 디렉터리 생성 + prepare 훅 자동 추가
// package.json 에 자동 추가된 내용{ "scripts": { "prepare": "husky" }}
pre-commit 훅 설정
# .husky/pre-commitnpm run lint-staged
// 🐶 package.json{ "lint-staged": { // 🦁 영철아, 모든 파일을 검사하면 너무 느리니까 "이번에 내가 수정한 파일"만 골라서! "*.{ts,tsx}": [ "eslint --fix", // 💡 고칠 수 있는 건 지가 알아서 다 고쳐줍니다. "prettier --write" // 💡 줄바꿈, 세미콜론까지 깔끔하게! ], "*.{json,md,css,scss}": [ "prettier --write" ] }}
동작 흐름
git commit 실행
↓
husky 의 pre-commit 훅 트리거
↓
lint-staged 실행
↓
커밋 대상 파일만 선별
(git add 된 파일들만 — 전체 파일 검사 아님!)
↓
*.ts, *.tsx → eslint --fix + prettier --write
*.json, *.md → prettier --write
↓
수정된 파일 자동으로 다시 staging
↓
커밋 완료 (에러 있으면 커밋 중단)
💡 lint-staged 의 핵심: 전체 파일이 아닌 커밋 대상 파일만 검사한다. 10만 줄짜리 프로젝트에서도 커밋하는 파일 5개만 검사하므로 빠르다.
# run-s = run-sequential (순차)npm run validate# type-check 완료 → lint 실행 → test 실행# run-p = run-parallel (병렬)npm run validate:ci# type-check 와 lint 동시에 실행 (더 빠름)
a) npm install 실행 후
b) npm publish 실행 전
c) npm run build 실행 전
d) git 클론 후 npm install 실행 시
✅ 정답: c — npm run build 전에는 실행되지 않는다
💡 상세 해설:
원리 설명: prepare 는 npm 의 내장 라이프사이클 훅으로, npm install (의존성 설치), npm publish (패키지 배포), npm pack 실행 시 트리거된다. npm run <임의스크립트> 실행 시에는 트리거되지 않는다. npm run build 전에 뭔가를 자동 실행하려면 prebuild 훅을 사용해야 한다.
📌 핵심 기억법: "prepare = npm 내장 이벤트(install, publish)에만 반응. 커스텀 스크립트에는 pre<script> 를 사용."
Q2. lint-staged 를 사용하는 주요 이유는?
a) ESLint 를 더 빠르게 실행하기 위한 캐시 시스템이다
b) 커밋할 파일만 선별해 린트를 실행하므로 속도가 빠르고 불필요한 검사를 줄인다
c) git blame 에서 린트 관련 커밋을 숨긴다
d) ESLint 설정을 자동으로 생성해준다
✅ 정답: b — 커밋 대상 파일만 선별해 실행
💡 상세 해설:
원리 설명: lint-staged 는 git add 된 파일(staged files)만 필터링해서 린트와 포맷을 실행한다. 1만 개 파일이 있어도 커밋하는 5개 파일만 검사하므로 매우 빠르다. 또한 --fix 옵션으로 자동 수정된 파일을 다시 staging 해주어 수정 후 재커밋 없이 바로 커밋된다.
📌 핵심 기억법: "lint-staged = 변경한 파일만 검사. 전체 검사가 아니라 staged(커밋 예정) 파일만."
Q3. 🐣 영철이의 테스트 타임 — 아키텍처 설계
영숙 디자이너가 슬랙에 메시지를 보냈다. "영철 님, 제가 작은 CSS 수정을 했는데 커밋하려고 했더니 자꾸 ESLint 에러가 나서 커밋이 안 돼요. 저는 CSS 만 바꿨는데요..." 영호 리드가 "lint-staged 설정 확인해봐요" 라고 했다. 현재 설정은: