본문으로 건너뛰기
기술스택 · stack/javascript/ESLint와 Prettier로 코드 스타일 자동화

JavaScript · 3장 코드 품질과 도구

ESLint와 Prettier로 코드 스타일 자동화

들여쓰기는 몇 칸으로 할지, 따옴표는 무엇을 쓸지 같은 논쟁은 끝이 없어요. 실무에서는 이걸 사람이 아니라 도구에게 맡겨요. 코드 모양을 맞추는 Prettier와 실수를 찾아 주는 ESLint를 함께 쓰는 법을 정리했어요.

#3.3 · ESLint 10 · Prettier 3 기준

01. 모양은 Prettier, 실수는 ESLint

두 도구는 하는 일이 달라요. Prettier(포매터)는 코드가 어떻게 보이는지만 바꿔요. 줄 바꿈, 들여쓰기, 따옴표, 세미콜론을 정해진 규칙대로 다시 써 줘요. ESLint(린터)는 코드가 무엇을 하는지를 읽고, 버그일 가능성이 높은 곳을 찾아 알려 줘요.

①들쭉날쭉한 코드가 Prettier를 지나면 모양만 가지런해지고, ESLint를 지나면 쓰지 않는 변수와 중복된 키처럼 실수일 가능성이 높은 줄에 경고가 붙어요.

ESLint가 잡아 주는 실수는 실행해도 오류가 나지 않아서 놓치기 쉬운 것들이에요. 예를 들어 객체에 같은 키를 두 번 쓰면, 자바스크립트는 조용히 뒤의 값으로 덮어써요.

const config = {
  retries: 3,
  timeoutMs: 5000,
  retries: 0,          // 위의 값을 덮어써요 — ESLint: no-dupe-keys
};

console.log(config.retries); // 0

02. Prettier: 모양을 맞춰요

프로젝트에 Prettier를 설치하고, 빈 설정 파일 .prettierrc를 만든 뒤 실행해요. 버전을 정확히 고정(--save-exact)하는 건 Prettier가 버전에 따라 결과 모양을 조금씩 바꾸기 때문이에요. 팀원 모두가 같은 결과를 얻게 하려는 거예요.

npm install --save-dev --save-exact prettier
npx prettier . --write      # 프로젝트 전체를 정리해서 저장
npx prettier . --check      # 정리가 필요한 파일이 있는지 확인만

Prettier는 일부러 옵션이 적어요. 고를 게 적어야 논쟁도 적으니까요. 바꾸고 싶은 것만 .prettierrc에 적어요.

{
  "singleQuote": true,
  "printWidth": 100
}
// 정리 전
const user={name:"하늘",tags:[ 'new','vip' ],}
function greet( name ){return "안녕, "+name}

// npx prettier --write 뒤 (singleQuote 설정)
const user = { name: '하늘', tags: ['new', 'vip'] };
function greet(name) {
  return '안녕, ' + name;
}

03. ESLint: 실수를 찾아요

ESLint는 질문에 답하며 설정을 만들어 주는 명령으로 시작하는 게 가장 쉬워요. 이 명령은 package.json이 있는 폴더에서 실행해요.

npm init @eslint/config@latest
npx eslint .                # 프로젝트 전체 검사
npx eslint . --fix          # 자동으로 고칠 수 있는 건 고치기

설정은 eslint.config.js(또는 .mjs) 파일 하나에 자바스크립트로 적어요. ESLint 10부터는 이 형식만 써요(예전의 .eslintrc 파일은 더 이상 읽지 않아요). 아래는 추천 규칙 묶음에 이 노트에서 다룬 규칙 몇 개를 더한 예예요.

// eslint.config.js
import { defineConfig } from 'eslint/config';
import js from '@eslint/js';
import globals from 'globals';

export default defineConfig([
  {
    files: ['**/*.js'],
    plugins: { js },
    extends: ['js/recommended'],          // 추천 규칙 묶음
    languageOptions: { globals: globals.browser },
  },
  {
    rules: {
      eqeqeq: 'error',                    // == 대신 === (2장)
      'prefer-const': 'warn',             // 다시 넣지 않으면 const (2장)
      'no-var': 'error',
    },
  },
]);

이 설정 파일은 import를 쓰는 모듈이에요. 그래서 package.json에 "type": "module"이 있어야 해요. npm init -y로 만든 프로젝트는 "type": "commonjs"로 되어 있어서, 그대로 실행하면 SyntaxError: Cannot use import statement outside a module가 나요. 이럴 땐 "type"을 "module"로 바꾸거나(package.json), 파일 이름을 eslint.config.mjs로 해요. .mjs 파일은 type과 상관없이 언제나 모듈로 읽혀요.

