Logo

ESLint 상세 설정 가이드

많은 자바스크립트 프로젝트에서 ESLint를 사용하여 코드에 문제가 없는지 검사를 하고 있습니다. 이번 포스팅에서는 ESLint를 어떻게 설정하는지에 대해서 각 옵션 별로 좀 자세히 알아보겠습니다.

ESLint에 대한 기본적인 사용법은 관련 포스팅를 참고 바랍니다.

설정 파일 형식

ESLint는 JSON, YAML, JavaScript와 같이 다양한 형식의 설정 파일을 지원하는데요. 설정 파일의 이름은 항상 .eslintrc가 되야하며, 원하는 포맷에 따른 파일 확장자를 사용해야 합니다.

예를 들어, JSON 파일 포맷을 사용하고 싶다면 .eslintrc.json, YAML 파일 포맷을 사용하고 싶다면 .eslintrc.yml이나 .eslintrc.yaml을 사용하면 됩니다.

뿐만 아니라, 자바스크립트 프로젝트의 메타 정보를 담고 있는 package.json 파일의 eslintConfig 속성을 통해서 ESLint 설정을 하는 것도 가능한데요. Create React App으로 React 프로젝트를 생성해보면 package.json 파일 내에서 ESLint 설정을 발견하게 됩니다.

package.json
{
  "eslintConfig": {
    "extends": ["react-app", "react-app/jest"]
  }
}

package.json 파일을 통해서 ESLint 설정을 하는 것은 소규모의 개인 프로젝트라면 몰라도 팀 단위의 프로젝트라면 그리 추천드릴 만한 방법인 아닌 것 같지는 않습니다. 왜냐하면 한 파일에 여러 다른 메타 정보와 섞어놓으면 프로젝트가 커짐에 따라 유지보수가 점점 힘들어지기 때문입니다. 사용하는지 파악하기가 어렵기 때문입니다.

그래서 저는 개인적으로 ESLint 설정할 때 처음 프로젝트에 참여하는 분들이 ESLint를 사용하는지 한 번에 딱 파악할 수 있도록 별도의 설정 파일을 사용하는 편인데요. 인터넷에서 ESLint 설정을 검색해보시면 대부분 JSON 형태로 제공되기 때문에 YAML 포맷보다 JSON 포맷이 확실히 복사해서 붙여넣기가 수월한 것 같습니다.

자바스크립트 포맷의 경우, ESLint가 아직까지 ES 모듈을 제공하지 않기 때문에 export 키워드를 사용할 수 없기 때문에 아무래도 최근에는 쓰기가 꺼려지더라고요. 그래서 본 포스팅에서는 JSON 포맷을 기준으로 예제 설정을 보여드리도록 하겠습니다.

root 옵션

ESLint를 설정할 때는 여러 개의 설정 파일을 사용할 수 있는데요. 특히 Monorepo와 같이 하나의 코드 저장소(repository)에서 여러 개의 프로젝트가 공존하는 경우 매우 유용합니다.

ESLint는 현재 린트(lint) 대상의 파일이 위치한 폴더 안에 설정 파일이 있는지 우선적으로 확인해보고 없으면 그 상위 폴더를 한 단계 씩 거슬러 올라가면서 설정 파일을 찾게되는데요. root 옵션이 true로 설정되어 있는 설정 파일을 만나면 더 이상 상위 폴더로 올라가지 않습니다.

예를 들어, 프로젝트의 별 설정 파일에는 root 옵션을 false로 설정하고, 코드 저장소 최상위 경로에는 root 옵션을 true로 설정하면 코드 저장소의 공통 설정과 프로젝트 별 특화 설정을 분리해서 관리할 수 있어서 편리합니다.

.eslintrc.json
{
  "root": true
}
packages/project-a/.eslintrc.json
{
  "root": false
}
packages/project-b/.eslintrc.json
{
  "root": false
}

ESLint 설정 파일이 하나만 있는 코드 저장소에서도 혹여나 상위 폴더에 있는 설정 파일에 영향을 받는 일이 없도록 root 옵션을 true로 설정하는 경우가 많습니다.

