콘텐츠 대표 이미지 - ESLint & Prettier
🛠️ 개발 도구 가이드

ESLint & Prettier

코드 포맷팅과 품질 관리 도구 완전 정복 🚀

코드가 지저분해서 팀원한테 혼난 적 있어? 이제 그런 일 없게 해줄게! 😄

개발하다 보면 이런 상황 한 번쯤 겪어봤을 거야. 🤔
팀원이 짠 코드를 열어봤더니 들여쓰기가 어떤 건 탭, 어떤 건 스페이스... 세미콜론은 있다가 없다가... 변수명은 camelCase인가 snake_case인가 알 수가 없고...

그래서 코드 리뷰 시간의 절반이 "이거 왜 이렇게 썼어요?" 같은 스타일 얘기로 낭비되는 거지. 😅

ESLintPrettier는 바로 이 문제를 해결해주는 최강 콤보야!
코드 품질을 자동으로 체크해주고, 포맷팅까지 자동으로 맞춰주는 도구들이거든.
오늘은 이 두 친구를 완전히 정복해보자! 💪

ESLint 와 Prettier 의 역할 분담 📄 내 코드 var x=1 if(x==1){ console.log('hi') } // 들여쓰기 엉망 // == 사용 위험 // var 사용 금지 // 세미콜론 없음 🔍 ESLint 코드 품질 검사 ✓ var → let/const 권고 ✓ == → === 강제 ✓ 미사용 변수 감지 ✨ Prettier 코드 포맷팅 자동화 ✓ 들여쓰기 자동 정렬 ✓ 세미콜론 자동 추가 ✓ 따옴표 통일 🎉 완성된 코드 const x = 1; if (x === 1) { console.log('hi'); } ✓ 품질 검사 통과 ✓ 포맷 자동 정렬 ✓ 팀 스타일 통일 ✓ 코드 리뷰 집중! 😎 클린 코드 팀 협업 완성! ESLint = 코드 논리/품질 감시자 | Prettier = 코드 스타일 미용사

🔍 ESLint가 뭔데? 왜 필요해?

ESLint는 JavaScript(그리고 TypeScript)의 정적 분석 도구야.
쉽게 말하면, 코드를 실행하기 전에 미리 읽어보고 "야, 이거 문제 있어!" 하고 알려주는 친구지. 🕵️

2013년에 Nicholas C. Zakas가 만들었고, 지금은 JavaScript 생태계에서 사실상 표준 린터로 자리잡았어.
npm 주간 다운로드가 수천만 건에 달할 정도로 엄청나게 많이 쓰이고 있지!

🤔 린터(Linter)가 뭐야?
원래 "lint"는 옷에 붙은 보풀을 뜻해. 코드에서 불필요하거나 위험한 부분을 보풀처럼 잡아내는 도구라서 린터라고 부르는 거야!
코드의 버그 가능성, 안티패턴, 스타일 문제 등을 자동으로 찾아줘.
ESLint가 잡아주는 것들 🎯

ESLint는 크게 두 가지 종류의 문제를 잡아줘:

1️⃣ 코드 품질 문제 (Code Quality)

var 대신 let/const 사용 권고
== 대신 === 사용 강제 (타입 안전성)
• 선언했지만 사용하지 않는 변수 감지
• 도달할 수 없는 코드(unreachable code) 감지
console.log 프로덕션 코드에 남겨두는 것 경고
• 순환 참조, 무한 루프 가능성 경고
2️⃣ 코드 스타일 문제 (Code Style)

• 들여쓰기 규칙 (탭 vs 스페이스, 몇 칸?)
• 세미콜론 사용 여부
• 따옴표 스타일 (single vs double)
• 최대 줄 길이
• 공백 규칙

⚠️ 단, 스타일 관련 규칙은 Prettier와 겹치기 때문에 같이 쓸 때는 조정이 필요해! (뒤에서 자세히 설명할게)
ESLint 설치하기 📦

자, 이제 실제로 설치해보자! Node.js 프로젝트 기준이야.

# npm으로 설치
npm install --save-dev eslint

# yarn으로 설치
yarn add --dev eslint

# pnpm으로 설치
pnpm add --save-dev eslint

설치 후 초기 설정 파일을 만들어야 해. ESLint 9.x 이상부터는 새로운 flat config 방식을 사용해:

# ESLint 설정 초기화 (대화형 방식)
npx eslint --init

# 또는 최신 방식
npm init @eslint/config
💡 Tip! npx eslint --init을 실행하면 몇 가지 질문을 해줘.
"어떻게 ESLint를 사용할 거야?", "어떤 모듈 시스템 써?", "TypeScript 써?", "어떤 프레임워크 써?" 같은 것들이야.
대답하면 자동으로 설정 파일을 만들어줘서 편리해!