규칙마다 'off' · 'warn' · 'error' 중 하나를 정해요. 'error'가 하나라도 있으면 ESLint가 실패로 끝나서, 자동 검사(CI)에서 합치기 전에 막을 수 있어요. 추천 묶음(js/recommended)에는 쓰지 않는 변수(no-unused-vars), 없는 이름(no-undef), 중복 키(no-dupe-keys), 남겨 둔 debugger(no-debugger) 같은 규칙이 들어 있어요.

04. 둘을 함께, 저장할 때 자동으로

ESLint에도 모양에 관한 규칙이 있어서 Prettier와 부딪힐 수 있어요. eslint-config-prettier를 설치해 설정 배열의 맨 뒤에 넣으면, Prettier와 겹치는 ESLint 규칙을 꺼 줘요. 그러면 "모양은 Prettier, 실수는 ESLint"로 깔끔하게 나뉘어요.

// npm install -D eslint-config-prettier
import eslintConfigPrettier from 'eslint-config-prettier/flat';

export default defineConfig([
  /* … 위의 설정들 … */
  eslintConfigPrettier,                   // 맨 뒤에
]);

명령은 package.json의 scripts에 이름을 붙여 두고(npm run), 편집기에는 ESLint · Prettier 확장을 설치해 저장할 때 자동으로 정리되게 해요(VS Code는 editor.formatOnSave, 코드 편집기). 커밋하기 직전에 바뀐 파일만 검사하는 도구(예: lint-staged)를 붙이는 팀도 많아요.

05. 실전 포인트

  • 언제 쓰나요? 새 프로젝트를 시작하는 날 바로 설정해요. 나중에 넣으면 기존 코드 전체가 한꺼번에 바뀌어서, 그 커밋 때문에 변경 기록을 읽기 어려워져요.
  • 대신 쓰는 것: 스타일 규칙을 문서로 적어 두고 코드 리뷰에서 지적하는 방식은 쓰지 않아요. 사람은 리뷰에서 설계와 동작에 집중하고, 모양은 도구가 맞춰요. ESLint와 Prettier를 하나로 합친 새 도구(예: Biome)를 쓰는 팀도 있어요.
  • 흔한 실수: "type": "commonjs" 프로젝트에서 import를 쓰는 eslint.config.js를 만들어 ESLint가 아예 실행되지 않는 것(.mjs로 바꾸거나 type을 module로), 경고가 너무 많다고 규칙을 하나씩 끄다 보니 정작 중요한 것까지 꺼 버리는 것, 사람마다 편집기 설정이 달라 저장할 때마다 서로 다른 모양으로 바뀌는 것(설정 파일을 저장소에 올려서 막아요)이에요.

아래 코드는 실행하면 3000이 나와서 멀쩡해 보여요. 하지만 ESLint 추천 규칙에 걸리는 곳이 두 군데 있어요. 어디이고, 왜 문제인지 찾아보세요.

function shippingFee(amount) {
  const freeLine = 50000;
  const discount = 0.1;
  if (amount >= freeLine) {
    return 0;
  }
  return 3000;
  console.log('배송비 계산 끝');
}

console.log(shippingFee(42000));
해답 보기
  • const discount = 0.1; — 만들고 쓰지 않았어요(no-unused-vars). 할인을 빼먹은 건 아닌지 확인하라는 신호예요.
  • console.log('배송비 계산 끝'); — return 뒤라서 절대 실행되지 않아요(no-unreachable).
  • 둘 다 실행 결과에는 드러나지 않아서 눈으로 찾기 어려운 실수예요. 편집기에 ESLint 확장을 켜 두면 코드를 쓰는 순간 밑줄로 알려 줘요.

정리

  • Prettier는 코드 모양을, ESLint는 버그가 될 만한 코드를 맡아요.
  • Prettier는 npx prettier . --write, ESLint는 npx eslint .로 실행해요. ESLint 10은 eslint.config.js · .mjs 같은 설정 파일만 읽고, import를 쓰려면 모듈이어야 해요("type": "module" 또는 .mjs).
  • eslint-config-prettier를 맨 뒤에 넣어 두 도구가 부딪히지 않게 해요.
  • 프로젝트 첫날 설정하고, 편집기에서 저장할 때 자동으로 돌게 해요.
SIMPLE · 기술스택 / JavaScript — 3장 코드 품질과 도구