Oxlint 완벽 가이드 — Rust 기반 초고속 JavaScript 린터
이 글의 핵심
Oxlint는 Oxc 컴파일러 스택 위에 올라간 Rust 기반 린터로, 대규모 저장소와 CI에서 구조적 병목을 줄이도록 설계되었습니다. 이 글에서는 핵심 개념, ESLint 마이그레이션, 설정과 규칙, 점진적 도입, CI/CD, 성능·도구 비교, 실무 체크리스트를 한 흐름으로 정리합니다.
이 글의 핵심
Oxlint는 JavaScript와 TypeScript를 대상으로 하는 고성능 린터이며, Oxc(Oxidation Compiler) 스택과 동일한 파서·분석 파이프라인을 공유합니다. 구현 언어는 Rust이며, 목표는 단순히 “조금 더 빠른 ESLint”가 아니라 대규모 모노레포·CI에서 반복 실행되는 린트 작업의 구조적 병목을 제거하는 데 있습니다.
이 글에서는 다음을 순서대로 다룹니다.
- Oxlint의 핵심 개념(설계 철학, 기본 규칙, 타입 인지·다중 파일 분석)
- ESLint에서의 마이그레이션(
@oxlint/migrate, 점진적 도입,eslint-plugin-oxlint) - 설정과 규칙(
.oxlintrc.json, 카테고리, 플러그인 플래그, 자동 수정) - CI/CD 통합(실패 조건, 병렬화, GitHub/GitLab 출력 형식)
- 성능 벤치마크와 해석 시 주의점
- ESLint·Biome·Oxlint 비교
- 실전 프로젝트 적용 체크리스트
공식 문서와 벤치마크 저장소는 본문에서 링크로 안내합니다. 버전에 따라 규칙 수·CLI 옵션 이름이 달라질 수 있으므로, 도입 시에는 프로젝트에 고정한 Oxlint 버전의 문서를 기준으로 삼는 것이 안전합니다.
1. Oxlint의 핵심 개념
1.1 Oxc 스택과의 관계
Oxlint는 “별도의 실험적 파서”를 얹은 도구라기보다, Oxc가 제공하는 동일한 구문 분석·모듈 그래프·(옵션에 따른) 타입 정보 위에서 규칙을 실행합니다. 이 덕분에 대규모 코드베이스에서의 처리량과 규칙 간 공유 비용을 줄이는 설계가 가능합니다. 팀 입장에서는 “린터 한 개”로 보이지만, 내부적으로는 컴파일러 파이프라인에 가까운 공유 캐시와 병렬 처리를 전제로 합니다.
1.2 확장성(스케일)을 전제로 한 목표
Oxlint는 문서에서도 강조하듯 대형 저장소와 CI를 1차 사용자로 둡니다. 로컬 개발자 한 명의 체감 속도도 중요하지만, 더 큰 비용은 매 PR마다 전체 또는 준전체 파일을 대상으로 린트를 돌리는 조직에서 발생합니다. 여기서 중요한 것은 단일 파일 린트의 미세 최적화뿐 아니라, 불필요한 중복 작업과 규칙 설계상의 병목을 줄이는 것입니다.
1.3 기본값: “정확성 중심”의 신호
기본 설정은 과도한 스타일 논쟁보다 틀렸거나 위험하거나 쓸모없는 코드를 우선 표면화하는 방향에 가깝습니다. 팀은 이후에 필요에 따라 규칙을 단계적으로 강화할 수 있습니다. “처음부터 모든 카테고리를 켠다”보다, 도입 초기에는 소음을 줄이고 점진적으로 범위를 넓히는 운영이 성공 확률이 높습니다.
1.4 규칙 범위와 플러그인 호환
Oxlint는 ESLint 코어와 널리 쓰이는 플러그인 계열 규칙을 폭넓게 이식하는 방향을 유지합니다. 공식 문서에서는 수백 개 이상의 규칙을 전제로 하며, 팀은 Rules와 compatibility matrix로 프레임워크·파일 종류 지원을 확인할 수 있습니다. 다만 “ESLint 생태계의 모든 규칙이 1:1로 항상 존재한다”는 뜻은 아니므로, 마이그레이션 전후로 규칙 갭 분석은 필수입니다.
1.5 타입 인지 린팅(Type-aware)
타입 정보가 필요한 규칙은 Oxlint가 TypeScript의 네이티브 재구현(일명 TypeScript 7 계열)과 연계하는 방식을 전제로 합니다. 공식 문서는 Biome이 자체 타입 추론을 발전시키는 접근과 대비되어 설명됩니다. 팀 입장에서는 “우리가 ESLint에서 typescript-eslint의 타입 인지 규칙에 의존하는가?”가 도입 난이도를 가르는 핵심 질문이 됩니다.
1.6 다중 파일 분석(Multi-file analysis)
일부 규칙은 파일 단위만으로는 비용이 크거나 정확도가 떨어집니다. Oxlint는 프로젝트 전역 모듈 그래프를 전제로 하는 분석을 1급 기능으로 다루며, 순환 의존성처럼 “여러 파일에 걸친 맥락”이 필요한 검사에서 ESLint에서 흔히 보이는 성능 절벽을 완화하려는 목표를 가집니다.
1.7 진단 출력과 자동 수정
진단은 사람이 읽기 쉬운 메시지와 함께 스팬·문맥 데이터를 포함하는 쪽으로 설계되어 있으며, AI 보조 도구가 고치기에도 유리하도록 구조화된 정보를 제공합니다. 자동 수정은 --fix 계열 옵션으로 적용할 수 있으나, 동작 변경 가능성이 있는 수정은 별도 플래그로 분리되는 편이므로 CI 정책과 맞춰야 합니다.
2. ESLint에서 마이그레이션
2.1 설정 형식의 차이
ESLint(특히 flat config)와 Oxlint는 개념은 비슷하지만 설정 파일 형식과 지원 규칙 집합이 다릅니다. 따라서 마이그레이션의 핵심은 “규칙 이름을 옮긴다” 수준을 넘어, 팀이 실제로 의존하는 규칙·플러그인·오버라이드를 기준으로 갭을 줄이는 것입니다.
2.2 ESLint v9/v10 flat config 자동 변환
프로젝트 루트에서 ESLint flat config(eslint.config.js 등)를 사용 중이라면, 공식 도구 @oxlint/migrate로 변환할 수 있습니다.
npx @oxlint/migrate
# 또는 설정 파일 경로를 명시
npx @oxlint/migrate ./eslint.config.mjs
이 도구는 지원되는 규칙을 Oxlint 설정으로 옮기고, 심각도·옵션·경로별 오버라이드·globals 처리·루트 ignore 등을 가능한 범위에서 보존합니다. 결과물은 기본적으로 .oxlintrc.json 형태이며, 생성 후에도 수동 편집이 전제입니다.
2.3 타입 인지 규칙이 있는 경우
ESLint에서 typescript-eslint의 타입 인지 규칙을 쓰고 있다면, 마이그레이션 시 --type-aware를 검토합니다.
npx @oxlint/migrate --type-aware
타입 인지 린트는 도구 체인(예: oxlint-tsgolint 등)과 프로젝트의 tsconfig 구조에 민감합니다. “한 번에 전부 켠다”보다, 소수 파일/패키지부터 타입 인지 규칙을 검증하는 편이 안전합니다.
2.4 ESLint 플러그인을 그대로 써야 할 때(JS Plugins)
Oxlint가 네이티브로 포함하지 않는 규칙이 남아 있으면 JavaScript 플러그인 경로를 사용할 수 있습니다. @oxlint/migrate는 기본적으로 플러그인 마이그레이션을 시도하며, 필요 시 --js-plugins=false로 끌 수 있습니다. 사내 전용 로컬 플러그인은 자동 마이그레이션이 어려울 수 있으므로, 생성된 설정에 jsPlugins로 수동 등록하는 절차가 필요할 수 있습니다.
2.5 ESLint v8 이하 레거시 설정
레거시 .eslintrc.*는 @oxlint/migrate가 자동으로 읽지 않습니다. 현실적인 경로는 다음과 같습니다.
@eslint/migrate-config등으로 flat config로 먼저 올린 뒤@oxlint/migrate로 Oxlint 설정으로 변환
단순한 레거시 설정은 형태가 Oxlint 설정과 유사해 수동 변환이 빠를 수도 있습니다.
2.6 점진적 도입: oxlint && eslint
한 번에 완전 대체가 어렵다면, Oxlint를 먼저 실행해 대부분의 문제를 빠르게 걸러내고, 남은 갭은 ESLint가 담당하는 구성이 흔합니다.
oxlint && eslint .
이때 중복 진단을 줄이기 위해 eslint-plugin-oxlint로 ESLint 측에서 Oxlint가 이미 다루는 규칙을 끄는 방식이 권장됩니다. 장기적으로는 의존성과 복잡도를 줄이기 위해 Oxlint 단일 린터로 수렴하는 것이 유지보수에 유리합니다.
3. 설치와 기본 실행
공식 문서는 개발 의존성으로 oxlint를 추가하는 흐름을 권장합니다.
pnpm add -D oxlint
# npm / yarn 사용자는 각 패키지 매니저에 맞게 동일하게 설치
package.json 스크립트 예시는 다음과 같습니다.
{
"scripts": {
"lint": "oxlint",
"lint:fix": "oxlint --fix"
}
}
설정 파일은 작업 디렉터리에서 자동 탐색되며, 일반적으로 .oxlintrc.json 또는 .oxlintrc.jsonc를 사용합니다. 초기 템플릿이 필요하면 CLI의 --init을 활용할 수 있습니다.
4. 설정과 규칙
4.1 설정 파일과 스키마
.oxlintrc.json에는 JSON 스키마를 지정해 에디터 자동완성을 붙이는 팀이 많습니다. 공식 문서의 예시처럼 "$schema": "./node_modules/oxlint/configuration_schema.json" 형태를 쓸 수 있습니다(경로는 설치 환경에 맞게 조정). JSONC는 주석을 허용하므로, 팀 규칙 설명을 설정 옆에 남기기에도 적합합니다.
4.2 규칙 카테고리와 -A / -W / -D
CLI에서는 규칙과 카테고리를 누적하여 허용·경고·에러로 지정할 수 있습니다. 예를 들어 기본적으로 엄격한 카테고리를 한꺼번에 켜되 특정 규칙만 예외를 두는 식으로 운용할 수 있습니다.
대표 카테고리(공식 CLI 문서 기준)는 다음과 같습니다.
correctness: 명백히 잘못되었거나 쓸모없는 코드suspicious: 매우 가능성이 높은 문제pedantic: 엄격하거나 오탐이 있을 수 있는 규칙perf: 성능 관점의 개선style: 관용적 표현·스타일restriction: 특정 언어·라이브러리 기능 사용 제한nursery: 실험적 규칙all: nursery를 제외한 전체(플러그인 자동 활성화는 문서 정의를 따름)
예시는 다음과 같습니다.
oxlint -D correctness -A no-debugger
4.3 플러그인 활성화 플래그
React·Jest·import·Vue 등은 CLI 플래그로 켜고 끄는 방식이 문서화되어 있습니다. 예를 들어 React 규칙이 필요하면 --react-plugin, 접근성은 --jsx-a11y-plugin, ESM 문제 탐지는 --import-plugin 같은 식입니다. 팀 표준 프리셋을 정해 package.json 스크립트에 고정하는 것이 재현성을 높입니다.
4.4 자동 수정의 안전성
--fix는 가능한 범위에서 자동 수정을 적용합니다. --fix-suggestions, --fix-dangerously는 프로그램 동작이 바뀔 수 있는 수정까지 포함할 수 있으므로, 기본 CI에서는 보수적으로 두고 로컬에서만 쓰거나, 별도 워크플로로 분리하는 편이 안전합니다.
4.5 무시 파일과 인라인 주석
.gitignore는 기본적으로 존중되는 편이며, ESLint 시절의 .eslintignore도 함께 쓸 수 있습니다. 다만 장기적으로는 .oxlintrc.json의 ignorePatterns로 흡수하는 것이 관리에 유리합니다. 파일 내부에서는 ESLint와 유사한 disable 주석 패턴을 사용할 수 있으며, 사용하지 않는 disable을 잡는 옵션(--report-unused-disable-directives 등)도 제공됩니다.
4.6 출력 형식
CI에서는 --format github 또는 --format gitlab처럼 플랫폼이 읽기 쉬운 형식을 선택하면 리뷰 가시성이 좋아집니다. 로컬은 기본 출력이면 충분한 경우가 많습니다.
5. CI/CD 통합
5.1 실패 조건 설계
CI에서 린트는 “경고만 무한히 쌓이는 단계”가 되면 품질 게이트로 기능하지 못합니다. Oxlint는 --quiet, --deny-warnings, --max-warnings 등으로 경고를 실패로 승격할 수 있습니다. 팀 정책에 맞게 선택하세요.
- 에러만 게이트:
--quiet로 경고 출력을 줄이되, 정책상 경고를 무시할지 주의 - 경고도 실패:
--deny-warnings - 경고 개수 상한:
--max-warnings 0같은 식으로 임계치 운영
5.2 캐시와 설치
CI에서는 패키지 매니저 캐시와 node_modules 복원이 전체 시간을 좌우합니다. Oxlint 자체가 빠르더라도, 설치 단계가 느리면 체감 이득이 줄어듭니다. lockfile 기반 캐시 키와 의존성 설치 최적화를 함께 점검하세요.
5.3 GitHub Actions 예시
아래는 개념 예시입니다. 러너 OS, 패키지 매니저, 워킹 디렉터리에 맞게 조정해야 합니다.
name: lint
on:
pull_request:
push:
branches: [main]
jobs:
oxlint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
cache: npm
- run: npm ci
- run: npx oxlint --format github
모노레포라면 각 패키지 루트에서 oxlint를 실행하거나, 루트에서 경로를 나눠 실행하는 방식을 선택합니다. 중요한 것은 동일한 버전의 Oxlint를 로컬과 CI가 공유하는 것입니다.
5.4 병렬 작업 설계
oxlint && eslint처럼 순차 실행은 단순하지만 합산 시간이 늘어납니다. 팀 상황에 따라 분리 잡으로 병렬화할 수 있으나, 그 경우에도 “중복 규칙”을 eslint-plugin-oxlint로 정리하지 않으면 진단 중복과 시간 낭비가 생깁니다.
5.5 스레드 수
--threads로 스레드 수를 제한할 수 있습니다. CI 러너의 CPU 할량이 작은 환경에서는 오히려 과도한 병렬화가 역효과일 수 있어, 타임아웃과 함께 튜닝하는 것이 좋습니다.
6. 성능 벤치마크
Oxlint는 공식적으로 bench-linter 저장소의 벤치마크를 근거로, ESLint 대비 대략 수십 배에서 최대 백 배 가까운 속도 차이를 제시합니다. 다만 벤치마크는 항상 다음 변수에 민감합니다.
- 대상 저장소 크기와 파일 분포
- 규칙 세트(타입 인지·다중 파일 분석 포함 여부)
- 디스크 I/O와 캐시 상태
- Node/TS 버전과 ESLint 플러그인 구성
따라서 “문서 수치를 그대로 우리 CI 시간으로 기대한다”기보다, 본인 저장소에서 동일한 규칙 범위로 ESLint와 Oxlint를 각각 재현 측정하는 것이 가장 신뢰할 수 있습니다. 중요한 것은 상대 비교뿐 아니라, PR당 린트가 차지하는 절대 시간이 조직의 목표치 안에 들어오는지입니다.
7. ESLint vs Biome vs Oxlint
세 도구를 동일 선상의 “완전 대체재”로 보기 어렵습니다. 실무에서 자주 쓰는 관점으로 정리하면 다음과 같습니다.
| 관점 | ESLint | Biome | Oxlint |
|---|---|---|---|
| 주요 역할 | 린트(+플러그인 생태계) 중심 | 린트·포맷·임포트 정리 등 통합 | 린트 중심(고성능) |
| 구현 | 전통적으로 JS 기반(팀·버전에 따라 다름) | Rust 기반 단일 도구 | Rust 기반(Oxc 스택) |
| 포매터 | 보통 Prettier 별도 또는 에디터 | 내장 포매터가 강점 | 포매터 아님(별도 도구 필요) |
| 설정 | 매우 유연, 플러그인 의존성 큼 | biome.json 중심으로 단순화 | .oxlintrc.json 등, ESLint v8 형식 호환 지향 |
| 타입 인지 | typescript-eslint 등으로 구성 | 자체 추론 발전 중(제품 로드맵 참고) | TS 네이티브 재구현 계열과 연계하는 방향 |
| 도입 목적 | 규칙·플러그인 최대 유연성 | 한 바이너리로 개발자 경험 통합 | 린트 병목 제거·CI 가속 |
정리하면, 포맷까지 한 번에 통합하려면 Biome 후보가 강하고, ESLint를 가능한 한 대체하면서 린트만 극단적으로 가속하려면 Oxlint 후보가 강합니다. ESLint는 여전히 가장 큰 플러그인 생태계를 갖지만, 그만큼 구성 비용과 실행 비용이 누적됩니다.
8. 실전 프로젝트 적용 체크리스트
8.1 도입 전
- 필수 규칙 목록을 스프레드시트로 뽑고, Oxlint 규칙/호환 매트릭스와 대조합니다.
- 타입 인지 규칙 의존도를 평가합니다(프로젝트
tsconfig구조 포함). - 프레임워크 파일(Vue/Svelte/Astro 등) 지원 범위를 compatibility matrix로 확인합니다.
8.2 도입 초기
@oxlint/migrate로 1차 변환 후, 경고 폭발을 막기 위해 카테고리·플러그인을 단계적으로 켭니다.- CI에서는
--format github같은 리뷰 친화 출력을 켭니다. - 자동 수정은 로컬에서 먼저 검증하고, CI 기본은 수정 없이 검증으로 둡니다.
8.3 안정화 이후
eslint-plugin-oxlint로 중복을 걷어내고, 가능하면 Oxlint 단일화를 목표로 합니다.- 버전 정책(프로젝트 문서의 versioning policy)에 맞춰 Oxlint 업그레이드 루틴을 정합니다.
- 느린 머신/대용량 브랜치에서도 타임아웃 없이 완료되는지 주기적으로 확인합니다.
9. 정리
Oxlint는 “Rust로 빠르다”는 문구를 넘어, 대규모 저장소와 CI를 전제로 한 구조적 설계가 핵심입니다. ESLint에서의 이전은 @oxlint/migrate로 빠르게 시작할 수 있지만, 성공은 규칙 갭 분석과 점진적 운영에서 결정됩니다. Biome과의 선택은 기능 겹침이 아니라 통합 도구가 필요한지, 린트 가속이 최우선인지로 판단하는 것이 실무적으로 명확합니다.
배포 전에는 git add, git commit, git push 후 npm run deploy를 실행하는 저장소 규칙을 따르십시오.