⚙️ ESLint 설정 파일 완전 해부

ESLint의 핵심은 설정 파일이야. 버전에 따라 두 가지 방식이 있어:

Legacy 방식: .eslintrc.js, .eslintrc.json, .eslintrc.yml
Flat Config 방식 (ESLint 9+): eslint.config.js, eslint.config.mjs

Legacy 방식 설정 예시 (.eslintrc.js)
module.exports = {
  // 실행 환경 설정
  env: {
    browser: true,    // 브라우저 전역 변수 사용 가능
    es2021: true,     // ES2021 문법 사용 가능
    node: true,       // Node.js 전역 변수 사용 가능
  },

  // 확장할 규칙 세트 (미리 만들어진 규칙 모음)
  extends: [
    'eslint:recommended',           // ESLint 기본 권장 규칙
    'plugin:@typescript-eslint/recommended', // TypeScript 권장 규칙
    'plugin:react/recommended',     // React 권장 규칙
  ],

  // 파서 설정 (TypeScript 사용 시)
  parser: '@typescript-eslint/parser',
  parserOptions: {
    ecmaVersion: 'latest',
    sourceType: 'module',
    ecmaFeatures: {
      jsx: true,  // JSX 문법 허용
    },
  },

  // 플러그인 (추가 규칙 제공)
  plugins: [
    '@typescript-eslint',
    'react',
    'react-hooks',
  ],

  // 개별 규칙 설정
  rules: {
    // 'off' = 0, 'warn' = 1, 'error' = 2
    'no-console': 'warn',           // console.log 경고
    'no-unused-vars': 'error',      // 미사용 변수 에러
    'prefer-const': 'error',        // const 사용 강제
    'eqeqeq': 'error',              // === 사용 강제
    'no-var': 'error',              // var 사용 금지
    'react-hooks/rules-of-hooks': 'error',   // Hook 규칙
    'react-hooks/exhaustive-deps': 'warn',   // 의존성 배열 경고
  },
};
Flat Config 방식 설정 예시 (eslint.config.js)
import js from '@eslint/js';
import globals from 'globals';
import reactHooks from 'eslint-plugin-react-hooks';
import tseslint from 'typescript-eslint';

export default tseslint.config(
  { ignores: ['dist', 'node_modules'] },
  {
    extends: [js.configs.recommended, ...tseslint.configs.recommended],
    files: ['**/*.{ts,tsx}'],
    languageOptions: {
      ecmaVersion: 2020,
      globals: globals.browser,
    },
    plugins: {
      'react-hooks': reactHooks,
    },
    rules: {
      ...reactHooks.configs.recommended.rules,
      'no-console': 'warn',
      'prefer-const': 'error',
      '@typescript-eslint/no-unused-vars': 'error',
    },
  },
);
rules 설정의 3가지 레벨 🚦
레벨 의미 언제 쓰나?
off 0 규칙 비활성화 해당 규칙이 프로젝트에 맞지 않을 때
warn 1 경고 (빌드 실패 안 함) 권장하지만 강제하지 않을 때
error 2 에러 (빌드 실패) 반드시 지켜야 할 규칙
자주 쓰는 ESLint 규칙 모음 📋
rules: {
  // === 변수 관련 ===
  'no-var': 'error',              // var 사용 금지
  'prefer-const': 'error',        // 재할당 없으면 const 사용
  'no-unused-vars': 'error',      // 미사용 변수 금지
  'no-undef': 'error',            // 선언 안 된 변수 사용 금지

  // === 비교 연산자 ===
  'eqeqeq': ['error', 'always'],  // 항상 === 사용
  'no-eq-null': 'error',          // null 비교 시 === 사용

  // === 함수 관련 ===
  'no-empty-function': 'warn',    // 빈 함수 경고
  'arrow-body-style': ['error', 'as-needed'], // 화살표 함수 간결하게

  // === 코드 품질 ===
  'no-console': ['warn', { allow: ['warn', 'error'] }], // console.log 경고
  'no-debugger': 'error',         // debugger 금지
  'no-alert': 'warn',             // alert 경고
  'no-duplicate-imports': 'error', // 중복 import 금지

  // === 비동기 ===
  'no-async-promise-executor': 'error', // async Promise executor 금지
  'no-await-in-loop': 'warn',     // 루프 내 await 경고

  // === 객체/배열 ===
  'prefer-destructuring': 'warn', // 구조분해할당 권장
  'object-shorthand': 'error',    // 객체 단축 표기법 사용
}
💡 eslintignore 파일도 만들어줘!
.eslintignore 파일을 만들어서 검사하지 않을 파일/폴더를 지정할 수 있어.
node_modules/, dist/, build/ 같은 폴더는 검사할 필요 없으니까!
# .eslintignore
node_modules/
dist/
build/
*.min.js
coverage/

