ESLint는 JavaScript 코드에서 문법적 오류, 잠재적 버그 및 코딩 스타일 규칙을 검토하고 강제하는 도구이다. 코드 품질 유지, 버그 예방, 코드 리뷰 간소화 등의 이점을 얻을 수 있다. 프로젝트에서 코드의 일관성을 유지하고, 규칙을 강제할 수 있으며, 특히 팀 프로젝트에서 코드 스타일을 통일하는 데 효과적이다. 잠재적인 오류나 버그를 사전에 감지하고, 올바른 코딩 관행을 따르도록 도움을 주고, 일관된 스타일을 강제함으로써, 코드 리뷰 시 스타일에 대한 논의도 줄일 수 있다.
npm install eslint
ESLint의 설정 파일(다양한 확장자로 사용 가능)인 .eslintrc
,.eslintrc.json
, eslint.config.js
등은 다양한 구성 요소들로 이루어져 있으며, 각 요소는 프로젝트의 코드 규칙을 정의하고 관리하는 데 중요한 역할을 한다. ESLint 설정은 주로 JSON, YAML, 또는 JS 형식으로 작성되며, 각 구성 요소와 그 역할을 하나씩 정리해보자.
ESLint 최신 버전에서는
env
,parserOptions
,extends
:"eslint:recommended”
등의 일부 속성들이 기본값으로 설정되어 더 이상 명시적으로 설정하지 않아도 된다.
root
(루트 설정)root
는 해당 ESLint 설정 파일이 프로젝트의 최상위 설정 파일임을 지정하는 플래그이다. 이를 통해 상위 디렉토리의 다른 ESLint 설정 파일을 무시하고, 이 설정 파일만 사용하도록 할 수 있다.
{
"root": true
}
plugins
(플러그인)과 extends
(확장 설정)extends
는 특정 규칙 세트를 적용하는 설정이며, 이를 extends
옵션에 추가하면 해당 규칙들이 적용된다. 반면에, plugin
은 개별적으로 필요한 규칙들을 제공한다. 플러그인만 추가한다고 해서 규칙이 적용되는 것은 아니다. 어떤 규칙이 필요한지 직접 선택해야 한다. 플러그인은 여러 개의 extends
를 제공할 수 있다.
{
"plugins": ["react"],
"extends": [
"plugin:react/recommended"
],
}
쉽게 설명하자면, extends
는 미리 정의된 규칙 세트를 한 번에 적용할 수 있도록 해준다. 마치 미리 준비된 세트 메뉴를 주문하는 것과 비슷하다. 설정 파일 하나만 추가하면 그 안의 규칙들이 모두 적용된다. plugins
은 여러 개의 개별 규칙들을 제공하는데, 이 중에서 필요한 규칙들을 직접 골라서 사용할 수 있다. 그냥 플러그인을 설치했다고 해서 규칙이 바로 적용되는 게 아니라, 어떤 규칙들을 사용할지 직접 선택해야 한다. 플러그인은 때로는 설정 파일도 같이 제공해서, 그 설정 파일을 extends
에 추가하면 해당 규칙들이 일괄 적용되도록 할 수도 있다.
즉, extends
는 규칙들을 쉽게 묶어서 한 번에 적용하는 방법이고, plugins
은 개별적인 규칙들을 제공하고 그중에 필요한 것만 선택해서 쓸 수 있는 도구이다.
rules
(개별 규칙 설정)rules
는 코드 품질, 스타일, 성능 등의 규칙을 개별적으로 설정할 수 있는 요소이다. 각 규칙은 'off'
, 'warn'
, 'error'
중 하나의 수준으로 설정할 수 있으며, 배열 형태로 추가적인 옵션을 함께 설정할 수 있다. extends
의 규칙보다 우선으로 적용된다는 특징이 있다.
{
"rules": {
"no-console": "warn", // console.log 사용 시 경고
"eqeqeq": ["error", "always"], // === 사용 강제
"indent": ["error", 2], // 들여쓰기 2칸으로 설정
"quotes": ["error", "single"], // 작은 따옴표 사용 강제
"no-unused-vars": "error" // 사용되지 않은 변수 금지
}
}
예시에서 쓰인 규칙들은 ESLint 자체에서 제공하는 내장된 규칙들이다. 즉, 별도의
plugins
와extends
를 설정하지 않아도 ESLint 기본 규칙들은 사용할 수 있다.
"off"
: 규칙을 비활성화"warn"
: 경고 메시지 출력"error"
: 오류로 처리하여 빌드를 실패하게 만듦ignorePatterns
옵션과 .eslintignore
파일 (무시할 파일/폴더 설정)ignorePatterns
는 ESLint가 특정 파일이나 폴더를 검사하지 않도록 할 수 있는 설정이다. node_modules
같은 폴더나 특정 빌드 아티팩트 파일을 ESLint 검사에서 제외할 수 있다. ESLint는 린트(lint)를 수행할 때 특정 파일들을 무시하고 싶다면 설정 파일의 ignorePatterns
옵션을 사용하면 된다.
{
"ignorePatterns": ["build", "dist", "public"]
}
또는 .eslintignore
파일을 생성해도 동일하게 작동한다.
// 디렉토리 root에 .eslintignore 생성
build
dist
public
overrides
(개별 환경 설정)overrides
는 특정 파일이나 디렉토리에 대해 다른 ESLint 설정을 적용할 수 있도록 해주는 옵션이다. 기본적으로 설정한 규칙은 프로젝트 전반에 적용되지만, overrides
를 사용하면 특정 파일 패턴에 대해 맞춤형 설정을 정의할 수 있다. 이 기능은 파일 타입별로 다른 규칙이 필요할 때 유용하다.
{
"overrides": [
{
"files": ["*.ts", "*.tsx"],
"rules": {
"@typescript-eslint/no-unused-vars": ["error"],
"no-console": "off"
}
}
]
}
이 예시에서는 .ts
와 .tsx
파일에 대해서 TypeScript 관련 규칙을 적용하고 있다. 이 경우 @typescript-eslint/no-unused-vars
규칙을 설정하고 no-console
을 끄고 있다.
앞서 간단히 다뤘지만, Plugin을 어떻게 활용하느냐에 따라 ESLint의 기능과 방향성이 완전히 달라질 수 있기 때문에 해당 옵션에 대한 자세한 설명이 필요하다.
Plugin은 ESLint의 핵심 기능 중 하나로, 추가적인 규칙과 기능을 제공하는 확장 모듈이다. 기본적으로 ESLint가 제공하지 않는 새로운 규칙이나 환경 설정을 추가하거나, 특정 프레임워크와 라이브러리를 지원하는 역할을 한다.
ESLint Plugin은 다른 개발자들이 만들어 공개한 규칙의 모음이며, 기본 ESLint 규칙 외에 더 많은 규칙을 사용할 수 있게 해준다. 이러한 플러그인들은 보통 npm에 라이브러리 형태로 배포되며, npm install
명령어로 설치한 후 .eslintrc
설정 파일의 plugins
섹션에 추가하여 사용할 수 있다. 플러그인이 제공하는 규칙들은 해당 플러그인의 GitHub 저장소나 npm 페이지의 README 파일에서 확인할 수 있다.
플러그인은 기본 ESLint 규칙을 확장하는 역할을 하지만, 단독으로 작동하지 않는다. 플러그인을 설치해도 실제로 규칙을 적용하려면 해당 규칙을 명시적으로 활성화해야 한다. 즉, 플러그인은 규칙을 정의하고 이를 바탕으로 사용자가 직접 활성화할 수 있는 설정을 제공하는 방식이다.
보통 eslint plugin 라이브러리의 이름은 eslint-plugin-{플러그인 이름}
형식을 따르며, .eslintrc
설정 파일의 plugins
에 {플러그인 이름}
을 추가하여 사용할 수 있다.
ESLint 플러그인을 사용하는 방법은 간단하다.
설치: 플러그인은 보통 npm 또는 yarn을 통해 설치된다. 예를 들어, React와 관련된 ESLint 플러그인을 설치하려면 다음과 같이 실행한다.
npm install eslint-plugin-react --save-dev
.eslintrc 파일에서 설정: 설치가 완료되면 .eslintrc
파일에서 플러그인을 사용하도록 설정할 수 있다. 예를 들어, eslint-plugin-react
를 추가하려면 다음과 같이 설정한다.
{
"plugins": [
"react"
],
"rules": {
"react/jsx-uses-react": "error",
"react/jsx-uses-vars": "error"
}
}
plugins
: 플러그인의 이름을 추가한다. 여기서는 "react"를 추가했다.rules
: 플러그인이 제공하는 규칙을 명시적으로 활성화해야 한다. 규칙 이름은 일반적으로 플러그인명/규칙명
형식이다. 예를 들어, react/jsx-uses-react
와 같은 규칙을 활성화할 수 있다.Next.js의 기본 ESLint 설정을 세팅했다면,
.eslintrc.json
extends
에"next/typescript"
가 추가된다. 해당 extend에"typescript-eslint"
,typescript-eslint/parser
,"react"
plugin이 포함되어 있으니, 해당 plugin들의 설치와extends
,plugins
추가를 생략하고 rules를 사용할 수 있다.
typescript-eslint
typescript-eslint
는 TypeScript 코드를 검사하는 도구이다. 기본적으로 ESLint는 자바스크립트 코드를 검사하고, TypeScript는 다른 구조로 코드를 분석하는데, 이 둘이 다르게 동작하면서 서로 호환되지 않는 문제가 있다. typescript-eslint
는 이 문제를 해결해 두 도구가 함께 사용할 수 있도록 만든 것이다. 즉, TypeScript 코드를 ESLint에서 검사할 수 있게 도와주는 다리 역할을 하는 도구가 typescript-eslint
이다.
@typescript-eslint/naming-convention
은 typescript-eslint
라이브러리에서 제공하는 규칙이다. 기본 ESLint나 React 플러그인보다 더 세밀하게 이름 규칙을 정의할 수 있는 것이 특징이다. 이 플러그인을 사용하면 변수, 함수, 클래스, 인터페이스 등 다양한 코드 요소에 대해 구체적인 네이밍 규칙을 설정할 수 있어, 특히 팀의 코딩 스타일을 통일하고 코드의 가독성을 높이는 데 유용하다.
기본 ESLint나 React 플러그인에서도 이름 관련 규칙을 설정할 수 있지만, TypeScript의 타입 특성까지 고려한 상세한 규칙을 적용하기 위해 @typescript-eslint/naming-convention
이 널리 사용되는 것이다.
typescript-eslint/parser
typescript-eslint
를 사용한다는 것은 TypeScript 파일을 ESLint로 분석한다는 의미이다. 이를 위해 @typescript-eslint/parser
를 eslintrc.json
"parser"
에 반드시 추가해야 한다. 이 파서는 TypeScript 코드를 이해하고 분석할 수 있도록 돕기 때문에, JavaScript에 사용하는 기본 파서로는 TypeScript의 고유 문법을 처리할 수 없기 때문이다.
npm install --save-dev @typescript-eslint/parser
{
"parser": "@typescript-eslint/parser",
"plugins": ["@typescript-eslint"],
"extends": [
"plugin:@typescript-eslint/recommended"
]
}
@typescript-eslint/naming-convention
은 선택자(selector)와 형식(format)을 사용해 정의된다. 선택자는 이름 규칙이 적용될 대상(예: 변수, 함수, 클래스 등)을 지정하고, 형식은 그 대상이 따라야 할 이름 형식을 정의한다.
예를 들어 변수는 camelCase
또는 UPPER_CASE
로 작성하도록 규칙을 설정할 수 있고, 클래스는 항상 PascalCase
로 작성하도록 강제할 수 있다.
format 옵션은 변수, 함수, 클래스 등의 이름을 정할 때 따라야 할 다양한 형식을 정의한다. 예를 들어, 다음과 같은 형식이 있을 수 있다.
myID
, myId
모두 유효).myId
는 유효하지만 myID
는 유효하지 않다).selector 옵션은 이름 규칙을 강제하려는 대상(변수, 함수, 클래스 등)을 지정하는 설정이다. 예를 들어, 선택자로 function
이나 variable
을 지정하면 함수나 변수가 이름 규칙에 맞는지 검사하게 된다. 선택자는 하나 또는 여러 개를 배열로 전달할 수 있다.
modifiers는 선택자에 더 구체적인 조건을 추가하는 설정이다. 예를 들어, private
, readonly
, static
같은 접근성이나 속성을 지정해서 특정한 경우에만 이름 규칙을 적용할 수 있다. 예를 들어 { modifiers: ['private', 'readonly', 'static'] }
라고 설정하면 private static readonly
로 선언된 항목에만 규칙이 적용되고, 단순히 private
로만 선언된 항목에는 적용되지 않는다.
선택자의 형식은 매우 많다. 그 중 대표적으로 많이 쓰이는 형식들은 아래와 같다.
module.exports = {
"plugins": [
"@typescript-eslint"
],
"extends": [
"plugin:@typescript-eslint/recommended"
],
"rules": {
"@typescript-eslint/naming-convention": [
"error",
{
"selector": "variable",
"format": ["camelCase"],
}, // 변수 카멜 케이스 강제화
{
"selector": "function",
"format": ["camelCase"],
}, // 함수 카멜 케이스 강제화
{
"selector": "typeLike",
"format": ["PascalCase"]
} // 타입 파스칼 케이스 강제화
]
}
};
@typescript-eslint/naming-convention
은 추가적인 세부 옵션을 통해 더 구체적으로 설정할 수 있다. 대표적인 몇 가지는 아래와 같다.
leadingUnderscore: 'allow'
는 변수 이름이 _privateVariable
처럼 밑줄로 시작할 수 있도록 허용한다.{ prefix: ['I'] }
로 설정하면 인터페이스 이름이 항상 'I'로 시작하도록 강제할 수 있다.훨씬 더 많은 규칙들은 해당 라이브러리 링크를 통해 전부 확인 가능하다.
eslint-plugin-react
, eslint-plugin-react-hooks
eslint-plugin-react
,eslint-plugin-react-hooks
는 React 컴포넌트와 관련된 코드를 검사하는 데 사용되는 도구이다. 기본 ESLint 설정만으로는 React 특유의 코드 작성 방식에 대한 검사를 정확히 할 수 없기 때문에, 플러그인을 사용하여 React 컴포넌트의 라이프사이클, JSX 문법, hooks 사용에 대한 규칙을 설정하고 검사할 수 있다.
react/jsx-uses-vars
: JSX 내에서 정의된 변수들이 실제로 사용되고 있는지 검사하여, 정의되었지만 사용되지 않은 경우를 잡아낸다.react-hooks/rules-of-hooks
: hooks는 반드시 최상위에서 호출되어야 하며, 조건문이나 반복문 내에서 사용되면 안 된다. 이 규칙은 hooks의 사용을 올바르게 제한하여 최적의 성능과 예측 가능한 동작을 보장한다.이 외에도 JSX 속성에 대한 설정, 컴포넌트 이름 규칙, prop-types의 올바른 사용 등에 관한 세밀한 검사 규칙을 제공한다.
module.exports = {
"plugins": [
"react",
"react-hooks"
],
"extends": [
"plugin:react/recommended",
"plugin:react-hooks/recommended"
],
"rules": {
"react/jsx-uses-vars": "error",
"react-hooks/rules-of-hooks": "error"
}
};
eslint-plugin-import
eslint-plugin-import
는 import/export 문에서 발생할 수 있는 여러 문제들을 사전에 방지하고, import 문들의 정렬을 자동화하여 코드 일관성을 유지할 수 있다.
import/no-unresolved
: 존재하지 않는 모듈을 import하려 할 경우 경고를 발생시켜, 잘못된 파일 경로나 오타로 인해 생길 수 있는 오류를 미리 방지한다.import/order
: import 문을 정해진 순서에 맞게 정렬하도록 강제한다. 예를 들어 외부 라이브러리, 내부 모듈, 스타일 시트 등으로 import 문을 구분하고 그 순서를 정하여 코드를 일관되게 유지할 수 있다.import/newline-after-import
: 마지막 import 문 이후에는 반드시 한 줄의 공백을 두도록 강제한다. 이는 가독성을 높이고 import 영역과 로직 영역을 명확히 구분하기 위해 사용된다.module.exports = {
"plugins": [
"import"
],
"extends": [
"plugin:import/errors",
"plugin:import/warnings"
],
"rules": {
"import/no-unresolved": "error",
"import/order": [
"warn",
{
"groups": [
"builtin",
"external",
"internal"
],
"newlines-between": "always"
}
],
"import/newline-after-import": "warn"
}
};
eslint-plugin-check-file
eslint-plugin-check-file
은 파일 구조와 파일 이름의 일관성을 유지하기 위해 사용되는 플러그인이다. 특히 대규모 프로젝트에서 파일의 이름 규칙이나 폴더 구조가 일관되지 않으면 유지보수가 어려워질 수 있기 때문에, 이 플러그인을 사용하여 파일의 이름과 구조를 검사하고 규칙을 강제한다.
check-file/filename-naming-convention
: 지정된 파일에 대해 파일 이름이 일관된 패턴을 따르도록 강제한다.check-file/folder-naming-convention
: 지정된 폴더에 대해 폴더 이름이 일관된 패턴을 따르도록 강제한다.module.exports = {
"plugins": [
"check-file"
],
"rules": {
"check-file/naming-convention": [
"error",
{
"regex": "^[a-z]+(?:-[a-z]+)*$",
"match": true
}
], // 파일 이름을 케밥 케이스로 강제화
"check-file/folder-match-regex": [
"error",
{
"regex": "^(components|utils)$",
"match": true
}
] // 특정 폴더 내 파일 형식 제한
}
};
eslint-plugin-tailwindcss
eslint-plugin-tailwindcss
는 Tailwind CSS 클래스의 사용을 검사하는 플러그인이다. Tailwind의 클래스를 사용할 때의 실수를 방지하고, 프로젝트에서 일관성 있는 스타일링을 유지하기 위해 사용된다. 이 플러그인은 올바른 Tailwind CSS 클래스 이름을 사용하도록 보장하고, 잘못된 클래스 이름이나 잘못된 Tailwind CSS 설정을 미리 발견할 수 있다.
tailwindcss/classnames-order
: Tailwind CSS 클래스 이름이 지정된 순서대로 배치되었는지 검사한다.tailwindcss/no-custom-classname
: Tailwind의 기본 클래스 이름 외에 임의의 사용자 정의 클래스 이름 사용을 방지한다.module.exports = {
"plugins": [
"tailwindcss"
],
"extends": [
"plugin:tailwindcss/recommended"
],
"rules": {
"tailwindcss/classnames-order": "warn",
"tailwindcss/no-custom-classname": "off"
}
};
tanstack/eslint-plugin-query
tanstack/eslint-plugin-query
는 TanStack Query (구 React Query) 관련 코드를 검사하기 위한 ESLint 플러그인이다. TanStack Query는 비동기 데이터 관리를 간소화하기 위해 사용되며, 이 플러그인은 사용자가 TanStack Query를 올바르게 사용하고 있는지 검사하여 코드의 품질과 일관성을 유지하도록 돕는다.
tanstack/query/exhaustive-deps
:쿼리 함수에서 사용하는 모든 변수를 쿼리 키에 추가하도록 강제한다.tanstack/query/stable-query-client
: QueryClient
를 애플리케이션의 전체 생명주기 동안 하나의 인스턴스만 생성되게 강제한다.module.exports = {
"plugins": [
"@tanstack/query"
],
"extends": [
"plugin:@tanstack/query/recommended"
],
"rules": {
"tanstack/query/exhaustive-deps",
"tanstack/query/stable-query-client"
}
};
- Documentation - ESLint - Pluggable JavaScript Linter
- naming-convention | typescript-eslint
- npm: eslint-plugin-react
- npm: eslint-plugin-react-hooks
- npm: eslint-plugin-import
- npm: eslint-plugin-check-file
- npm: eslint-plugin-tailwindcss
- npm: @tanstack/eslint-plugin-query
- ESLint Plugin Query | TanStack Query Docs