개발새발 로그

React - Eslint + Prettier 설정하기 본문

React

React - Eslint + Prettier 설정하기

이즈흐 2024. 6. 11. 19:41

📖들어가며..

React 프로젝트를 시작할 때 개발 환경을 구축하는데 

보통 eslint나 prettier 설정은 인터넷에 검색해서 복붙을 하는 경향이 있었다.

빨리 개발환경을 세팅하고 프로젝트를 진행하기 위해서였다.

 

이번에 프로젝트 개발 환경을 구축하면서 eslint와 prettier을 설치하고 세팅하면서

"이게 무슨 역할을 하는 걸까?", "최소한 필요한 세팅은 어떻게 될까?" 를 생각하게됐고,

이를 정리하고자 포스팅하게 되었다.

 

✨Vite로 React 설치하기

나는 보통 vite를 사용한다. 

 Vite가 Webpack보다 빠르다..뭐다.. 하지만(현재 webpack은 또 발전해서 많이 빨라졌다고 한다.)

개인적으로는 정말 편하다.

간단한 프로젝트를 하기에 적합한 것 같다.

npm create vite@latest .

- 위 명령어를 통해 설치한다.

- 이후에는 입맛대로 선택해서 설치하면된다.

 

✨Eslint + Prettier 설정하기

Vite로 리액트를 설치하고 나면 아래와 같이 .eslintrc.cjs 가 생길 것이다.

module.exports = {
  root: true,
  env: { browser: true, es2020: true },
  extends: [
    'eslint:recommended',
    'plugin:@typescript-eslint/recommended',
    'plugin:react-hooks/recommended',
  ],
  ignorePatterns: ['dist', '.eslintrc.cjs'],
  parser: '@typescript-eslint/parser',
  plugins: ['react-refresh'],
  rules: {
    'react-refresh/only-export-components': [
      'warn',
      { allowConstantExport: true },
    ],
  },
}

그러면 위 설정에서 좀 더 필요한 패키지가 있기 때문에 몇 가지를 설치할 것이다.

npm i -D 
eslint  // 코드 품질과 일관성을 유지하기 위한 정적 분석 도구
prettier  // 코드 포매터로 코드 스타일을 자동으로 일관되게 유지
eslint-plugin-react //React 지원 플러그인, 문법 분석 및 검사 지원
eslint-config-prettier  /// ESLint와 Prettier 간의 충돌을 방지하기 위한 설정을 제공
eslint-plugin-prettier  // Prettier 규칙을 ESLint 규칙으로 통합하여 ESLint가 코드 스타일을 검사하게 함
@typescript-eslint/eslint-plugin  // TypeScript 코드에 대한 ESLint 규칙을 제공하는 플러그인
@typescript-eslint/parser  // ESLint가 TypeScript 코드를 이해하고 분석할 수 있도록 도와주는 파서

더 설치하긴하지만 먼저 제일 기본적인 것들을 위처럼 설치해준다.

위를 설치하고나면 필요한 설정들이 있다.

 

 


 

📖eslint-plugin-react

여기에서 더 자세한 설명을 볼 수 있다.

간단하게 이 플러그인에 대해서 설명하면 아래와 같다.

React 지원 플러그인, 문법 분석 및 검사 지원
- JSX 구문 검사
- React 컴포넌트의 올바른 사용을 보장하는 규칙 제공
- React 관련 모범 사례를 따르도록 하는 규칙 제공

 