Prettier 동작 원리 - AST 변환 과정 ① 원본 코드 function hello( name,age,city){ return "Hello "+ name+" you are "+ age+" from "+city } 😱 읽기 힘들어! 줄이 너무 길고 스타일이 제각각 ② AST 파싱 FunctionDeclaration ├─ id: hello ├─ params: │ ├─ name │ ├─ age │ └─ city └─ body: {...} 코드를 트리 구조로 분해해서 이해해! 스타일 정보 제거 ③ 코드 재생성 function hello( name, age, city ) { return ( `Hello ${name}` ); } 완벽한 포맷! 설정한 규칙대로 100% 자동 정렬 저장하면 바로! Prettier는 코드를 AST(추상 구문 트리)로 파싱한 뒤, 설정에 맞게 새로 출력해 그래서 어떻게 쓰든 결과는 항상 동일해! 이게 Prettier의 핵심 철학이야 🎯

✨ Prettier - 코드 스타일의 독재자(좋은 의미로!)

Prettier는 2017년에 등장한 코드 포맷터야.
ESLint가 "이 코드 문제 있어!"라고 알려주는 친구라면,
Prettier는 "내가 알아서 고쳐줄게!" 하고 직접 코드를 수정해주는 친구야. 🪄

Prettier의 핵심 철학은 "Opinionated"야.
즉, 설정 옵션을 최소화하고 Prettier가 정한 스타일을 따르게 하는 거지.
처음엔 "내 스타일대로 하고 싶은데..." 싶을 수 있지만,
팀 전체가 같은 스타일을 쓰게 되면 코드 리뷰에서 스타일 논쟁이 사라져! 🎉

Prettier 설치하기 📦
# npm으로 설치
npm install --save-dev prettier

# yarn으로 설치
yarn add --dev prettier

# pnpm으로 설치
pnpm add --save-dev prettier
Prettier 설정 파일 (.prettierrc)

설정 파일은 JSON, YAML, JS 형식 모두 지원해. 가장 많이 쓰는 JSON 형식으로 보여줄게:

// .prettierrc
{
  "printWidth": 80,          // 한 줄 최대 길이 (기본값: 80)
  "tabWidth": 2,             // 들여쓰기 공백 수 (기본값: 2)
  "useTabs": false,          // 탭 대신 스페이스 사용 (기본값: false)
  "semi": true,              // 세미콜론 사용 (기본값: true)
  "singleQuote": true,       // 작은따옴표 사용 (기본값: false)
  "quoteProps": "as-needed", // 객체 속성 따옴표 (필요할 때만)
  "jsxSingleQuote": false,   // JSX에서 큰따옴표 사용
  "trailingComma": "es5",    // 후행 쉼표 (es5, all, none)
  "bracketSpacing": true,    // 객체 중괄호 공백 { foo: bar }
  "bracketSameLine": false,  // JSX 닫는 태그 위치
  "arrowParens": "always",   // 화살표 함수 매개변수 괄호 항상
  "endOfLine": "lf"          // 줄 끝 문자 (lf, crlf, cr, auto)
}
주요 옵션 비교 👀
❌ singleQuote: false (기본값)
const name = "홍길동";
const greeting = "안녕하세요";
✅ singleQuote: true
const name = '홍길동';
const greeting = '안녕하세요';
❌ trailingComma: "none"
const obj = {
  name: '홍길동',
  age: 30
};
✅ trailingComma: "es5"
const obj = {
  name: '홍길동',
  age: 30,
};
💡 trailingComma "es5"를 추천하는 이유!
마지막 항목에 쉼표가 있으면 나중에 항목을 추가할 때 git diff가 깔끔해져.
쉼표 없으면 새 항목 추가 시 이전 줄도 수정해야 해서 diff가 지저분해지거든!
prettierignore 파일 설정
# .prettierignore
node_modules/
dist/
build/
*.min.js
*.min.css
package-lock.json
yarn.lock
pnpm-lock.yaml
Prettier 실행하기 🚀
# 특정 파일 포맷팅
npx prettier --write src/index.js

# 특정 폴더 전체 포맷팅
npx prettier --write src/

# 모든 JS/TS 파일 포맷팅
npx prettier --write "**/*.{js,jsx,ts,tsx}"

# 포맷팅 확인만 (수정 안 함, CI에서 유용)
npx prettier --check "**/*.{js,jsx,ts,tsx}"

package.json에 스크립트로 등록해두면 더 편해:

