Pullanner project - Prettier, ESLint 설정

이소라·2023년 2월 22일

Pullanner project

목록 보기
2/11

Introduction

  • 일관성 있는 형식으로 코드 작성 및 잠재적 에러를 발견하여 코드 퀄리티를 높이기 위하여 Code Formatter와 Linter를 도입했습니다.
    • 이러한 도구를 사용하여 코딩 스타일에 대한 고민을 덜고, 코드 작성에만 집중할 수 있게 되었습니다.
  • ESLint에도 코드 포맷팅 기능이 있지만, Prettier의 자동 코드 포맷팅 기능이 더 강력하기 때문에 eslint-config-prettier 플러그인을 사용하여 eslint에서 formatting관련 rule들을 모두 해제하였습니다.
    • 즉 Linting은 ESLint가, Code Formatting은 Prettier가 담당할 수 있도록 했습니다.
  • 커밋 시 ESLint와 Prettier가 자동적으로 적용될 수 있도록 Git Hook 중 pre-commit을 사용했습니다.
    • Git Hook을 좀 더 편리하게 사용할 수 있는 도구인 Husky와 Lint-staged를 활용하여 커밋 시 ESLint와 Prettier가 적용된 후 커밋이 될 수 있도록 설정하였습니다.



Prittier, ESLint 파일

prettier 설정 파일

{
    "bracketSpacing": true,
    "singleQuote": true,
    "tabWidth": 2,
    "trailingComma": "all",
    "printWidth": 100,
    "endOfLine": "auto"
 }

eslint 설정 파일

'use strict';

module.exports = {
  env: {
    browser: true,
    es2022: true,
    node: true,
  },
  extends: [
    'eslint:recommended',
    'plugin:import/recommended',
    'plugin:react/recommended',
    'plugin:react-hooks/recommended',
    'plugin:@typescript-eslint/recommended',
    'plugin:prettier/recommended',
    'plugin:react/jsx-runtime',
    'airbnb',
    'plugin:jsx-a11y/recommended',
    'plugin:import/typescript',
  ],
  plugins: ['react', '@typescript-eslint', 'import'],
  parser: '@typescript-eslint/parser',
  parserOptions: {
    ecmaFeatures: { jsx: true },
    ecmaVersion: 'latest',
  },
  rules: {
    'no-warning-comments': [
      'warn',
      {
        terms: ['TODO', 'FIXME', 'XXX', 'BUG'],
        location: 'anywhere',
      },
    ],
    'import/order': [
      'error',
      {
        groups: ['builtin', 'external', 'internal', 'parent', 'sibling', 'index', 'object', 'type'],
        pathGroups: [
          {
            pattern: 'react*',
            group: 'external',
            position: 'before',
          },
        ],
        'newlines-between': 'always',
        alphabetize: {
          order: 'asc',
          caseInsensitive: true,
        },
      },
    ],
    'react/function-component-definition': [
      'error',
      {
        namedComponents: 'arrow-function',
        unnamedComponents: 'arrow-function',
      },
    ],
    'no-console': 'off',
    'react/jsx-filename-extension': ['warn', { extensions: ['.tsx', '.jsx'] }],
    'import/prefer-default-export': 'off',
    'no-plusplus': ['error', { allowForLoopAfterthoughts: true }],
    'react/require-default-props': 'off',
    'react/prop-types': 'off',
    'consistent-return': 'off',
    curly: ['error', 'all'],
    eqeqeq: ['error', 'smart'],
    '@typescript-eslint/naming-convention': [
      'error',
      { format: ['camelCase', 'UPPER_CASE'], selector: 'variable', leadingUnderscore: 'allow' },
      { format: ['camelCase'], selector: 'parameter', leadingUnderscore: 'allow' },
      { format: ['camelCase', 'PascalCase'], selector: 'function' },
      { format: ['PascalCase'], selector: 'interface' },
      { format: ['PascalCase'], selector: 'typeAlias' },
    ],
    '@typescript-eslint/array-type': ['error', { default: 'array' }],
    'no-unused-vars': ['error', { argsIgnorePattern: '^_', destructuredArrayIgnorePattern: '^_' }],
    'react/react-in-jsx-scope': 'off',
  },
  settings: {
    'import/resolver': {
      typescript: {},
    },
  },
};



Extends 목록의 설정들

plugin:jsx-a11y/recommended

  • 모듈
    • eslint-plugin-jsx-a11y
  • 설명
    • JSX를 정적으로 평가(static evaluation)하여 애플리케이션의 접근성 문제를 찾아주는 플러그인입니다.
    • alt-text 규칙을 통해 img 태그 등에 alternative text를 명시하지 않을 시 에러를 발생시켜, 사용자가 요소를 볼 수 없는 상황일 경우 대체할 정보를 표시할 수 있도록 합니다.
    • no-noninteractive-element-interactions룰을 통해 interactive element가 아닌 div 태그 등에 mouse나 keyboard event handler를 할당하지 못하도록 에러를 발생시킵니다.