plugins 옵션

ESLint에는 기본으로 제공되는 규칙(rule) 외에도 추가적인 규칙(rule)을 사용할 수 있도록 만들어주는 다양한 플러그인(plugin)이 있는데요. 아마도 ESLint가 자바스크립트 커뮤니티에서 가장 많이 사용되는 린터(linter)가 된 이유는 바로 이 강력한 플러그인(plugin) 생태계라고 해도 과언이 아닐 것입니다.

플러그인은 설정 파일의 plugins 옵션을 통해서 설정하는데요. 예를 들어, 불러오기(import)와 React와 관련된 규칙은 다음과 같이 추가할 수 있습니다.

.eslintrc.json
{
  "plugins": ["import", "react"]
}

당연히 먼저 프로젝트에 해당 플러그인을 개발 의존성으로 설치해놨어야 되겠죠? 보통 ESLint 플러그인의 npm 패키지 이름은 eslint-plugin-로 시작하오니 참고바랍니다.

$ npm i -D eslint-plugin-import eslint-plugin-react

플러그인을 설정할 때 흔히 오해하게 되는 부분이 단순히 플러그인만 추가해주면 관련 규칙이 바로 활성화된다고 생각하는 것인데요. 사실 플러그인은 새로운 규칙을 단순히 설정이 가능한 상태로 만들어주기만 합니다. 규칙을 위반하면 오류(error)를 낼지 경고(warn)를 낼지 아니면 해당 규칙을 끌지(off)에 대해서는 다음에 설명드릴 extends 옵션이나 rules 옵션을 통해서 추가 설정을 해줘야 합니다.

extends 옵션

Google, Facebook, Airbnb 등 수많은 세계적인 기업들이 ESLint로 자바스크립트 코드를 린트(lint)하는데요. 설정 파일의 extends 옵션을 통해서 이러한 기업들이 공개해놓은 설정을 그대로 가져와 기반(base) 설정으로 활용할 수 있습니다.

예를 들어, Airbnb에서 npm 저장소에 공개한 ESLint 설정인 eslint-config-airbnb를 기반 설정으로 사용해볼까요?

.eslintrc.json
{
  "extends": ["airbnb"]
}

이렇게 확장이 가능한 ESLint 설정은 npm 패키지 이름이 eslint-config-로 시작하며 extends 옵션에 명시할 때는 위와 같이 앞 부분을 생략해도 무방합니다.

뿐만 아니라 대부분의 ESLint 플러그인은 추천 설정을 제공하는데요. extends 옵션은 이러한 추천 설정을 사용할 때도 사용됩니다.

예를 들어, 위에서 설정한 importreact 플러그인에서 제공하는 추천 설정을 사용해볼까요?

.eslintrc.json
{
  "plugins": ["import", "react"],
  "extends": ["plugin:import/recommended", "plugin:react/recommended"]}

이러한 ESLint의 확장성 덕분에 매 번 백지 상태에서 설정을 하지 않아도 되니 참 다행입니다. 👍

rules 옵션

설정 파일에서 rules 옵션은 규칙 하나 하나를 세세하게 제어하기 위해서 사용되는데요. 일반적으로는 extends 옵션을 통해서 설정된 규칙을 덮어쓰고 싶을 때 유용하게 쓸 수 있습니다.

예를 들어, Airbnb 기반 설정에서는 no-console 규칙을 어기면 경고(warn)를 내고, import/prefer-default-export 규칙을 어기면 오류(error)를 내도록 되어 있는데요. 만약에 no-console 규칙을 어겼을 시, 경고 대신에 오류를 내고, import/prefer-default-export 규칙은 비활성화해 보겠습니다.

.eslintrc.json
{
  "extends": ["airbnb"],
  "rules": {    "no-console": "error",    "import/prefer-default-export": "off"  }}

이렇게 ESLint는 rules 옵션으로 명시된 규칙을 extends 옵션을 통해서 가져온 규칙보다 우선 시 해주는데요. rules 옵션을 많이 사용하면 사용할 수록 직접 관리해야하는 설정이 늘어나는 부작용이 있으니 주의가 필요합니다.