// package.json
{
  "scripts": {
    "format": "prettier --write \"src/**/*.{js,jsx,ts,tsx,css,json}\"",
    "format:check": "prettier --check \"src/**/*.{js,jsx,ts,tsx,css,json}\""
  }
}

🤝 ESLint + Prettier 함께 쓰기 (핵심!)

자, 이제 진짜 중요한 부분이야! 🎯
ESLint와 Prettier를 같이 쓸 때 문제가 생길 수 있어.
왜냐하면 ESLint도 스타일 규칙이 있고, Prettier도 스타일 규칙이 있거든.
이 둘이 충돌하면 ESLint가 "이렇게 해!" 하고, Prettier가 "아니 저렇게 해!" 하면서
서로 싸우는 상황이 벌어져. 😅

⚠️ 충돌 예시

ESLint 규칙: "quotes": ["error", "double"] → 큰따옴표 사용해!
Prettier 설정: "singleQuote": true → 작은따옴표 사용해!

→ Prettier가 작은따옴표로 바꾸면, ESLint가 에러를 내뱉는 무한 루프 발생! 😱
해결책: eslint-config-prettier 🛡️

이 문제를 해결하는 공식 방법이 있어!
eslint-config-prettier를 사용하면 Prettier와 충돌하는 ESLint 규칙들을 자동으로 비활성화해줘.

# 필수 패키지 설치
npm install --save-dev eslint-config-prettier

# 선택: ESLint에서 Prettier를 실행하고 싶다면
npm install --save-dev eslint-plugin-prettier
설정 방법 (Legacy .eslintrc.js)
// .eslintrc.js
module.exports = {
  extends: [
    'eslint:recommended',
    'plugin:@typescript-eslint/recommended',
    'plugin:react/recommended',
    'prettier',  // 반드시 마지막에! Prettier와 충돌하는 규칙 비활성화
  ],
  // prettier 플러그인으로 Prettier 규칙을 ESLint에서 실행 (선택사항)
  plugins: ['prettier'],
  rules: {
    'prettier/prettier': 'error',  // Prettier 규칙 위반 시 ESLint 에러
  },
};
🔑 핵심 포인트!
extends 배열에서 'prettier'는 반드시 마지막에 와야 해!
앞에 있는 설정들의 스타일 관련 규칙을 덮어써야 하니까.
설정 방법 (Flat Config eslint.config.js)
import js from '@eslint/js';
import tseslint from 'typescript-eslint';
import prettierConfig from 'eslint-config-prettier';

export default [
  js.configs.recommended,
  ...tseslint.configs.recommended,
  prettierConfig,  // 마지막에 추가!
  {
    rules: {
      // 여기에 커스텀 규칙 추가
      'no-console': 'warn',
      'prefer-const': 'error',
    },
  },
];
eslint-plugin-prettier를 쓸까 말까? 🤔

eslint-plugin-prettier는 Prettier를 ESLint 플러그인으로 실행해서
Prettier 포맷팅 오류를 ESLint 에러로 표시해주는 도구야.

근데 최근에는 이 방식보다 ESLint와 Prettier를 별도로 실행하는 방식을 더 권장해!

방식 장점 단점
eslint-plugin-prettier 사용 ESLint 한 번만 실행하면 됨 속도 느림, 에러 메시지 복잡
별도 실행 (권장) 빠름, 역할 분리 명확 두 번 실행해야 함
💡 Prettier 공식 문서에서도 권장하는 방식!
ESLint는 코드 품질 검사용으로만 쓰고,
Prettier는 포맷팅 전용으로 별도 실행하는 게 더 깔끔해.
에디터 저장 시 Prettier 자동 실행 + CI에서 별도 체크하는 방식이 베스트야!

개발 워크플로우 - ESLint & Prettier 통합 👨‍💻 개발자 코드 작성 💾 파일 저장 에디터에서 Ctrl+S ✨ Prettier 자동 포맷팅 • 들여쓰기 정렬 • 따옴표 통일 • 세미콜론 추가 • 줄 길이 조정 🔍 ESLint 실시간 품질 검사 • 에러 밑줄 표시 • 경고 표시 • 자동 수정 제안 • 규칙 위반 알림 클린 코드! 🔒 Git Hooks (Husky) - 커밋 전 자동 검사 git commit 개발자가 커밋 시도 pre-commit Prettier 포맷 체크 pre-commit ESLint 품질 검사 통과 ✅ 커밋 성공! 깨끗한 코드 실패 ❌ 커밋 차단! 수정 후 재시도

🖥️ VS Code에서 완벽하게 설정하기

아무리 좋은 도구도 에디터와 연동이 안 되면 불편하잖아?
VS Code에서 ESLint와 Prettier를 완벽하게 연동하는 방법을 알려줄게! 💪

