
Biome: ESLint + Prettier를 하나로 합친 도구
ESLint와 Prettier 설정 충돌로 삽질한 경험, 누구나 있을 것이다. Biome는 이 둘을 하나로 합치고 속도까지 잡았다.

ESLint와 Prettier 설정 충돌로 삽질한 경험, 누구나 있을 것이다. Biome는 이 둘을 하나로 합치고 속도까지 잡았다.
AI에게 '로그인 만들어줘'라고 했더니 엉망인 코드가 나왔다. 프롬프트를 구조화하니 결과물이 완전히 달라졌다.

맥을 새로 사면 개발 환경 세팅에 이틀이 걸렸다. dotfiles과 자동화 스크립트를 만들고 나니 30분이면 끝난다.

HTML5 Drag and Drop API로 만든 칸반 보드가 네이버 웨일에서만 동작하지 않았다. 브라우저 제스처가 네이티브 드래그 이벤트를 가로채는 문제, dnd-kit의 Pointer Events 기반 아키텍처로 해결했다.

오픈소스에 기여하려고 봤는데 README가 없어서 포기한 적이 있다. 그때 좋은 문서의 가치를 뼈저리게 느꼈다.

프로젝트를 새로 시작할 때마다 겪는 의식이 있다. npm install eslint prettier eslint-config-prettier eslint-plugin-prettier를 입력하고, .eslintrc.json과 .prettierrc를 만들고, 두 도구가 서로 싸우지 않도록 설정을 조율하는 과정.
처음엔 "이게 표준이니까"라고 받아들였다. 하지만 프로젝트가 쌓일수록 이 조합이 불편했다. ESLint는 코드 품질을, Prettier는 포매팅을 담당한다는 건 알겠는데, 왜 두 도구가 같은 코드를 두 번 읽어야 할까? 왜 설정 파일이 두 개나 필요할까? 그리고 왜 이렇게 느릴까?
Biome를 처음 봤을 때 든 생각: "드디어 누군가 이걸 해결했구나."
Biome의 핵심 통찰은 단순했다. 린팅과 포매팅은 별개의 작업이 아니라 같은 코드 분석 파이프라인의 다른 단계일 뿐이다.
ESLint와 Prettier를 따로 쓰는 건 마치 집을 청소하는데 먼지 털기 담당과 쓰레기 줍기 담당을 따로 고용하는 것과 같다. 둘 다 같은 방을 두 번 돌아야 하고, 누가 먼저 할지 순서를 정해야 하고, 서로 충돌하지 않도록 규칙을 조율해야 한다.
Biome는 이걸 하나로 합쳤다. 코드를 한 번 파싱하고, AST(Abstract Syntax Tree)를 한 번 만들고, 거기서 린팅과 포매팅을 동시에 처리한다. 게다가 Rust로 작성돼서 기존 도구보다 100배 빠르다는 벤치마크 결과가 있다.
처음엔 "또 하나의 대안 도구겠지"라고 생각했다. 하지만 실제로 써보니 달랐다. 설정 파일 하나로 끝나고, 속도가 체감될 정도로 빠르고, VS Code 익스텐션도 훌륭했다. 이건 단순한 대안이 아니라 패러다임 시프트였다.
ESLint + Prettier 조합에서는 최소 두 개의 설정 파일이 필요했다. 거기에 TypeScript를 쓰면 tsconfig.json도 추가되고, 충돌 방지를 위해 eslint-config-prettier도 설치해야 했다.
Biome는 하나의 설정 파일로 모든 걸 관리한다.
{
"$schema": "https://biomejs.dev/schemas/1.9.4/schema.json",
"organizeImports": {
"enabled": true
},
"linter": {
"enabled": true,
"rules": {
"recommended": true,
"suspicious": {
"noExplicitAny": "error"
},
"style": {
"useConst": "warn",
"noUnusedVariables": "error"
}
}
},
"formatter": {
"enabled": true,
"indentStyle": "space",
"indentWidth": 2,
"lineWidth": 100
},
"javascript": {
"formatter": {
"quoteStyle": "single",
"trailingCommas": "all"
}
}
}
이 하나의 파일에서 린팅 규칙, 포매팅 스타일, import 정리까지 모두 설정된다. 충돌할 일이 없다. 왜냐하면 애초에 하나의 도구니까.
Node.js 기반 도구들은 태생적으로 느리다. JavaScript는 인터프리터 언어고, 파일 I/O가 많을수록 오버헤드가 커진다. 큰 프로젝트에서 ESLint를 돌리면 몇 초씩 걸리는 이유다.
Biome는 Rust로 작성됐다. 컴파일된 네이티브 바이너리라 시작 시간이 거의 없고, 병렬 처리가 기본이다. 공식 벤치마크에서는 ESLint보다 100배 빠르다고 하는데, 실제 프로젝트에서는 10~50배 정도 차이를 체감했다.
# ESLint + Prettier (기존)
$ time npm run lint
real 0m8.342s
# Biome (전환 후)
$ time biome check .
real 0m0.234s
이 속도 차이는 단순히 "빠르네"로 끝나지 않는다. 개발 경험이 바뀐다. 저장할 때마다 즉시 피드백이 오고, CI에서 린팅 단계가 병목이 되지 않는다.
ESLint와 Prettier를 함께 쓸 때는 항상 순서를 고민해야 했다. "Prettier가 먼저? ESLint가 먼저?" Git hook에서는 어떤 순서로? CI에서는?
Biome는 이런 고민이 없다. 하나의 명령어로 끝난다.
# 린트 + 포맷 체크
biome check .
# 자동 수정
biome check --write .
# CI 모드 (에러 시 exit code 1)
biome ci .
VS Code 익스텐션을 설치하면 저장 시 자동 포맷도 바로 된다. 별도 설정 없이.
// .vscode/settings.json
{
"editor.defaultFormatter": "biomejs.biome",
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"quickfix.biome": "explicit",
"source.organizeImports.biome": "explicit"
}
}
기존 프로젝트를 Biome로 옮기는 게 생각보다 쉬웠다. Biome가 마이그레이션 도구를 제공하기 때문이다.
# ESLint 설정을 Biome로 변환
biome migrate eslint --write
# Prettier 설정을 Biome로 변환
biome migrate prettier --write
이 명령어는 기존 .eslintrc.json과 .prettierrc를 읽어서 biome.json으로 자동 변환한다. 물론 100% 완벽하진 않지만, 대부분의 규칙은 호환된다.
실제로 내 프로젝트에서 마이그레이션했을 때:
biome migrate eslint --write 실행biome.json 확인 및 미세 조정.eslintrc.json, .prettierrc, eslint-config-prettier 삭제package.json에서 관련 devDependencies 제거전체 과정이 10분도 안 걸렸다.
CI 파이프라인에 Biome를 넣는 것도 간단하다. Node.js 도구가 아니라 독립 실행 파일이라 설치도 빠르다.
name: CI
on: [push, pull_request]
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Biome
uses: biomejs/setup-biome@v2
with:
version: latest
- name: Run Biome
run: biome ci .
기존 ESLint + Prettier 조합보다 훨씬 빠르게 돌아간다. 큰 프로젝트에서는 CI 시간이 절반 이하로 줄었다.
현재 JavaScript/TypeScript 생태계의 린팅/포매팅 옵션을 비교하면:
| 도구 | 속도 | 린팅 | 포매팅 | 설정 복잡도 | 생태계 성숙도 |
|---|---|---|---|---|---|
| ESLint + Prettier | 느림 | 최고 | 최고 | 복잡 (2개 도구) | 매우 높음 |
| Biome | 매우 빠름 | 좋음 | 좋음 | 단순 (1개 도구) | 중간 (성장 중) |
| oxlint | 매우 빠름 | 기본 | 없음 | 단순 | 낮음 (초기) |
ESLint는 여전히 가장 많은 규칙과 플러그인을 제공한다. 하지만 대부분의 프로젝트는 그렇게 많은 규칙이 필요하지 않다. Biome의 recommended 규칙 세트만으로도 90% 이상의 일반적인 문제를 잡아낸다.
oxlint는 Rust 기반 린터지만 포매팅 기능이 없다. 여전히 Prettier와 함께 써야 하므로 Biome의 "통합" 장점이 없다.
결국 나에게 와닿은 건: 대부분의 프로젝트에서 Biome의 트레이드오프가 합리적이다. 100% ESLint 규칙 호환이 필요한 게 아니라면, 속도와 단순함을 택하는 게 낫다.
완벽하진 않다. 알아둬야 할 한계들:
아직 지원 안 되는 것들:eslint-plugin-security)하지만 Biome 팀은 빠르게 움직이고 있다. 2024년에만 Vue 지원 로드맵이 추가됐고, 규칙 세트도 꾸준히 확장되고 있다. Rome 프로젝트를 포크한 후 커뮤니티 주도로 운영되면서 오히려 더 활발해졌다.
Biome를 쓰기 시작한 후 달라진 것들:
npm install --save-dev @biomejs/biome, biome init, 끝..eslintrc, .prettierrc, eslint-config-prettier 전부 삭제.물론 ESLint + Prettier가 여전히 강력한 조합인 건 맞다. 특히 복잡한 규칙이나 특정 플러그인이 필요하면 ESLint를 계속 써야 한다.
하지만 대부분의 프로젝트—특히 새로 시작하는 프로젝트—에서는 Biome가 더 나은 선택이라고 확신한다. 빠르고, 단순하고, 충분히 강력하다.
설정 지옥에 지쳤다면, 한 번쯤 시도해볼 가치가 있다. 나처럼 "왜 진작 안 썼을까" 싶을 수도 있다.
# 시작은 이렇게 간단하다
npm install --save-dev @biomejs/biome
npx biome init
npx biome check --write .
이제 코드 작성에 집중하자. 린터와 포매터 설정 싸움은 Biome가 알아서 해결해줄 테니까.
There's a ritual I go through every time I start a new project. Type npm install eslint prettier eslint-config-prettier eslint-plugin-prettier, create .eslintrc.json and .prettierrc, then carefully orchestrate settings so the two tools don't fight each other.
At first, I accepted it as "this is the standard." But as projects accumulated, this combination felt increasingly awkward. I understood that ESLint handles code quality and Prettier handles formatting, but why do two tools need to read the same code twice? Why do we need two config files? And why is it so slow?
When I first encountered Biome, I thought: "Finally, someone solved this."
Biome's core insight was simple. Linting and formatting aren't separate tasks—they're just different stages of the same code analysis pipeline.
Using ESLint and Prettier separately is like hiring separate contractors for dusting and picking up trash when cleaning a house. Both need to walk through the same rooms twice, you need to decide who goes first, and you need to coordinate rules so they don't conflict.
Biome unified this. Parse the code once, build the AST (Abstract Syntax Tree) once, then handle both linting and formatting simultaneously. Plus, being written in Rust, benchmarks show it's 100x faster than existing tools.
Initially, I thought "just another alternative tool." But actually using it felt different. One config file, noticeably fast, excellent VS Code extension. This wasn't just an alternative—it was a paradigm shift.
The ESLint + Prettier combo required at least two config files. Add TypeScript and you need tsconfig.json too, plus eslint-config-prettier to prevent conflicts.
Biome manages everything with one config file.
{
"$schema": "https://biomejs.dev/schemas/1.9.4/schema.json",
"organizeImports": {
"enabled": true
},
"linter": {
"enabled": true,
"rules": {
"recommended": true,
"suspicious": {
"noExplicitAny": "error"
},
"style": {
"useConst": "warn",
"noUnusedVariables": "error"
}
}
},
"formatter": {
"enabled": true,
"indentStyle": "space",
"indentWidth": 2,
"lineWidth": 100
},
"javascript": {
"formatter": {
"quoteStyle": "single",
"trailingCommas": "all"
}
}
}
This single file configures linting rules, formatting style, and import organization. No conflicts possible. Because it's one tool from the start.
Node.js-based tools are inherently slow. JavaScript is an interpreted language, and overhead grows with file I/O. That's why running ESLint on large projects takes several seconds.
Biome is written in Rust. As a compiled native binary, it has virtually no startup time and parallel processing is built-in. Official benchmarks claim 100x faster than ESLint, though in real projects I noticed 10-50x improvement.
# ESLint + Prettier (before)
$ time npm run lint
real 0m8.342s
# Biome (after migration)
$ time biome check .
real 0m0.234s
This speed difference isn't just "nice to have"—it changes the developer experience. Immediate feedback on every save, linting never becomes a CI bottleneck.
Using ESLint and Prettier together always meant worrying about order. "Prettier first? ESLint first?" What order in Git hooks? In CI?
Biome eliminates this concern. One command does everything.
# Lint + format check
biome check .
# Auto-fix
biome check --write .
# CI mode (exit code 1 on errors)
biome ci .
Install the VS Code extension and format-on-save works immediately. No additional configuration needed.
// .vscode/settings.json
{
"editor.defaultFormatter": "biomejs.biome",
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"quickfix.biome": "explicit",
"source.organizeImports.biome": "explicit"
}
}
Migrating existing projects to Biome was easier than expected. Biome provides migration tools.
# Convert ESLint config to Biome
biome migrate eslint --write
# Convert Prettier config to Biome
biome migrate prettier --write
These commands read existing .eslintrc.json and .prettierrc and auto-convert to biome.json. Not 100% perfect, but most rules are compatible.
When I migrated my project:
biome migrate eslint --writebiome.json.eslintrc.json, .prettierrc, eslint-config-prettierpackage.jsonThe entire process took less than 10 minutes.
Adding Biome to CI pipelines is straightforward. As a standalone executable rather than a Node.js tool, installation is fast too.
name: CI
on: [push, pull_request]
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Biome
uses: biomejs/setup-biome@v2
with:
version: latest
- name: Run Biome
run: biome ci .
Runs much faster than the ESLint + Prettier combo. On large projects, CI time was cut by more than half.
Comparing current JavaScript/TypeScript ecosystem linting/formatting options:
| Tool | Speed | Linting | Formatting | Config Complexity | Ecosystem Maturity |
|---|---|---|---|---|---|
| ESLint + Prettier | Slow | Best | Best | Complex (2 tools) | Very High |
| Biome | Very Fast | Good | Good | Simple (1 tool) | Medium (growing) |
| oxlint | Very Fast | Basic | None | Simple | Low (early) |
ESLint still provides the most rules and plugins. But most projects don't need that many rules. Biome's recommended rule set catches over 90% of common issues.
oxlint is a Rust-based linter but has no formatting. You still need Prettier, losing Biome's "unified" advantage.
What resonated with me: For most projects, Biome's trade-offs are reasonable. Unless you need 100% ESLint rule compatibility, choosing speed and simplicity makes more sense.
Not perfect. Limitations to know:
Not yet supported:eslint-plugin-security)But the Biome team moves fast. In 2024 alone, Vue support was added to the roadmap and rule sets continue expanding. After forking from the Rome project, community-driven development actually accelerated.