plugin:import/typescript

  • 모듈
    • eslint-plugin-import
    • eslint-import-resolver-typescript
  • 설명
    • eslint-import-resolver-plugin은 eslint-plugin-import에 TypeScript 지원을 추가합니다.
    • .cts/.mts/.ts/.tsx/.d.cts/.d.mts/.d.ts 확장자를 가진 파일을 import/require 할 수 있습니다.
    • tsconfig.json에 정의된 paths를 사용할 수 있습니다.

plugin:@typescript-eslint/recommended

  • 모듈
    • typescript-eslint
    • @typescript-eslint/parser
  • 설명
    • ESLint, Pretter가 TypeScript를 지원할 수 있도록 하는 도구입니다.
    • TypeScript는 number, string, boolean 등으로 초기화 된 변수나 매개 변수에 명시적으로 유형을 선언하지 않아도 타입을 유추할 수 있습니다.

plugin:import/recommended

  • 모듈
    • eslint-plugin-import
  • 설명
    • 적절하게 import를 할 수 있도록 유효성을 검사하는 규칙을 가지고 있는 ESLint 플러그인입니다.
    • file path나 스펠링이 틀린 것도 잡아낼 수 있습니다.
    • no-extraneous-dependencies: 외부 패키지 사용을 금지하는 규칙입니다.

eslint:recommended

  • 모듈
    • eslint:recommended
  • 설명
    • ESLint 팀에서 best practice로 간주하는 규칙이 포함된 built-in configuration입니다.
    • no-const-assign: const variable에 재할당을 금지하는 규칙입니다.

plugin:react/recommended

  • 모듈
    • plugin:react/recommended
  • 설명
    • React에 특화된 ESLint 규칙입니다.
    • button-has-type: 명시적으로 type attribute를 쓰지 않고 button element를 사용하는 것을 금지하는 규칙입니다.

plugin:react/jsx-runtime

  • 모듈
    • plugin:react/recommended
  • 설명
    • React 17의 새로운 JSX transform을 사용하는 경우, 이 플러그인을 extends에 명시하여 관련 규칙을 비활성화해야 합니다.
    • react-in-jsx-scope: JSX를 사용할 때 React를 꼭 import 해와야 하는 규칙입니다.

plugin:react-hooks/recommended

  • 모듈
    • eslint-plugin-react-hooks
  • 설명
    • React Hook의 2가지 규칙을 적용하는 ESLint plugin입니다.
      1. 최상위 레벨에서 hook을 호출해야 합니다.
      2. React function(function components, custom hook)에서 hook을 호출해야 합니다.

plugin:prettier/recommended

  • 모듈
    • eslint-config-prettier
  • 설명
    • Prettier와의 충돌을 방지하기 위해 code formatting과 관련된 ESLint rule을 비활성화합니다.

airbnb

  • 모듈
    • eslint-config-airbnb
  • 설명
    • ECMAScript6+, React가 포함된 Airbnb의 ESLint rules에 대한 ESLint configurations입니다.
    • eslint, eslint-plugin-import, eslint-plugin-react, eslint-plugin-react-hooks, and eslint-plugin-jsx-a11y를 필요로 합니다.
    • 익명 함수를 사용해야 하는 경우(inline callback 등) 함수 선언문이 아닌 화살표 함수 표현식을 사용하도록 강제합니다.

plugin:storybook/recommended

  • 모듈
    • eslint-plugin-storybook
  • 설명
    • Storybook을 Best practice로 사용하기 위한 공식적인 ESLint plugin입니다.
    • storybook/default-exports: Story file에는 default export가 있어야 한다는 규칙입니다.



Rules 목록