필수 확장 프로그램 설치 🔌
VS Code 확장 프로그램 (Extensions)

🔍 ESLint (dbaeumer.vscode-eslint)
→ ESLint 규칙 위반을 실시간으로 에디터에 표시해줘

Prettier - Code formatter (esbenp.prettier-vscode)
→ 저장 시 자동으로 Prettier 포맷팅 실행

확장 프로그램 탭에서 검색하거나, 터미널에서:
code --install-extension dbaeumer.vscode-eslint
code --install-extension esbenp.prettier-vscode
VS Code 설정 파일 (.vscode/settings.json)

프로젝트 루트에 .vscode/settings.json 파일을 만들어서 팀 전체가 같은 설정을 쓰게 해!

// .vscode/settings.json
{
  // 기본 포맷터를 Prettier로 설정
  "editor.defaultFormatter": "esbenp.prettier-vscode",

  // 저장 시 자동 포맷팅
  "editor.formatOnSave": true,

  // 저장 시 ESLint 자동 수정
  "editor.codeActionsOnSave": {
    "source.fixAll.eslint": "explicit"
  },

  // 언어별 포맷터 설정
  "[javascript]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  },
  "[typescript]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  },
  "[javascriptreact]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  },
  "[typescriptreact]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  },
  "[json]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  },
  "[css]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  },

  // ESLint 설정
  "eslint.validate": [
    "javascript",
    "javascriptreact",
    "typescript",
    "typescriptreact"
  ],

  // 탭 크기 (Prettier 설정과 일치시켜)
  "editor.tabSize": 2,
  "editor.insertSpaces": true
}
💡 팀 프로젝트에서 꿀팁!
.vscode/settings.json을 Git에 커밋해두면 팀원 모두가 같은 에디터 설정을 쓸 수 있어.
"내 컴퓨터에서는 됐는데..." 같은 상황을 방지할 수 있지! 😄

🐶 Husky + lint-staged로 커밋 전 자동 검사

에디터 설정만으로는 부족해! 😤
팀원 중 누군가가 에디터 설정을 안 했거나, 실수로 포맷팅 안 된 코드를 커밋할 수도 있잖아.

Husky는 Git Hooks를 쉽게 관리해주는 도구야.
lint-staged는 Git에 스테이징된 파일에만 린트/포맷팅을 실행해주는 도구고.
이 둘을 조합하면 커밋 전에 자동으로 코드 검사를 할 수 있어! 🔒

설치하기 📦
# Husky와 lint-staged 설치
npm install --save-dev husky lint-staged

# Husky 초기화
npx husky init
Husky 설정하기

npx husky init을 실행하면 .husky/ 폴더가 생기고 pre-commit 파일이 만들어져:

# .husky/pre-commit
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"

npx lint-staged
lint-staged 설정하기

package.json에 lint-staged 설정을 추가해:

// package.json
{
  "lint-staged": {
    "*.{js,jsx,ts,tsx}": [
      "prettier --write",
      "eslint --fix"
    ],
    "*.{css,scss,json,md}": [
      "prettier --write"
    ]
  }
}
✅ 이렇게 하면 어떻게 돼?

1. 개발자가 git commit 실행
2. Husky의 pre-commit hook 발동
3. lint-staged가 스테이징된 파일에만 Prettier + ESLint 실행
4. 문제 없으면 커밋 성공! ✅
5. 문제 있으면 커밋 차단! ❌ (수정 후 다시 커밋)

→ 더러운 코드는 절대 저장소에 들어올 수 없어! 🛡️
💡 lint-staged의 장점!
변경된 파일에만 린트를 실행하기 때문에 속도가 빨라.
프로젝트 전체를 검사하면 느리지만, 변경된 파일만 검사하면 순식간에 끝나거든!

⚛️ TypeScript + React 실전 완전 설정

실제 프로젝트에서 가장 많이 쓰는 TypeScript + React 조합의
완전한 설정을 보여줄게! 이거 하나면 바로 쓸 수 있어. 🎯

필요한 패키지 전체 설치
npm install --save-dev \
  eslint \
  prettier \
  @typescript-eslint/eslint-plugin \
  @typescript-eslint/parser \
  eslint-plugin-react \
  eslint-plugin-react-hooks \
  eslint-plugin-jsx-a11y \
  eslint-plugin-import \
  eslint-config-prettier \
  husky \
  lint-staged
