ESLint, Prettier, TypeScript

프로젝트를 만들 때마다 ESLint, Prettier, TypeScript부터 설정하게 되는데, 매번 다른 설정을 찾아다니기 힘들어서 그냥 여기다가 정리하려고 한다.

설정은 현재 사용도가 높은 Next.js 기준으로 정리한다. 패키지 매니저는 npm으로 하나, yarn이든 뭐든 상관은 없다.

Dependencies

Prettier, ESLint

우선 Prettier, ESLint부터 부터 깔자.

$ npm install -D prettier eslint eslint-config-prettier eslint-plugin-prettier

ESLint은 린트를 설정하고 Prettier는 포매팅을 설정하는 거지만, 두 설정 간 충돌이 생길 수 있다. 따라서 eslint-config-prettier, eslint-plugin-prettier을 설치한다.

그냥 eslint, prettier, eslint-config-prettier, eslint-plugin-prettier는 단짝이라고 생각하고 같이 깔자.

eslint-config-prettier - ESLint에서 Prettier와 충돌이 생길 수 있는 규칙을 제거한다.

// .eslintrc.js (또는 .json)
{
  extends: [
    // ...
    "prettier" // 마지막에 넣자.
  ]
}

eslint-plugin-prettier - ESLint에 Prettier 규칙을 추가해준다.

공식 문서에서 추천하는 옵션은 다음과 같다. eslint-plugin-prettier는 plugin:prettier/recommended 설정을 포함하고 있는데, 이 설정은 eslint-plugin-prettier 뿐 아니라 eslint-config-prettier 설정까지 한번에 해준다. 즉, 이전 단계에서 했던 extends는 없애도 된다.

// .eslintrc.js
module.exports = {
  plugins: ["prettier"],
  rules: {
    "prettier/prettier": "error"
  },
  extends: [
    "plugin:prettier/recommended" // 추천 옵션. 사용한다면 extends 맨 마지막에 넣어야 한다.
  ]
}

이후에는 직접 .prettierrc 파일을 만들면 된다.

TypeScript

타입스크립트 프로젝트를 쓸거면 깔면 된다.

$ npm install -D typescript

타입스크립트는 설정을 위해 tsconfig.json을 이용한다. 타입스크립트는 다른 언어와 달리 프로젝트에 따라 어떤 설정을 끄고 켜서 타입 체킹을 느슨하게 하거나 강하게 하는 것이 가능하다. 이런 내용이 궁금하다면 Effective TypeScript를 읽어보는 것을 추천한다. 이 블로그에도 정리되어 있다.

이펙티브 타입스크립트 (Effective TypeScript)

typescript-eslint

$ npm install @typescript-eslint/parser @typescript-eslint/eslint-plugin

ESLint와 TypeScript를 함께 사용할 것이기 때문에 typescript에 이어서 typescript-eslint도 설치한다. (설치 방법 및 용도)

참고로 TSLint는 deprecated 됐기 때문에 typescript-eslint를 사용해야 한다. (출처)

@typescript-eslint/parser는 ESLint 커스텀 파서이다. 타입스크립트 코드를 ESLint에 호환되는 노드로 파싱하며 타입스크립프 프로그램을 지원한다.

이는 타입스크립트가 자바스크립트와는 다른, ESLint와 호환되지 않는 AST 양식을 사용하기 때문이다. 타입스크립트 문법은 자바스크립트의 superset이니까(e.g., : number).

@typescript-eslint/eslint-plugin는 typescript-eslint에서 제공하는 규칙과 설정을 ESLint에서 사용하기 위해 필요한 플러그인이다. 마찬가지로 깔아야 한다.

설명은 마쳤으니 이제 typescript-eslint을 사용하기 위한 config도 추가해준다. 공식 문서 추천 세팅은 다음과 같다.

// .eslintrc.js
module.exports = {
  root: true,
  parser: "@typescript-eslint/parser", // 커스텀 parser 설정
  extends: ["eslint:recommended", "plugin:@typescript-eslint/recommended"],
  plugins: ["@typescript-eslint"]
}

마지막에 모든 설정을 정리해서 한번에 코드로 알려줄테니 걱정말도록!

Next.js

의존성부터 설치하자.

$ npm i -D @types/node @types/react @types/react-dom eslint-config-next eslint-plugin-jsx-a11y eslint-plugin-react eslint-plugin-react-hooks

React나 Next.js를 쓸 경우 ESLint가 모든 .jsx, .tsx 파일마다 import React 를 하라고 아우성치는 모습을 볼 수 있다.

'React' must be in scope when using JSX

어차피 Next.js를 쓴다면 React가 내장되어 있으니 rule을 추가한다.

module.exports = {
  rules: {
    "react/react-in-jsx-scope": "off",
  }
}

정리

이제 파일별로 내가 사용하는 설정을 정리한다.

포매팅의 경우 사람마다 워낙 취향이 다르다. 난 2 spaces indentation에 semicolon은 빼는 것을, trailing comma는 넣는 것을 선호한다.

그리고 C, Java, Rust 등 다른 언어에서는 ""가 문자열이니 난 double quote(")로 하겠다. 어차피 Prettier 돌리면 single quote(') 알아서 double quote로 바뀐다.

// .prettierrc
{
  "printWidth": 80,
  "semi": false,
  "singleQuote": false,
  "trailingComma": "all",
  "tabWidth": 2,
  "bracketSpacing": true,
  "endOfLine": "lf",
  "useTabs": false,
  "arrowParens": "avoid"
}

ESLint 설정은 위에서 설정한 걸 합친 결과이다. rules에는 내가 좋아하는 설정을 추가했다.

// .eslintrc.js
module.exports = {
  root: true,
  plugins: [
    "prettier",
    "@typescript-eslint"
    "react",
    "react-hooks"
  ],
  extends: [
    "next/core-web-vitals",
    "plugin:react/recommended",
    "plugin:react-hooks/recommended",
    "eslint:recommended",
    "plugin:@typescript-eslint/recommended",
    "plugin:prettier/recommended" // 마지막 유지
  ]
  rules: {
    "prettier/prettier": "error",
    "react/jsx-uses-react": "error",
    "react/jsx-uses-vars": "error",
    "react/react-in-jsx-scope": "off",
    "no-console": "warn",
    "object-shorthand": "error"
  }
}

TypeScript 설정이다. 기본 설정에 내가 필요하다고 생각하는 옵션을 추가로 넣는다.

{
  "compilerOptions": {
    "target": "es2022",
    "lib": ["dom", "dom.iterable", "esnext"],
    "allowJs": true,
    "skipLibCheck": true,
    "noUncheckedIndexedAccess": true, // 추가
    "strict": true,
    "noEmit": true,
    "esModuleInterop": true,
    "module": "esnext",
    "moduleResolution": "bundler",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "jsx": "preserve",
    "incremental": true,
    "plugins": [
      { "name": "next" }
    ],
    "paths": {
      "@/*": ["./src/*"]
    }
  },
  "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
  "exclude": ["node_modules"]
}

이후에 필요하다고 생각되는 플러그인이 있다면 추가 예정이다.

Last updated