ESLint + Prettier에서 Biome으로 옮긴 이유

ESLint + Prettier에서 Biome으로 옮긴 이유

2026년 2월 11일

프로젝트를 시작할 때마다 린트 설정을 마주치는데,
어떤 파일이 무엇을 하는지 이해하지 못한 채 복붙만 해왔습니다.

ESLint + Prettier 조합에서 Biome으로 넘어가면서, 왜 이런 도구가 필요한지부터 다시 정리하게 됐어요.
그 과정에서 기록한 내용을 공유해 봅니다.

0. 그래서 린트는 왜 필요한가

코드는 실행만 되면 끝이 아니다.

혼자 작업해도, 2주 후의 나는 “이걸 왜 이렇게 썼지?”를 반복하게 된다.
팀이라면 더하다. A는 작은따옴표, B는 큰따옴표, C는 세미콜론을 빠뜨린다.
PR마다 코드 스타일 얘기가 나오게 된다.

린트는 이런 문제를 코드 리뷰 전에 자동으로 잡아준다.
크게 두 역할로 나뉜다.

  • Linter: 코드의 잠재적 오류안티패턴을 검출한다. console.log 남기기, 선언하지 않은 변수, 사용하지 않는 import 등.
  • Formatter: 코드의 스타일을 강제로 통일한다. 들여쓰기, 따옴표, 세미콜론, 줄 길이 등.

이 둘은 역할이 다르기 때문에, 전통적으로 ESLint(Linter) + Prettier(Formatter)를 함께 써왔다.

1. 문제 상황

ESLint + Prettier 조합을 쓰면 만들어야 하는 파일 목록이다.

.eslintrc.json       ← ESLint 규칙
.prettierrc          ← Prettier 포맷 규칙
.eslintignore        ← ESLint 제외 파일
.prettierignore      ← Prettier 제외 파일
.vscode/settings.json
.vscode/extensions.json

그리고 package.json에도 의존성이 쌓인다.

{
  "devDependencies": {
    "eslint": "^8.0.0",
    "prettier": "^3.0.0",
    "eslint-config-prettier": "^9.0.0",
    "eslint-plugin-prettier": "^5.0.0"
  }
}

eslint-config-prettier가 낯선 패키지일 수 있다.
ESLint와 Prettier가 같은 규칙을 두고 서로 다르게 판단하는 경우가 있다.
예를 들어 Prettier가 세미콜론을 없애도록 포맷하면, ESLint는 “세미콜론 없음”을 오류로 잡는다.
이 충돌을 막으려고 eslint-config-prettier가 필요하다. 해결하려고 패키지를 하나 더 까는 셈이다.

2. 내가 처음 한 생각

처음엔 이 구조가 당연한 줄 알았다.

“다들 이렇게 쓰니까, 이게 맞는 거겠지.”

그런데 새 프로젝트를 시작할 때마다 같은 문제를 반복했다.

  • ESLint와 Prettier 규칙이 충돌해서 저장할 때마다 오류가 깜빡인다
  • 팀원 컴퓨터에서 자동 포맷이 안 된다
  • eslint --fix를 해도 Prettier 포맷이 그대로다

파일이 많으니 어디를 고쳐야 하는지 추적하기도 어려웠다.
문제가 ESLint 설정인지, Prettier 설정인지, 아니면 VSCode 설정인지부터 헷갈렸다.

3. 각 설정 파일의 역할

.eslintrc.json / eslint.config.js

ESLint의 규칙을 정의하는 파일이다.
어떤 코드 패턴을 오류/경고로 볼지, 어떤 플러그인을 쓸지 설정한다.

{
  "extends": ["eslint:recommended", "plugin:react/recommended"],
  "rules": {
    "no-unused-vars": "warn",
    "no-console": "error"
  }
}

ESLint v9부터는 eslint.config.js (flat config) 형식이 기본이 됐다.
파일명과 형식이 달라졌을 뿐 역할은 같다.

.prettierrc / prettier.config.js

Prettier의 포맷 규칙을 정의하는 파일이다. 코드 스타일에 관한 것만 다룬다.

{
  "semi": false,
  "singleQuote": true,
  "tabWidth": 2,
  "printWidth": 80
}

Prettier는 의도적으로 옵션이 적다.
”스타일 논쟁을 끝내기” 위해 만들어진 도구라 선택지 자체를 줄여뒀다.

4. 실제로 해 본 선택: Biome으로 이동

설정 구조를 이해하고 나서, 더 단순한 방법이 있다는 걸 알게 됐다.

Biome은 Rust로 만들어진 툴로, Linter와 Formatter를 하나로 합쳐놓았다.

설치도 패키지 하나다.

npm install --save-dev --save-exact @biomejs/biome
npx biome init

설정 파일도 하나다.

// biome.json
{
  "$schema": "https://biomejs.dev/schemas/1.9.4/schema.json",
  "organizeImports": { "enabled": true },
  "linter": {
    "enabled": true,
    "rules": { "recommended": true }
  },
  "formatter": {
    "enabled": true,
    "indentStyle": "space",
    "indentWidth": 2,
    "lineWidth": 80
  },
  "javascript": {
    "formatter": {
      "quoteStyle": "single",
      "semicolons": "asNeeded"
    }
  }
}

biome.json 하나가 .eslintrc.json.prettierrc를 모두 대체한다.
같은 도구가 Linter와 Formatter를 둘 다 처리하니 규칙 충돌 자체가 없다.

5. 결과: 무엇이 달라졌나

ESLint + PrettierBiome
관리 파일.eslintrc, .prettierrc, ignore 파일 2개biome.json 하나
패키지 수eslint, prettier, 충돌 방지 패키지, 플러그인들@biomejs/biome 하나
규칙 충돌eslint-config-prettier로 별도 해결 필요충돌 없음
속도보통Rust 기반으로 체감될 만큼 빠름

단점도 있다. ESLint 생태계는 방대하다.
eslint-plugin-react-hooks처럼 프레임워크 특화 규칙 중 Biome에 아직 없는 것들이 있다.
이런 규칙이 반드시 필요한 프로젝트라면 ESLint를 유지하거나 병행해야 한다.

6. 지금 다시 한다면

새 프로젝트를 시작할 때 이 기준으로 선택한다.

  • 사이드 프로젝트 / 빠른 프로토타이핑 → Biome
  • 팀 프로젝트, 특수한 ESLint 플러그인 불필요 → Biome
  • 프레임워크 특화 규칙(react-hooks, @typescript-eslint 등)이 필수 → ESLint + Prettier 유지

설정 파일 자체보다 “이 파일이 어느 레이어를 담당하는가”를 먼저 이해하는 게 중요했다.
그걸 알고 나면, 에러가 생겼을 때 어디를 봐야 하는지가 보이는 거 같다.

비고