완전한 .eslintrc.js 설정
// .eslintrc.js
module.exports = {
  root: true,
  env: {
    browser: true,
    es2022: true,
    node: true,
  },
  extends: [
    'eslint:recommended',
    'plugin:@typescript-eslint/recommended',
    'plugin:@typescript-eslint/recommended-requiring-type-checking',
    'plugin:react/recommended',
    'plugin:react/jsx-runtime',  // React 17+ (import React 불필요)
    'plugin:react-hooks/recommended',
    'plugin:jsx-a11y/recommended',  // 접근성 규칙
    'plugin:import/recommended',
    'plugin:import/typescript',
    'prettier',  // 반드시 마지막!
  ],
  parser: '@typescript-eslint/parser',
  parserOptions: {
    ecmaVersion: 'latest',
    sourceType: 'module',
    project: './tsconfig.json',  // TypeScript 타입 체크 활성화
    ecmaFeatures: {
      jsx: true,
    },
  },
  plugins: [
    '@typescript-eslint',
    'react',
    'react-hooks',
    'jsx-a11y',
    'import',
  ],
  settings: {
    react: {
      version: 'detect',  // React 버전 자동 감지
    },
    'import/resolver': {
      typescript: true,
      node: true,
    },
  },
  rules: {
    // TypeScript 관련
    '@typescript-eslint/no-unused-vars': ['error', {
      argsIgnorePattern: '^_',  // _로 시작하는 매개변수는 허용
    }],
    '@typescript-eslint/no-explicit-any': 'warn',
    '@typescript-eslint/prefer-const': 'error',
    '@typescript-eslint/no-non-null-assertion': 'warn',

    // 일반 규칙
    'no-console': ['warn', { allow: ['warn', 'error'] }],
    'prefer-const': 'error',
    'no-var': 'error',
    'eqeqeq': ['error', 'always'],
    'no-duplicate-imports': 'error',

    // React 관련
    'react/prop-types': 'off',  // TypeScript 사용 시 불필요
    'react/display-name': 'warn',

    // import 순서 정렬
    'import/order': ['error', {
      'groups': [
        'builtin',
        'external',
        'internal',
        'parent',
        'sibling',
        'index',
      ],
      'newlines-between': 'always',
      'alphabetize': {
        'order': 'asc',
        'caseInsensitive': true,
      },
    }],
  },
  ignorePatterns: [
    'dist/',
    'build/',
    'node_modules/',
    '*.config.js',
    '*.config.ts',
  ],
};
완전한 .prettierrc 설정
// .prettierrc
{
  "printWidth": 100,
  "tabWidth": 2,
  "useTabs": false,
  "semi": true,
  "singleQuote": true,
  "quoteProps": "as-needed",
  "jsxSingleQuote": false,
  "trailingComma": "es5",
  "bracketSpacing": true,
  "bracketSameLine": false,
  "arrowParens": "always",
  "endOfLine": "lf",
  "overrides": [
    {
      "files": "*.json",
      "options": {
        "printWidth": 200
      }
    },
    {
      "files": "*.md",
      "options": {
        "proseWrap": "always"
      }
    }
  ]
}
완전한 package.json 스크립트
// package.json
{
  "scripts": {
    "lint": "eslint src --ext .ts,.tsx,.js,.jsx",
    "lint:fix": "eslint src --ext .ts,.tsx,.js,.jsx --fix",
    "format": "prettier --write \"src/**/*.{ts,tsx,js,jsx,css,json}\"",
    "format:check": "prettier --check \"src/**/*.{ts,tsx,js,jsx,css,json}\"",
    "type-check": "tsc --noEmit",
    "validate": "npm run type-check && npm run lint && npm run format:check"
  },
  "lint-staged": {
    "*.{ts,tsx,js,jsx}": [
      "prettier --write",
      "eslint --fix"
    ],
    "*.{css,json,md}": [
      "prettier --write"
    ]
  }
}

🔄 CI/CD에서 ESLint & Prettier 자동화

로컬에서만 검사하면 부족해! 🙅
GitHub Actions 같은 CI/CD 파이프라인에서도 자동으로 검사하면
어떤 환경에서도 코드 품질을 보장할 수 있어.

GitHub Actions 설정 예시
# .github/workflows/code-quality.yml
name: 코드 품질 검사

on:
  push:
    branches: [main, develop]
  pull_request:
    branches: [main, develop]

jobs:
  quality-check:
    runs-on: ubuntu-latest

    steps:
      - name: 코드 체크아웃
        uses: actions/checkout@v4

      - name: Node.js 설정
        uses: actions/setup-node@v4
        with:
          node-version: '20'
          cache: 'npm'

      - name: 의존성 설치
        run: npm ci

      - name: TypeScript 타입 체크
        run: npm run type-check

      - name: ESLint 검사
        run: npm run lint

      - name: Prettier 포맷 체크
        run: npm run format:check
