린팅과 포매팅
린팅과 포매팅
린터와 포매터는 비슷해 보이지만 역할이 다릅니다. 이 글은 두 도구의 정의 · 대표 도구 · 트레이드오프.
1. 린터와 포매터에 대한 이야기
린터 (linter) 는 코드의 의미 · 스타일 · 잠재 결함을 정적으로 검사. "이 변수는 선언만 되고 사용되지 않는다", "이 함수는 await 없이 async 를 호출한다" 같은 진단. 어원은 1978 년 Bell Labs 의 Stephen Johnson 이 만든 C 분석기 lint.
포매터 (formatter) 는 코드의 스타일 (들여쓰기 · 줄바꿈 · 공백) 을 일관되게 다시 적음. 의미를 바꾸지 않음. Prettier 의 공식 페이지가 이 도구를 "an opinionated code formatter" 로 정의하면서 의도적으로 옵션을 줄이는 방향. 옵션이 적다는 것은 합의 비용을 줄인다는 설계 결정.
두 역할은 분리되기도 하고 한 도구가 둘 다 하기도 합니다.
2. JS / TS
| 도구 | 첫 릴리스 | 역할 |
|---|---|---|
| ESLint | 2013 | Nicholas C. Zakas 가 시작. AST 기반 린터. 플러그인 생태계. |
| Prettier | 2017 | James Long. opinionated 포매터. |
| TypeScript ESLint | 2019 | typescript-eslint.io. TS AST 위에서 ESLint 규칙 실행. |
| Rome → Biome | 2023 | Rome 프로젝트가 종료된 후 커뮤니티 포크 Biome 출범. Rust 기반. 포매터 + 린터 통합. |
| dprint | 2020 | Rust 기반 포매터. 다언어 플러그인. |
| Oxlint / oxc | 2023 | Rust 기반 ESLint 호환 린터. 속도 강조. |
대표 조합 둘:
- ESLint + Prettier — 가장 큰 생태계. 규칙 충돌은
eslint-config-prettier로 끔. ESLint 의 풍부한 플러그인 (React Hooks · Next.js · Tailwind · security 등) 이 강점. - Biome 단독 — 한 바이너리에 포매터 · 린터를 묶었고 Rust 라 빠름. Biome 공식 페이지는 Prettier 와 약 97% 호환 · 약 35배 속도. 단 ESLint 규칙 전부를 포팅하지는 않았으므로 (현재 약 491 규칙) 특정 플러그인에 의존하는 프로젝트는 갈아타기 전 확인 필요.
3. Python
| 도구 | 첫 릴리스 | 역할 |
|---|---|---|
| pylint | 2003 | 가장 오래된 Python 린터. 검사 폭이 넓고 느린 편. |
| flake8 | 2010 | pycodestyle + pyflakes + mccabe 래퍼. |
| isort | 2013 | Timothy Crosley. import 정렬 전문 도구. |
| Black | 2018 | PSF 프로젝트. opinionated 포매터 (거의 옵션 없음). |
| Ruff | 2022 | Astral. Rust. flake8 / isort / pydocstyle / pyupgrade / autoflake 의 다수 규칙을 한 도구로 흡수. 이후 Ruff Format (2023) 으로 Black 호환 포매팅. |
Ruff 공식 문서는 "10–100x faster" 라는 비교. 단일 바이너리 · pyproject.toml 설정 · 자동 수정 (--fix) 이 채택을 빠르게 만듦.
4. Java
| 도구 | 출시 | 역할 |
|---|---|---|
| Checkstyle | 2001 | 스타일 · 관습 검사. 가장 오래됨. |
| PMD | 2002 | 정적 분석. 코드 스멜 · 복잡도. |
| SpotBugs (FindBugs 후속) | 2017 | 바이트코드 기반 잠재 버그 탐지. |
| google-java-format | 2015 | Google 스타일 가이드 포매터. |
| Spotless | 2016 | Gradle / Maven 플러그인. 포매터들을 빌드 단계에 통합. |
Spotless 가 빌드 통합 측면에서 자주 채택. ./gradlew spotlessApply 한 줄로 일괄 포맷.
5. pre-commit hook 통합
- lint-staged (Node) + Husky — 스테이지된 JS / TS 파일에만 ESLint · Prettier 실행. 작은 PR 에 빠름.
- pre-commit (pre-commit.com) — 다언어.
.pre-commit-config.yaml에 Ruff · Black · Checkstyle 같은 도구를 줄 단위로. - lefthook (Go) — 단일 바이너리 · 언어 비종속.
6. 자주 쓰는 모양
ESLint (평탄 설정, v9+):
// eslint.config.mjs
import js from "@eslint/js";
import tseslint from "typescript-eslint";
export default [
js.configs.recommended,
...tseslint.configs.recommended,
{ rules: { "no-console": "warn" } },
];
Prettier:
// .prettierrc
{ "semi": true, "singleQuote": true, "trailingComma": "all", "printWidth": 100 }
Biome:
// biome.json
{
"$schema": "https://biomejs.dev/schemas/1.9.0/schema.json",
"formatter": { "enabled": true, "indentStyle": "space", "indentWidth": 2 },
"linter": { "enabled": true, "rules": { "recommended": true } }
}
Ruff (pyproject.toml):
[tool.ruff]
line-length = 100
target-version = "py312"
[tool.ruff.lint]
select = ["E", "F", "I", "UP", "B"]
ignore = []
명령:
# 공통
pnpm exec eslint .
pnpm exec prettier --write .
pnpm exec biome check --write .
# Python
uv run ruff check .
uv run ruff format .
# Java
./gradlew spotlessCheck
./gradlew spotlessApply
7. 트레이드오프
Biome vs ESLint + Prettier:
| 축 | ESLint + Prettier | Biome |
|---|---|---|
| 설정 단순성 | 두 도구 각각 + 충돌 회피 설정 | 한 파일 |
| 속도 | 충분하나 큰 저장소에서 느려질 수 있음 | Rust 기반, 보고된 수치상 빠름 |
| 규칙 커버리지 | 플러그인 포함 수천 규칙 | 약 491 (성장 중) |
| 생태계 성숙도 | 10 년 + | 비교적 신규 |
큰 기존 코드베이스에서 ESLint 플러그인 의존이 많으면 갈아타기 비용이 크고, 새 프로젝트나 단순 규칙으로 충분한 경우 Biome 의 단일 바이너리가 합의 비용을 줄임.
8. 자주 걸리는 자리
포매터와 린터의 같은 규칙 충돌 — 포맷은 포매터에 맡기고 린터는 의미 검사만 하도록 분리. eslint-config-prettier 가 이 분리를 표준화.
ESLint 9 의 평탄 설정 (eslint.config.js) 으로 옮기면서 기존 .eslintrc.* 와 호환이 끊김. 양쪽이 섞이면 한쪽이 무시.
Black 과 Ruff Format — 줄바꿈 결정이 거의 같지만 완전히 동일하지는 않음. 한 저장소 안에서 한쪽을 정해 일관되게.
IDE 자동 포맷 vs CI 포맷 검사 버전 다름 — PR 마다 포맷 변경이 끊임없이 들어옴. 버전을 락파일 · package.json · pyproject.toml 에 고정.
pre-commit 훅이 너무 많음 — 우회 (--no-verify) 가 늘어남. 무거운 검사는 CI 로 미루는 분담.
하고픈 말
린터와 포매터의 역할 분리 + 한 바이너리 통합 (Biome · Ruff) 의 두 흐름이 공존합니다. 큰 생태계 의존이 있으면 ESLint + Prettier, 새 프로젝트나 속도가 중요하면 Biome / Ruff. 어느 쪽이든 버전 고정 + 에디터 자동 적용 + CI 검증 셋이 함께 있을 때 PR 의 포맷 잡음이 사라집니다.
Next
- python-venv-poetry-history
- regex
ESLint 공식 문서 · Prettier 공식 문서 · Biome 공식 사이트 · Ruff 공식 문서 · Black 공식 문서 · Spotless GitHub · typescript-eslint · editorconfig.org · Prettier — Why Prettier? 를 참고합니다.