💡 Next.js / React / Nest.js 등 TypeScript 기반 프로젝트를 새로 시작할 때마다 반복되는 설정을 한번에 정리합니다.
# Prettier
pnpm add -D prettier
# Tailwind CSS를 사용하는 경우
pnpm add -D prettier-plugin-tailwindcss
# ESLint (Flat Config 기준)
pnpm add -D eslint @eslint/js globals typescript-eslint
# React 프로젝트 추가
pnpm add -D eslint-plugin-react eslint-plugin-react-hooks eslint-plugin-react-refresh
# Prettier와 ESLint 충돌 방지
pnpm add -D eslint-config-prettier
# import 정렬 (선택)
pnpm add -D eslint-plugin-perfectionist
# Git hook
pnpm add -D husky lint-staged
npx husky init⚠️ ESLint v9부터 Flat Config(
eslint.config.js)가 기본입니다. 기존.eslintrc.*포맷은 deprecated 되었습니다.
.prettierrc{
"semi": true,
"singleQuote": false,
"tabWidth": 2,
"trailingComma": "es5",
"printWidth": 100,
"arrowParens": "always",
"plugins": ["prettier-plugin-tailwindcss"]
}| 옵션 | 값 | 이유 |
|---|---|---|
semi | true | 세미콜론 명시 — 압축 시 ASI 오류 방지 |
singleQuote | false | JSX 속성은 더블쿼트가 기본 — 일관성 유지 |
tabWidth | 2 | 업계 표준, 중첩 코드 가독성 |
trailingComma | "es5" | 배열/객체 끝 쉼표 — Git diff 최소화 |
printWidth | 100 | 80은 너무 좁고 120은 너무 넓음 — 100이 실무 적합 |
arrowParens | "always" | 매개변수 항상 소괄호 — 일관성 |
plugins | prettier-plugin-tailwindcss | Tailwind 클래스 자동 정렬 (사용 시) |
.prettierignoredist
node_modules
build
*.lock
pnpm-lock.yaml
coverage
.next
.cache
public✅
*.lock/pnpm-lock.yaml은 자동 생성 파일이므로 반드시 제외하세요.public/은 외부 에셋이나 빌드 결과물이 포함될 수 있어 제외하는 것이 안전합니다.
eslint.config.jsimport js from "@eslint/js";
import prettier from "eslint-config-prettier";
import react from "eslint-plugin-react";
import reactHooks from "eslint-plugin-react-hooks";
import reactRefresh from "eslint-plugin-react-refresh";
import { defineConfig, globalIgnores } from "eslint/config";
import globals from "globals";
import tseslint from "typescript-eslint";
export default defineConfig([
globalIgnores(["dist", "node_modules", "build", ".cache"]),
{
files: ["**/*.{ts,tsx}"],
extends: [
js.configs.recommended,
...tseslint.configs.recommended,
react.configs.flat.recommended,
react.configs.flat["jsx-runtime"],
reactHooks.configs.flat.recommended,
reactRefresh.configs.vite,
prettier, // ← 반드시 마지막에!
],
languageOptions: {
ecmaVersion: 2020,
globals: globals.browser,
parserOptions: {
ecmaFeatures: { jsx: true },
},
},
settings: {
react: { version: "detect" },
},
rules: {
// React
"react/react-in-jsx-scope": "off",
"react/prop-types": "off",
// TypeScript
"@typescript-eslint/no-explicit-any": "warn",
"@typescript-eslint/no-unused-vars": [
"warn",
{ argsIgnorePattern: "^_", varsIgnorePattern: "^_" },
],
// HMR
"react-refresh/only-export-components": ["warn", { allowConstantExport: true }],
// React Compiler 사용 시
"react-hooks/preserve-manual-memoization": "warn",
},
},
]);| 규칙 | 설정 | 이유 |
|---|---|---|
react/react-in-jsx-scope | off | React 17+는 JSX에 import 불필요 |
react/prop-types | off | TypeScript로 타입 검사하므로 불필요 |
@typescript-eslint/no-explicit-any | warn | error는 초기 개발 시 너무 엄격 — 점진적 적용 |
@typescript-eslint/no-unused-vars | warn | _ 접두사는 의도적 미사용으로 허용 |
react-hooks/preserve-manual-memoization | warn | React Compiler 도입 시 false positive 방지 |
⚠️ **
eslint-config-prettier**는 반드시extends마지막에 위치해야 합니다. Prettier와 충돌하는 모든 ESLint 포매팅 규칙을 비활성화합니다.
source.organizeImports는 TypeScript Language Server 기반으로 미사용 import 제거 + 알파벳 정렬만 합니다. 그룹 구분(react → 외부 라이브러리 → 내부 @/)이 필요하다면 eslint-plugin-perfectionist를 추가하세요.
import perfectionist from "eslint-plugin-perfectionist";
// rules에 추가
"perfectionist/sort-imports": ["warn", {
type: "natural",
order: "asc",
groups: ["react", "external", "internal", "parent", "sibling", "index"],
}],.vscode/settings.json{
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.formatOnSave": true,
"editor.formatOnPaste": false,
"editor.formatOnType": false,
"editor.tabSize": 2,
"editor.insertSpaces": true,
"editor.detectIndentation": false,
"editor.autoIndent": "full",
"editor.wordWrap": "on",
"editor.codeActionsOnSave": {
"source.fixAll.eslint": "explicit",
"source.organizeImports": "explicit"
},
"files.eol": "\n",
"files.insertFinalNewline": true,
"files.trimTrailingWhitespace": true,
"eslint.useFlatConfig": true,
"eslint.validate": ["javascript", "javascriptreact", "typescript", "typescriptreact"],
"typescript.tsdk": "node_modules/typescript/lib",
"typescript.enablePromptUseWorkspaceTsdk": true
}| 항목 | ❌ 피할 설정 | ✅ 권장 설정 | 이유 |
|---|---|---|---|
formatOnPaste | true | false | 붙여넣기 시 의도치 않은 포매팅 방지 |
언어별 defaultFormatter | 각 언어별로 반복 선언 | 전역 설정만 사용 | 전역 defaultFormatter로 커버됨 — 중복 불필요 |
💡 언어별
defaultFormatter를 각각 명시하는 패턴은 흔히 볼 수 있지만, 전역editor.defaultFormatter를 이미 설정했다면 중복입니다.[css]등 특정 언어에서 다른 포매터를 써야 할 때만 오버라이드하세요.
Husky는 Git Hook을 쉽게 설정할 수 있게 해주는 도구입니다.
Git은 커밋, 푸시 등의 이벤트 전후에 스크립트를 실행할 수 있는 Hook 기능을 기본 제공합니다. 그런데 이 Hook 파일(.git/hooks/)은 git이 추적하지 않아 팀원과 공유가 되지 않습니다.
Husky는 Hook 스크립트를 .husky/ 디렉토리에 저장하고, prepare 스크립트를 통해 pnpm install 시 자동으로 Git Hook에 등록되도록 만들어줍니다.
.git/hooks/ ← Git이 실제로 실행하는 Hook (공유 불가)
.husky/ ← Husky가 관리하는 Hook 원본 (git 추적, 팀 공유 가능)| Hook | 실행 시점 | 주요 용도 |
|---|---|---|
pre-commit | git commit 직전 | lint, format, 테스트 |
commit-msg | 커밋 메시지 작성 후 | 커밋 메시지 컨벤션 검사 |
pre-push | git push 직전 | 전체 테스트, 빌드 검증 |
lint-staged는 git add로 staged된 파일에만 lint/format을 실행합니다.
Husky의 pre-commit에서 eslint .을 직접 실행하면 프로젝트 전체 파일을 검사하므로 느립니다. lint-staged를 사용하면 현재 커밋에 포함된 파일만 검사해서 속도를 크게 줄일 수 있습니다.
✅
Husky (언제 실행할지)+lint-staged (무엇을 실행할지)= 빠르고 안전한 pre-commit
.husky/pre-commitpnpm lint-stagedpackage.json — lint-staged 설정{
"lint-staged": {
"*.{ts,tsx,js,jsx}": [
"eslint --fix --no-warn-ignored",
"prettier --write"
]
}
}git commit
└─ Husky pre-commit
└─ lint-staged (staged 파일만 대상)
├─ eslint --fix → 자동 수정 가능한 lint 오류 수정
└─ prettier --write → 포매팅 통일💡
--no-warn-ignored플래그는globalIgnores에 포함된 파일이 staged될 때 경고를 숨깁니다.
tsconfig.json 체크리스트{
"compilerOptions": {
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true
}
}| 옵션 | 권장값 | 이유 |
|---|---|---|
strict | true | strictNullChecks, strictFunctionTypes 등 전체 활성화 |
noUnusedLocals | true | ESLint no-unused-vars와 이중 방어 |
noUnusedParameters | true | 함수 시그니처 정리 강제 |
⚠️
strict: true로 설정했다면 ESLint의@typescript-eslint/no-explicit-any를error로 올리는 것도 고려하세요.
| 파일 | 역할 | 적용 시점 |
|---|---|---|
.prettierrc | 코드 스타일 규칙 정의 | 저장 시 / 커밋 시 |
.prettierignore | 포매팅 제외 경로 | 항상 |
eslint.config.js | 코드 품질 규칙 정의 | 저장 시 / 커밋 시 |
.vscode/settings.json | IDE에서 위 설정을 자동 실행 | 저장 시 (IDE 레이어) |
.husky/pre-commit | 커밋 시 lint-staged 실행 | 커밋 시 (Git 레이어) |
package.json lint-staged | staged 파일에만 lint/format 실행 | 커밋 시 |
tsconfig.json | 컴파일 타임 타입 검사 | 빌드 시 / IDE 실시간 |
[ 개발 중 ] VSCode settings.json
→ formatOnSave (Prettier)
→ codeActionsOnSave (ESLint fix + organizeImports)
[ 커밋 시 ] Husky pre-commit
→ lint-staged
→ eslint --fix
→ prettier --write
[ 빌드 시 ] tsc (tsconfig strict)
→ 타입 오류 최종 검증✅ IDE 설정 없이 다른 에디터를 사용하는 팀원도 커밋 시점에는 동일한 품질 기준이 강제됩니다.