🎯 CI에서는 --fix 옵션 쓰지 마!
CI 환경에서는 코드를 자동으로 수정하는 게 아니라 검사만 해야 해.
eslint --fix 대신 eslint만 실행하고,
prettier --write 대신 prettier --check를 사용해!
문제가 있으면 빌드를 실패시켜서 개발자가 직접 수정하게 해야 해.

🚨 자주 발생하는 문제와 해결책
문제 1: ESLint와 Prettier가 계속 충돌해요 😤
증상: Prettier로 저장하면 ESLint 에러가 생기고, ESLint로 고치면 Prettier가 다시 바꾸는 무한 루프
해결:
1. eslint-config-prettier가 설치되어 있는지 확인
2. extends 배열에서 'prettier'가 마지막인지 확인
3. npx eslint-config-prettier-check로 충돌 규칙 확인
# 충돌하는 규칙 확인하기
npx eslint-config-prettier src/index.ts
문제 2: 특정 파일이나 줄에서 ESLint 규칙 무시하고 싶어요
// 다음 줄 전체 무시
// eslint-disable-next-line no-console
console.log('디버깅용');

// 특정 규칙만 무시
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const data: any = fetchData();

// 파일 전체에서 특정 규칙 무시 (파일 맨 위에)
/* eslint-disable no-console */

// 블록 단위로 무시
/* eslint-disable no-unused-vars */
const unusedVar = 'test';
/* eslint-enable no-unused-vars */
💡 eslint-disable은 정말 필요할 때만 써! 남용하면 ESLint를 쓰는 의미가 없어져.
꼭 주석으로 왜 비활성화했는지 이유를 남겨두는 게 좋아.
문제 3: Prettier가 내 코드를 이상하게 바꿔요
// 특정 부분 Prettier 포맷팅 비활성화
// prettier-ignore
const matrix = [
  1, 0, 0,
  0, 1, 0,
  0, 0, 1,
];

// JSX에서
{/* prettier-ignore */}
<div className="very-long-class-name-that-should-not-be-wrapped">
  내용
</div>
문제 4: Windows에서 줄 끝 문자(CRLF) 문제
⚠️ Windows 개발자 주의!
Windows는 기본적으로 CRLF(\r\n)를 사용하는데, Linux/Mac은 LF(\n)를 써.
팀에 Windows 사용자가 있으면 이 설정을 꼭 해줘!
# .gitattributes 파일 생성
* text=auto eol=lf
*.{cmd,[cC][mM][dD]} text eol=crlf
*.{bat,[bB][aA][tT]} text eol=crlf
// .prettierrc에서 줄 끝 문자 통일
{
  "endOfLine": "lf"
}

🔌 알아두면 유용한 ESLint 플러그인들

ESLint의 진짜 강점은 플러그인 생태계야!
프레임워크나 라이브러리에 맞는 플러그인을 추가하면 더 강력해져. 💪

플러그인 용도 설치 명령어
eslint-plugin-react React 관련 규칙 npm i -D eslint-plugin-react
eslint-plugin-react-hooks React Hooks 규칙 npm i -D eslint-plugin-react-hooks
@typescript-eslint TypeScript 규칙 npm i -D @typescript-eslint/eslint-plugin
eslint-plugin-import import/export 규칙 npm i -D eslint-plugin-import
eslint-plugin-jsx-a11y 접근성(a11y) 규칙 npm i -D eslint-plugin-jsx-a11y
eslint-plugin-jest Jest 테스트 규칙 npm i -D eslint-plugin-jest
eslint-plugin-security 보안 취약점 감지 npm i -D eslint-plugin-security
eslint-plugin-unicorn 고급 모범 사례 npm i -D eslint-plugin-unicorn
Next.js 프로젝트라면?
# Next.js는 자체 ESLint 설정 제공
npm install --save-dev eslint-config-next

// .eslintrc.js
module.exports = {
  extends: [
    'next/core-web-vitals',  // Next.js 권장 설정 (Core Web Vitals 포함)
    'prettier',
  ],
};
Vue.js 프로젝트라면?
npm install --save-dev eslint-plugin-vue

// .eslintrc.js
module.exports = {
  extends: [
    'plugin:vue/vue3-recommended',  // Vue 3 권장 설정
    'prettier',
  ],
  parser: 'vue-eslint-parser',
  parserOptions: {
    parser: '@typescript-eslint/parser',
  },
};

👥 기존 프로젝트에 도입하는 전략

"우리 프로젝트는 이미 코드가 수천 줄인데 지금 ESLint 도입하면 에러가 수백 개 나올 것 같아요..." 😱

걱정 마! 단계적으로 도입하는 방법이 있어. 재능넷 같은 플랫폼에서 개발 관련 멘토링을 받아보면
이런 실전 경험을 가진 개발자들의 조언을 구할 수도 있어. 😊