이를 설치하고 아래와 같이 eslintrc.cjs 파일에 추가해줘야한다.

  "extends": [
    "eslint:recommended",
    "plugin:react/recommended",
    "plugin:react/jsx-runtime", // 필수 추가
  ]
  
  // ...
  
 // plugins: ['react']를 추가하는 이유는, 
 // eslint-plugin-react 플러그인을 활성화하여 React와 관련된 추가적인 규칙을 적용하기 위함
  plugins: [
    'react',

그리고 필수추가라고 말한 부분은 아래와 같이 공식 문서에서 말해주고 있다.

If you are using the new JSX transform from React 17, extend react/jsx-runtime in your eslint config (add "plugin:react/jsx-runtime" to "extends") to disable the relevant rules.
React 17의 새로운 JSX 트랜스폼을 사용하는 경우, eslint 구성에서 react/jsx-runtime을 확장하여("plugin:react/jsx-runtime"을 "extends"에 추가) 관련 규칙을 비활성화하세요.

만약 여기에서 말하는 설정을 해주지 않는다면 eslint의 jsx오류가 뜰 것이다.

'React' must be in scope when using JSX eslintreact/react-in-jsx-scope 오류

아래와 같이 jsx지원을 설정하라고하는데 이는 필요없다고 판단해서 작성하지 않았다.

//JSX 지원을 사용하도록 설정합니다.

//eslint 2+ 사용
{
  "parserOptions": {
    "ecmaFeatures": {
      "jsx": true
    }
  }

✅추가 사항

이제부터 eslint.config.js를 사용한다고 한다. vite는 아직 업데이트가 안돼서 eslintrc.cjs가 생성되는 것 같다.

자세한건 공식문서를 확인하라고 하고 있다.

사실 이렇게 계속해서 발전하는 사항에 대해서 파악해야 했었는데 이 포스팅을 통해 알게 되었다.

계속해서 바뀌는 프론트엔드 생태계를 빨리빨리 파악하자..

 

나는 일단 eslintrc.cjs로 진행하려고한다.

위 방식은 아직 익숙치 못해서 정확하게 공식문서가 얘기하는 방식을 활용할 수 있을까 에 대한 문제때문이다.

 

 


📖eslint-config-prettier

여기에서 자세하게 확인할 수 있다.

Prettier와 충돌할 수 있는 ESLint 규칙을 비활성화하여 두 도구가 함께 원활하게 작동하도록 한다.

 extends: [
    'prettier'  // Prettier 규칙 적용
  ],

 

Turns off all rules that are unnecessary or might conflict with Prettier.
This lets you use your favorite shareable config without letting its stylistic choices get in the way when using Prettier.
Note that this config only turns rules off, so it only makes sense using it together with some other config.
불필요하거나 프리티어와 충돌할 수 있는 모든 규칙을 끕니다.
이렇게 하면 Prettier를 사용할 때 스타일 선택에 방해받지 않고 좋아하는 공유 가능한 구성을 사용할 수 있습니다.
이 설정은 규칙만 끄기 때문에 다른 설정과 함께 사용하는 경우에만 의미가 있습니다.

 

 


 

📖eslint-plugin-prettier

여기에서 자세하게 확인할 수 있다.

Prettier 규칙을 ESLint 규칙으로 통합한다.

 

주요 역할은 Prettier의 포맷팅 규칙을 ESLint 규칙으로 변환하여, ESLint가 Prettier의 규칙을 따르도록 한다.

아래와 같이 설정을 추가해줘야 한다.

{
    "extends": ["plugin:prettier/recommended"] // // Prettier 규칙 설정

    "plugins": ["prettier"], // / eslint-plugin-prettier 플러그인 활성화
      "rules": {
        "prettier/prettier": "error" // // Prettier 규칙을 ESLint 오류로 표시
      }
    }
}

 

🤔eslint-config-prettier와 eslint-plugin-prettier의 차이?

위 두 플러그인의 차이는 아래와 같다.

eslint-plugin-prettier

역할: Prettier의 포맷팅 규칙을 ESLint 규칙으로 변환하여 ESLint가 Prettier의 규칙을 기반으로 코드를 검토하도록 합니다.

장점: ESLint가 Prettier의 포맷팅 규칙을 기반으로 코드 스타일을 검토할 수 있게 해줍니다. 이를 통해 Prettier와 ESLint 통합을 더욱 간편하게 합니다.

eslint-config-prettier

역할: Prettier와 충돌할 수 있는 ESLint 규칙을 비활성화하여 두 도구가 함께 원활하게 작동하도록 합니다.

장점: Prettier와 ESLint의 규칙 충돌을 방지하여 코드 스타일과 코드 품질 검사를 일관되게 유지할 수 있게 해줍니다.

 


📖@typescript-eslint/eslint-plugin과@typescript-eslint/parser

우리는 eslintrc.cjs를 사용하기 때문에 여기에서 사용법을 확인하는 것이 좋다. (레거시 Eslint)

📜@typescript-eslint/eslint-plugin

typescript-eslint의 규칙들을 사용할 수 있게 해준다

TypeScript 코드에서 발생할 수 있는 다양한 코드 품질 문제를 검사하고, TypeScript에 특화된 규칙을 제공합니다. 이를 통해 TypeScript 프로젝트에서도 ESLint를 효과적으로 사용할 수 있습니다.

📜@typescript-eslint/parser

타입스크립트 코드 분석 및 검사 지원한다.

TypeScript코드에 대한 AST생성한다고 한다.

기본적으로 ESLint는 JavaScript 코드를 분석하도록 설계되어 있지만, TypeScript는 JavaScript보다 복잡한 타입 시스템과 구문을 가지고 있습니다. 따라서 TypeScript 코드를 정확히 분석하고 검사하려면 전용 파서가 필요합니다.

 

위 두 패키지를 사용하려면 아래와 같이 코드를 추가해주면 된다.

/* eslint-env node */
module.exports = {
  extends: [
  'eslint:recommended', 
  'plugin:@typescript-eslint/recommended'  // TypeScript ESLint 추천 규칙 사용
  ], 
  parser: '@typescript-eslint/parser', // TypeScript 파서 설정
  plugins: ['@typescript-eslint'], // TypeScript ESLint 플러그인 활성화
  root: true,
};

 

 


👨‍💻내가 추가한 설정

그럼 이제는 내가 추가한 설정들을 설명하려고 한다.

검색해서 무슨용도인지 어떻게 사용하는지 검색해서 이해하기 쉽도록 정리해보았다.

주관적으로 작성했기때문에 오류가 있다면 피드백 부탁드립니다.

 

📖eslint-plugin-import와 eslint-import-resolver-typescript

여기에서 자세하게 확인할 수 있다.

ES6+ import/export 문법의 린팅을 지원하고, 파일 경로와 import 이름의 오타를 예방한다.

이러한 것들을 마크업 에디터에 표시해주는 모듈이라고 한다.

이 플러그인은 ES2015+(ES6+) 가져오기/내보내기 구문의 린팅을 지원하고 파일 경로 및 가져오기 이름의 철자가 틀린 문제를 방지하기 위한 것입니다.
ES2015+ 정적 모듈 구문이 제공하려는 모든 장점을 에디터에서 마크업합니다.

 

나는 타입스크립트를 사용하기 때문에 eslint-import-resolver-typescript와  @typescript-eslint/parser 를 추가로 설치해야 한다.

// 플러그인에 eslint-plugin-import를 설정
plugins: [
	'import',
]
// 기호에 맞춰 eslint-plugin-import에서 추천하는 규칙을 적용한다.
extends: [
  "plugin:import/typescript", // TypeScript 관련 import 규칙
  "plugin:import/recommended", // import 플러그인의 추천 규칙 사용
   // 대안으로, 'recommended'는 아래의 두 개의 설정과 조합할 수 있습니다.
  // "plugin:import/errors",
  // "plugin:import/warnings",
]

rules : {
    'import/order': [
          'error',
          {
          //['builtin', 'external']: 이 배열은 'builtin' (Node.js 내장 모듈)과 
          // 'external' (npm 패키지) 모듈이 같은 그룹에 속하도록 설정
            groups: [
              ['builtin', 'external'],
              'internal',
              // ['parent', 'sibling']: 부모 디렉토리와 형제 디렉토리 모듈을 같은 그룹으로 설정합니다.
              ['parent', 'sibling'],
              'index'
            ],
            //각 그룹 사이에 항상 빈 줄을 추가
            'newlines-between': 'always',
            // 특정 경로 패턴에 대해 별도의 그룹을 정의
            pathGroups: [
              {
                pattern: '@/**',
                group: 'internal',
                position: 'after'
              }
            ]
          }
        ],

/*
이 설정은 import 문들을 다음과 같은 순서로 정렬한다.
->
Node.js 내장 모듈 및 외부 패키지
프로젝트 내부 모듈 (예: @/로 시작하는 경로 포함)
부모 디렉토리 및 형제 디렉토리 모듈
현재 디렉토리의 index 파일
*/

📜eslint-import-resolver-typescript

eslint-plugin-import플러그인의 해석기(resolver) 중 하나로, TypeScript 프로젝트에서 import 문을 정확하게 해석할 수 있도록 도와줍니다.
이 해석기는 TypeScript의 설정 파일(tsconfig.json)을 읽어들여, TypeScript 컴파일러가 모듈을 해석하는 방식과 일치하게 import 문을 처리합니다.

 

주요기능은 아래와 같다고 한다.

  • TypeScript의 경로 별칭 지원: tsconfig.json에서 설정한 경로 별칭(paths)을 인식할 수 있습니다.
  • 타입 정의 파일 지원: .d.ts 파일을 통해 모듈을 해석할 수 있습니다.
  • 프로젝트 구조 인식: TypeScript 프로젝트의 구조를 이해하고, 올바른 모듈 경로를 찾도록 도와줍니다.

특히 eslint-import-resolver-typescript는 아래와 같은 설정이 필요하다고 한다.

  "settings": {
    "import/resolver": {
      "typescript": {
        "alwaysTryTypes": true
        
        // 아래 더 많은 설정이 있지만 
        // 기본적으로 <root>/tsconfig.json을 사용하려면 생략하세요.
      }
    },
    // ...

이를 통해 ESLint가 TypeScript의 설정과 일치하게 모듈을 해석할 수 있으며, 경로 별칭, 타입 정의 파일 등을 지원하여 더 정확하고 일관된 코딩 스타일을 유지할 수 있다고 한다.

 

근데 eslint-plugin-import/typescript 에서는 이렇게 작성하면도 괜찮다고 하고 있다.

부가 설명으로는 아래와 같다.

다음 스니펫을 사용하거나 그 아래에 설명된 세분화된 설정을 사용하여 직접 구성을 조합할 수 있습니다.
다음 구성에서 사용되는 @typescript-eslint/parser 및 eslint-import-resolver-typescript를 설치했는지 확인합니다.

"그 아래" 에서는 reslover에 대해서 설명해주고 있다.

 

"settings": {
    "import/resolver": {
    // # 타입스크립트 리졸버를 설치하고 구성해야 합니다.
    // https://github.com/import-js/eslint-import-resolver-typescript#configuration 참조
      "typescript": true,
      "node": true
    },

 

나는 일단 첫 번째 방식을 사용하고 있다.

두 코드 모두 똑같은 기능을 하는 것으로 이해하고 있지만 다시 더 정확하게 공부해서 나중에 수정해보려고 한다.

 

🤔resolver가 뭘까?

나는 아직 정확하게 resolver의 역할에 대해서 이해하지 못한 것 같았다.

그래서 공식문서를 보면서 이해해보려고 했다.

With the advent of module bundlers and the current state of modules and module syntax specs, it's not always obvious where  "import x from 'module"  should look to find the file behind "module".
모듈 번들러의 출현과 모듈 및 모듈 구문 사양의 현재 상태로 인해 'module'에서 x를 가져오면 모듈 뒤에 있는 파일을 어디에서 찾아야 하는지 항상 명확하지 않습니다.

 

 

 

📖 eslint-plugin-simple-import-sort

여기에서 자세하게 설명하고 있다.

simple-import-sort는 JavaScript 및 TypeScript 파일에서 import 문을 자동으로 정렬해주는 ESLint 플러그인입니다.
이 플러그인은 코드의 가독성을 높이고 일관성을 유지하는 데 도움을 줍니다.
import 문을 정렬하는 규칙을 설정하고, 이를 자동으로 적용하여 개발자가 수동으로 정렬할 필요 없이 깨끗한 코드 스타일을 유지할 수 있게 해줍니다.

 

{
  "plugins": ["simple-import-sort"],
  "rules": {
    "simple-import-sort/imports": "error",
    "simple-import-sort/exports": "error"
  }
}

예시를 보면 이해가 빨리된다.

import React from 'react';
import { useState } from 'react';
import C from './C';
import B from './B';
import A from './A';

// 위 코드가 다음과 같이 정렬됩니다.

import React from 'react';
import { useState } from 'react';

import A from './A';
import B from './B';
import C from './C';

🤔그럼 eslint-plugin-simple-import-sort랑 eslint-plugin-import랑 무슨 차이일까?

📜eslint-plugin-simple-import-sort

주요 목적: import 문을 자동으로 정렬하는 것.

기능

  • import 문을 알파벳 순서 또는 지정된 규칙에 따라 자동 정렬.
  • import 문을 그룹별로 정렬 (예: 외부 모듈, 내부 모듈, 상대 경로).
  • 사용하기 쉽고 설정이 간단함.

📜 eslint-plugin-import

주요 목적: import 문과 관련된 다양한 규칙을 제공하여 모듈 해석과 import/export 사용을 관리하고 최적화하는 것.

기능

  • import 문에서 사용되지 않는 모듈 경고.
  • import 문에서 모듈의 존재 여부 확인.
  • import 순서 검사.
  • 특정 모듈의 import 금지.
  • import 문에서 파일 확장자 일관성 검사.

eslint-plugin-simple-import-sort은 단순히 import 문을 정렬하는 데 중점을 두고,

eslint-plugin-import은 import 문과 관련된 다양한 규칙을 제공하여 더 포괄적인 관리와 최적화를 목표로 한다.

 

 

🛠️최종 설정

 "eslint": "^8.57.0",
"eslint-config-prettier": "^9.1.0",
"eslint-import-resolver-typescript": "^3.6.1",
"eslint-plugin-import": "^2.29.1",
"eslint-plugin-prettier": "^5.1.3",
"eslint-plugin-react": "^7.34.2",
"eslint-plugin-react-hooks": "^4.6.0",
"eslint-plugin-react-refresh": "^0.4.6",
"eslint-plugin-simple-import-sort": "^12.1.0",
"prettier": "^3.3.2",
"typescript": "^5.2.2",

📜.eslintrc.cjs

module.exports = {
  root: true, // 이 설정 파일이 최상위 설정 파일임을 지정
  env: { browser: true, es2020: true }, // 환경 설정: 브라우저와 ES2020 문법을 지원
  extends: [
    'eslint:recommended', // ESLint의 권장 규칙 세트 사용
    'plugin:@typescript-eslint/recommended', // TypeScript ESLint 플러그인의 권장 규칙 세트 사용
    'plugin:react-hooks/recommended', // React Hooks 관련 권장 규칙 세트 사용
    'plugin:prettier/recommended', // Prettier와 ESLint의 충돌을 방지하기 위한 설정
    'plugin:react/recommended', // React 관련 권장 규칙 세트 사용
    'plugin:react/jsx-runtime', // React 17에서의 JSX 변환을 지원하는 설정
    'plugin:import/typescript', // TypeScript용 import 플러그인 설정
  ],
  ignorePatterns: ['dist', '.eslintrc.cjs'], // ESLint가 무시할 파일 또는 디렉토리 지정
  parser: '@typescript-eslint/parser', // TypeScript 코드를 파싱하기 위한 파서 지정
  plugins: [
    'react', // React 관련 규칙 사용
    'react-refresh', // React Fast Refresh 관련 규칙 사용
    'import', // import 관련 규칙 사용
    'simple-import-sort', // import 정렬 관련 규칙 사용
    '@typescript-eslint', // TypeScript ESLint 플러그인 사용
    'prettier' // Prettier 관련 규칙 사용
  ],
  settings: {
    'import/resolver': {
      typescript: {
        alwaysTryTypes: true // TypeScript 모듈 해석 시 타입 정보도 시도
      },
      react: {
        version: 'detect' // React 버전을 자동으로 감지
      }
    }
  },
  rules: {
    'react-refresh/only-export-components': [
      'warn', // React 컴포넌트만 export하도록 경고
      { allowConstantExport: true } // 상수 export는 허용
    ],
    'simple-import-sort/imports': 'error', // import 문을 정렬하지 않으면 오류 발생
    'simple-import-sort/exports': 'error', // export 문을 정렬하지 않으면 오류 발생
    'import/order': [
      'error', // import 문 순서가 올바르지 않으면 오류 발생
      {
        groups: [
          ['builtin', 'external'], // 내장 모듈과 외부 모듈을 그룹화
          'internal', // 내부 모듈 그룹
          ['parent', 'sibling'], // 부모와 형제 모듈을 그룹화
          'index' // 인덱스 파일 그룹
        ],
        'newlines-between': 'always', // 그룹 사이에 항상 새로운 줄 추가
        pathGroups: [
          {
            pattern: '@/**', // '@/'로 시작하는 경로를 내부 모듈로 그룹화
            group: 'internal', // 내부 모듈 그룹으로 지정
            position: 'after' // 다른 경로 그룹 다음에 위치
          }
        ]
      }
    ],
    'react/prop-types': 0, // prop-types 검사를 비활성화 (TypeScript 사용)
    'react-hooks/rules-of-hooks': 'error', // React Hooks 규칙 위반 시 오류 발생
    'prettier/prettier': 'warn', // Prettier 규칙 위반 시 경고 발생
    'no-console': [
      'error', // console.log 사용 시 오류 발생
      {
        allow: ['error', 'warn'] // console.error와 console.warn은 허용
      }
    ]
  }
}

위 설정의 아래에 내가 주로 사용하는 rules를 추가했다.(주석으로 확인)

 

여기서 중복되어 정리한 코드가 있다

  extends: [
    'plugin:prettier/recommended', // Prettier와 ESLint의 충돌을 방지하기 위한 설정

    'prettier' // Prettier 규칙 적용
  ],

 

plugin:prettier/recommended는 이미 Prettier의 규칙을 ESLint에 통합하므로, prettier를 따로 추가할 필요가 없습니다. 
extends 배열에서 prettier를 제거해도 됩니다.

 

📜.prettierrc

{
  // 세미콜론을 사용하지 않음
  "semi": false,
  // 문자열에 작은 따옴표를 사용
  "singleQuote": true,
  // HTML, JSX 등에서 각 속성을 한 줄에 하나씩 작성
  "singleAttributePerLine": true,
  // 닫는 괄호를 같은 줄에 배치 (HTML, JSX 등)
  "bracketSameLine": true,
  // 줄의 끝을 LF (Line Feed)로 설정
  "endOfLine": "lf",
  // 끝에 쉼표를 사용하지 않음
  "trailingComma": "none",
  // 화살표 함수의 매개변수에 괄호를 사용하지 않음 (매개변수가 하나일 경우)
  "arrowParens": "avoid"
}

 

📘마무리하며..

이제까지 eslint 설정은 복붙을 주로 사용했다.

그냥 남이 하는 것이 정답이니까라고 생각하고 사용했다.

무슨 역할을 하는지 아예몰랐었다.

이제라도 내가 주로 사용하는 것들이 무슨 역할을 하는지 어떻게 사용하는지 알아야할 것 같아서 이렇게 정리하게 되었다.

또 까먹겠지만 해당 글을 통해서 리마인드할 수 있도록 노력하려고 한다.

 

728x90
반응형
LIST