RulesDescriptionReason
no-warning-comments설정에 명시된 특정한 단어를 포함하고 있는 주석에 대해 보고하는 규칙커밋하기 전에 ‘TODO’, ‘FIXME’, ‘XXX’, ‘BUG’ 주석에 있을 경우 보고 받아서 주석을 제거할 수 있게 이 규칙을 적용했습니다.
import/orderrequire나 import 문의 순서 컨벤션을 정하고 그것을 강제하는 규칙require나 import 문의 순서 컨벤션을 정하고 그것을 강제하는 규칙
react/function-component-definition함수 컴포넌트를 사용할 때 특정한 함수 타입을 적용하도록 도와주는 규칙컨벤션에서 함수를 arrow function을 사용해서 정의하기로 결정했기 때문에, 함수 컴포넌트 정의시 arrow function을 사용하도록 이 규칙을 적용했습니다.
no-consoleconsole의 사용을 금지하는 규칙console.log를 사용하여 에러를 확인하는 것은 git commit 전 확인하는데 유용하므로, console을 사용하기로 결정해서 이 규칙을 비활성화 했습니다.
react/jsx-filename-extensionJSX 문법 포함하는 파일이 .jsx 확장자를 사용하도록 권장하는 규칙jsx 확장자를 통해 파일에서 JSX 문법을 사용하는지 한번에 알아볼 수 있으므로 이 규칙을 적용했습니다.
import/prefer-default-exportexport하는 파일 내에서 default export를 사용하도록 권장하는 규칙default export를 사용하면 intellisense가 잘 작동하지 않아서 불편하기 때문에, default export를 사용하지 않기로 결정하여 이 규칙을 비활성화 했습니다.
no-plusplus단항 연산자 ++, —를 허용하지 않는 규칙단항 연산자는 자동 semi-colon(;) 삽입 대상이어서 공백의 차이로 인해 소스 코드의 의미 체계가 달라질 수 있으므로, 단항 연산자를 사용하지 않도록 이 규칙을 적용했습니다. 그러나 for 문에서의 단항 연산자는 semi-colon 없이 사용하므로, allowForLoopAfterthoughts 옵션을 통해 단항 연산자를 허용했습니다.
react/require-default-props컴포넌트의 props가 required 타입이 아닐 때 대응되는 defaultProps값을 설정하도록 강제하는 규칙프로젝트에서 TypeScript를 사용하기 때문에, defaultProps 값이 필요 없으므로 이 규칙을 비활성화 했습니다.
react/prop-types컴포넌트의 props에 대한 타입인 propTypes을 설정하도록 강제하는 규칙프로젝트에서 TypeScript를 사용하기 때문에, propTypes 값이 필요 없으므로 이 규칙을 비활성화 했습니다.
curly모든 block 문에 대해 일관적인 괄호({}) 스타일을 강제하는 규칙모든 block 문을 괄호로 감싸는 일관적인 스타일을 적용하여 코드의 가독성을 높이기 위해 이 규칙을 적용했습니다.
eqeqeqstrick equality operator(===, ≠=)를 사용하도록 강제하는 규칙타입 변환을 일으키는 eqaulity operator(==, ≠) 대신에 stict equality operator(===, ≠=)를 사용하는 것이 안전하기 때문에 이 규칙을 적용했습니다. smart 옵션을 사용하여 literal 값을 비교할 때, typeof 연산자의 반환값을 평가할 때, null과 비교할 때의 3가지 경우에 이 규칙이 적용되지 않도록 했습니다.
@typescript-eslint/naming-convention코드 전반에 네이밍 컨벤션을 강제하는 규칙기존에 논의한 네이밍 컨벤션을 강제함으로써 코드의 가독성이 좋아지므로 이 규칙을 적용했습니다.사용하지 않는 변수나 매개변수를 정의할 때 underscore(_)로 시작하는 이름을 붙이기 때문에, 변수와 매개변수에 leadingUnderscore 옵션을 사용했습니다.
@typescript-eslint/array-type배열 타입을 일관적으로 정의하도록 강제하는 규칙모든 배열 타입을 T[]의 형태로 정의함으로써 코드의 가독성이 좋아지므로 이 규칙을 적용했습니다.
no-unused-vars변수가 사용되지 않는 것을 허용하지 않는 규칙사용되지 않는 변수는 코드에서 자리를 차지하고 가독성을 헤치므로, 이러한 경우를 방지하기 위해 이 규칙을 적용했습니다. 사용하지 않는 인수나 구조 분해 할당 시 사용하지 않는 변수를 underscore(_)로 정의하기 때문에, argsIgnorePattern: ‘^_’ 과 destructredArrayIgnoerPattern : ‘^_' 옵션을 사용했습니다.
react/react-in-jsx-scopeJSX를 사용할 때 scope 내에 React가 있는지 확인하는 규칙React 17 버전 이후부터 새로운 JSX transfom에서 자동적으로 react/jsx-runtime 함수를 불러오기 때문에, 이 규칙을 비활성화 했습니다.
arrow-body-stylearrow function의 내부를 괄호로 감싸도록 강제하는 규칙arrow function의 내부를 항상 괄호로 감싸는 일관적인 스타일을 적용하여 코드의 가독성을 높이기 위해 이 규칙을 적용했습니다.
import/extensionssource path를 import할 때 파일 확장자의 사용 여부를 결정하는 규칙typescript resolver가 import 경로에서 파일 확장자의 생략을 허용하므로, import 경로에 파일 확장자를 사용하지 않도록 이 규칙을 적용했습니다. 추후에 이미지 파일 import 시 이미지 파일임을 구분하기 위해 특정 파일 확장자를 사용할 예정입니다.

0개의 댓글