아무래도 위에서 배운 extends 옵션을 통해 자바스크립트 커뮤니티에서 유지보수가 잘 되고 있는 공개된 설정을 적극적으로 활용하는 것이 유지보수 측면에서 유리하겠죠?

env 옵션

자바스크립트는 다양한 환경에서 실행될 수 있는데 각 환경마다 전역(global) 변수를 통해 접근이 가능한 고유한 객체들이 있습니다. 대표적인 예로, 브라우저 환경에서는 전역에서 접근이 가능하지만 NodeJS 환경에서는 불가능한 windows 객체를 들 수가 있겠네요.

ESLint는 기본적으로 미리 선언하지 않고 접근하는 변수에 대해서는 오류를 내기 때문에 이렇게 각 실행 환경(runtime)에서 기본적으로 제공되는 전역 객체에 대해서 설정을 통해 알려줘야 하는데요. 이러한 역할을 실행 파일의 env 옵션이 담당합니다.

예를 들어, ESLint로 린트(lint)를 할 자바스크립트 코드가 브라우저에서 실행될 수도 있고, NodeJS에서도 실행될 수 있다면, 두 가지 실행 환경에서 접근 가능한 모든 전역 객체를 다음과 같이 등록해줄 수 있습니다.

.eslintrc.json
{
  "env": {
    "browser": true,
    "node": true
  }
}

parser와 parserOptions 옵션

개발자가 작성하는 자바스크립트 코드는 실제로 브라우저와 같은 실행 환경에서 실제로 돌아가는 코드와 다른 경우가 많은데요. 대표적인 예로 타입스크립트나 JSX와 같은 자바스크립트의 확장 문법으로 개발하거나 Babel과 같은 트랜스파일러(transpiler)를 통해 최신 문법으로 개발하는 경우를 들 수 있습니다.

개발자들이 항상 최신 문법의 자바스크립트로 코딩할 수 있도록 도와주는 도구인 Babel에 대한 자세한 내용은 관련 태그를 참고 바랍니다.

ESLint는 기본적으로 순수한 자바스크립트 코드만 이해할 수 있기 때문에 자바스크립트의 확장 문법이나 최신 문법으로 작성한 코드를 린트(lint)하기 위해서는 그에 상응하는 파서(parser)를 사용하도록 설정해줘야 합니다.

예를 들어, 타입스크립트와 JSX를 사용하여 작성된 코드를 린트(lint)하도록 설정해보겠습니다.

.eslintrc.json
{
  "parser": "@typescript-eslint/parser",
  "parserOptions": {
    "sourceType": "module",
    "ecmaFeatures": {
      "jsx": true
    },
    "ecmaVersion": 11,
  }
}

이번에는 Babel 파서로 사용하도록 설정해보겠습니다.

.eslintrc.json
{
  "parser": "@babel/eslint-parser"
}

settings 옵션

일부 ESLint 플러그인은 추가적인 설정이 가능한데요. 이런 경우에는 설정 파일의 settings 옵션을 사용합니다.

예를 들어, react 플러그인이 프로젝트에 설치된 리액트의 버전을 자동으로 탐지하도록 설정해보겠습니다. (기본 설정은 리액트 최신 버전을 기준으로 린트(lint)를 하게 되었습니다.)

.eslintrc.json
{
  "settings": {
    "react": {
      "version": "detect"
    }
  }
}

다른 플러그인에 대한 구체적인 설정 방법은 해당 플러그인의 공식 문서를 참고바라겠습니다.

ignorePatterns 옵션과 .eslintignore 파일

ESLint는 린트(lint)를 수행할 때 기본적으로 node_modules 폴더나 .로 시작하는 설정 파일은 무시하는데요. 그 밖에 다른 파일을 무시하고 싶다면 설정 파일의 ignorePatterns 옵션을 사용할 수 있습니다.

{
  "ignorePatterns": ["build", "dist", "public"]
}