1
먼저 warn으로 시작하기
처음에는 모든 규칙을 error 대신 warn으로 설정해.
빌드가 실패하지 않으면서 문제를 파악할 수 있어.
2
자동 수정 가능한 것부터 처리
npx eslint --fix src/로 자동 수정 가능한 문제들을 한 번에 처리해.
많은 문제가 자동으로 해결돼!
3
파일 단위로 점진적 적용
.eslintignore에 기존 파일들을 추가하고,
새로 만드는 파일부터 규칙을 적용해. 기존 파일은 하나씩 수정해나가.
4
규칙을 점진적으로 강화
warn으로 시작했다가 팀이 익숙해지면 error로 올려.
한 번에 다 바꾸려 하면 팀원들이 힘들어해!
5
팀 합의 먼저!
규칙을 정할 때 팀원들과 충분히 논의해.
"왜 이 규칙이 필요한가"를 설명하고 동의를 얻어야 잘 지켜져.
⚡ 빠른 도입 팁!
eslint --fix를 실행하면 자동으로 수정 가능한 문제의 약 70-80%가 해결돼.
나머지는 수동으로 수정해야 하지만, 처음 생각보다 훨씬 적어!

✅ ESLint + Prettier 설정 완료 체크리스트 📦 패키지 설치 ☑ eslint 설치 ☑ prettier 설치 ☑ eslint-config-prettier 설치 ☑ @typescript-eslint 설치 (TS 사용 시) ☑ eslint-plugin-react 설치 (React 사용 시) ☑ husky 설치 ☑ lint-staged 설치 ⚙️ 설정 파일 ☑ .eslintrc.js 또는 eslint.config.js 생성 ☑ .prettierrc 생성 ☑ .eslintignore 생성 ☑ .prettierignore 생성 ☑ .gitattributes 생성 (줄 끝 문자) ☑ extends 마지막에 'prettier' 추가 확인 🔧 에디터 & 자동화 ☑ VS Code ESLint 확장 설치 ☑ VS Code Prettier 확장 설치 ☑ .vscode/settings.json 생성 ☑ formatOnSave: true 설정 ☑ defaultFormatter: prettier 설정 ☑ codeActionsOnSave ESLint 설정 ☑ Husky pre-commit hook 설정 🚀 CI/CD & 스크립트 ☑ package.json lint 스크립트 추가 ☑ package.json format 스크립트 추가 ☑ lint-staged 설정 추가 ☑ GitHub Actions 워크플로우 생성 ☑ CI에서 --check 옵션 사용 확인 ☑ 팀원 전체 설정 공유 완료 🎉 모두 체크했다면 완벽한 코드 품질 관리 시스템 완성!

🎯 마무리 - 핵심 정리

자, 오늘 엄청 많은 내용을 다뤘는데 핵심만 정리해볼게! 🎉

📌 ESLint vs Prettier 역할 구분

🔍 ESLint = 코드 품질 감시자
→ 버그 가능성, 안티패턴, 논리적 오류를 잡아줘
var 사용, == 사용, 미사용 변수 등

Prettier = 코드 스타일 미용사
→ 들여쓰기, 따옴표, 세미콜론, 줄 길이 등 포맷팅 자동화
→ 설정한 스타일로 코드를 자동으로 재작성해줘
🔑 함께 쓸 때 핵심 규칙

1. eslint-config-prettier로 충돌 방지
2. extends에서 'prettier'는 반드시 마지막!
3. 에디터 저장 시 자동 포맷팅 설정
4. Husky + lint-staged로 커밋 전 자동 검사
5. CI/CD에서 --check 옵션으로 검증

처음에는 설정이 복잡해 보여도, 한 번 제대로 세팅해두면
코드 품질 걱정 없이 개발에만 집중할 수 있어! 💪

팀 프로젝트에서 코드 스타일 논쟁으로 시간 낭비하는 일도 없어지고,
코드 리뷰에서 진짜 중요한 로직 얘기에만 집중할 수 있게 돼.

만약 이런 개발 환경 설정이 어렵다면, 재능넷에서 개발 환경 설정 전문가를 찾아서
도움을 받는 것도 좋은 방법이야! 다양한 개발 재능을 가진 분들이 많이 계시거든. 😊

자, 이제 깨끗하고 일관된 코드로 멋진 프로젝트를 만들어봐! 🚀

🔍 ESLint ✨ Prettier 🐶 Husky 📦 lint-staged ⚛️ TypeScript 🔄 CI/CD 💾 VS Code 🛡️ 코드 품질
댓글 작성

이 글에 대한 여러분의 생각을 들려주세요

댓글 0