이 방법 대신에 .gitignore 파일과 유사한 방식으로 .eslintignore 파일을 생성해도 됩니다.

build
dist
public

만약에 ESLint가 .gitignore 파일에 이미 나열해놓은 경로를 무시하도록 설정하고 싶다면 ESLint 커맨드를 실행할 때 --ignore-path 옵션을 붙여주면 됩니다.

$ eslint --ignore-path .gitignore .

overrides 옵션

프로젝트 내에서 일부 파일에 대해서만 살짝 다른 설정을 적용해줘야 할 때는 어떻게 해야할까요? 그럴 때는 설정 파일의 overrides 옵션을 사용하면 됩니다.

예를 들어, 프로젝트에 자바스크립트 파일과 타입스크립트 파일이 공존한다면 자바스크립트 파일을 기준으로 기본 설정을 하고, 타입스크립트 파일을 위한 설정은 overrides 옵션에 명시할 수 있습니다. 타입스크립트 확장자를 가진 파일에 대해서는 타입스크립트 용 파서와 플러그인과 추천 설정을 사용하도록 세팅해주고 있습니다.

.eslintrc.json
{
  "overrides": [
    {
      "files": "**/*.+(ts|tsx)",
      "parser": "@typescript-eslint/parser",
      "plugins": ["@typescript-eslint"],
      "extends": ["plugin:@typescript-eslint/recommended"]
    }
  ]
}

만약에 프로젝트 내에 테스트 파일에만 추가적으로 Jest 플러그인과 Testing Library 플러그인에서 추천하는 규칙을 활성하고 싶다면 다음과 같이 설정합니다.

.eslintrc.json
{
  "overrides": [
    {
      "files": ["**/__tests__/**/*", "**/*.{spec,test}.*"],
      "env": {
        "jest/globals": true
      },
      "plugins": ["jest", "testing-library"],
        "extends": [
        "plugin:jest/recommended",
        "plugin:jest-dom/recommended",
        "plugin:testing-library/react"
      ]
    }
  ]
}

샘플 설정 파일

지금까지 배운 내용을 종합하여 간단한 샘플 설정 파일을 작성해보았습니다. 실제 프로젝트에서 ESLint 설정을 하실 때 템플릿으로 사용하시면 좋을 것 같습니다.

{
  "root": true,
  "env": {
    "browser": true,
    "commonjs": true,
    "es6": true,
    "node": true
  },
  "extends": [
    "eslint:recommended",
    "plugin:react/recommended",
    "plugin:react-hooks/recommended",
    "plugin:jsx-a11y/strict",
    "plugin:import/recommended",
    "plugin:import/typescript",
    "plugin:@typescript-eslint/recommended",
    "plugin:testing-library/react",
    "prettier"
  ],
  "plugins": [
    "react",
    "react-hooks",
    "jsx-a11y",
    "import",
    "@typescript-eslint"
  ],
  "settings": {
    "import/resolver": {
      "typescript": {
        "alwaysTryTypes": true
      }
    },
    "react": {
      "version": "detect"
    }
  },
  "rules": {
    "no-console": "error",
    "import/prefer-default-export": "off"
  },
  "overrides": [
    {
      "files": "**/*.+(ts|tsx)",
      "parser": "@typescript-eslint/parser",
      "plugins": ["@typescript-eslint"],
      "extends": ["plugin:@typescript-eslint/recommended"]
    },
    {
      "files": ["**/__tests__/**/*", "**/*.{spec,test}.*"],
      "env": {
        "jest/globals": true
      },
      "plugins": ["jest", "jest-dom", "testing-library"],
      "extends": [
        "plugin:jest/recommended",
        "plugin:jest-dom/recommended",
        "plugin:testing-library/react"
      ]
    }
  ]
}

마치면서

본 가이드에서 다룬 정도의 옵션만 아시면 현업에서 ESLint 설정을 하시는데 큰 불편함은 없을 것 같은데 어떠신가요? ESLint 설정을 깔끔하게 하시는데 도움이 되었으면 좋겠습니다.