์žฌ๋ฐŒ๊ฒŒ ํ•ฉ์‹œ๋‹ค

๊ธฐ๋กํ•˜๊ธฐ, ๊ฐ€์‹œํ™”ํ•˜๊ธฐ

React

eslint ํ”Œ๋Ÿฌ๊ทธ์ธ ์ข…๋ฅ˜, ์ด ์ •๋ฆฌ

์€๋˜๋”” 2022. 10. 15. 15:04
ํ”„๋กœ์ ํŠธ ์Šค์บํด๋”ฉ ์ค‘ ์ˆ˜๋งŽ์€ eslint ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ๋งˆ์ฃผํ•˜๊ฒŒ ๋œ ๋‚˜..
์ผ์ผ์ด ๊ตฌ๊ธ€๋งํ•˜๋Š๋ผ ๊ณ ์ƒํ–ˆ์–ด์„œ, ํ˜น์‹œ ๋‚˜๊ฐ™์€ ์‚ฌ๋žŒ์ด ์žˆ์„๊นŒ ์ •๋ฆฌํ•ด๋ด„!๐Ÿ˜‡

ํŒจํ‚ค์ง€๋“ค์„ ๋ช‡ ๊ฐ€์ง€๋กœ ๋ถ„๋ฅ˜ํ•ด๋’€์œผ๋‹ˆ, ์•„๋ž˜ ๋ถ„๋ฅ˜๋กœ ๊ฐ ํŒจํ‚ค์ง€์˜ ๋Œ€๋žต์ ์ธ ์—ญํ• ๋“ค์„ ํŒŒ์•…ํ•˜์‹  ๋‹ค์Œ ์ž์„ธํ•œ ์„ค์น˜ ๊ณผ์ •์„ ๊ตฌ๊ธ€๋ง ํ•˜์‹œ๋ฉด ๋  ๋“ฏํ•ฉ๋‹ˆ๋‹ค!

prettier ์‚ฌ์šฉ ๊ด€๋ จ

prettier์™€ eslint๋ฅผ ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•œ ํŒจํ‚ค์ง€๋“ค์ž…๋‹ˆ๋‹ค. ์ฐธ๊ณ ๋กœ prettier๋Š” ์ฝ”๋“œ ํฌ๋งทํŒ…์ด ์ฃผ ๋ชฉ์ ์ด๊ณ , eslint๋Š” lint(์—๋Ÿฌ๋ฅผ ์žก์•„๋‚ด๋Š” ์ผ)๊ฐ€ ์ฃผ ๋ชฉ์ ์ด๊ธฐ ๋•Œ๋ฌธ์— ๋ณดํ†ต ๋‘ ๊ฐ€์ง€๋ฅผ ํ•จ๊ป˜ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. 

  • eslint-config-prettier
  • eslint-plugin-prettier

typescript ์‚ฌ์šฉ ๊ด€๋ จ

  • @typescript-eslint/eslint-plugin
  • @typescript-eslint/parser

react-native ๊ด€๋ จ

  • eslint-plugin-react-native
  • @react-native-community/eslint-config

airbnb style ์ ์šฉ ๊ด€๋ จ

๋งจ ์ฒซ ๋ฒˆ์งธ์— ์žˆ๋Š” ํŒจํ‚ค์ง€๋ฅผ ์œ„ํ•ด ์•„๋ž˜ ๋„ค ๊ฐœ๋ฅผ ์„ค์น˜ํ•˜์…”์•ผ ํ•ฉ๋‹ˆ๋‹ค!

  • eslint-config-airbnb
  • eslint-plugin-import
  • eslint-plugin-jsx-a11y
  • eslint-plugin-react
  • eslint-plugin-react-hooks

๊ทธ ์™ธ

  • eslint-import-resolver-typescript
  • eslint-plugin-simple-import-sort
    : import๋ฌธ์„ ํŠน์ • ๊ธฐ์ค€์— ๋”ฐ๋ผ ์ž๋™์ •๋ ฌํ•  ์ˆ˜ ์žˆ๋Š” ํ”Œ๋Ÿฌ๊ทธ์ธ์ž…๋‹ˆ๋‹ค. .eslintrc.js ํŒŒ์ผ์—์„œ ์ •๋ ฌ ์ˆœ์„œ๋ฅผ ์ปค์Šคํ„ฐ๋งˆ์ด์ง• ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • eslint-plugin-unused-imports
    : ์‚ฌ์šฉ๋˜์ง€ ์•Š์€ import๋ฌธ์„ ์ง€์›Œ์ฃผ๋Š” ํ”Œ๋Ÿฌ๊ทธ์ธ์ž…๋‹ˆ๋‹ค.

.eslintrc.js 

์œ„ ํŒจํ‚ค์ง€๋“ค์„ ์‚ฌ์šฉํ•˜๋ฉด์„œ ์ž‘์„ฑํ•œ .eslintrc.js ํŒŒ์ผ์„ ์ฒจ๋ถ€ํ•ฉ๋‹ˆ๋‹ค.

module.exports = {
  root: true,
  env: {
    es2021: true,
    node: true,
    jest: true,
    'react-native/react-native': true,
  },
  ignorePatterns: ['node_modules/', '.pnp.cjs', '.pnp.loader.mjs', '.yarn'],
  plugins: [
    '@typescript-eslint',
    'react',
    'react-native',
    'simple-import-sort',
    'unused-imports',
    'jest',
    'testing-library',
    'import',
  ],
  extends: [
    'airbnb',
    '@react-native-community',
    'eslint:recommended',
    'plugin:react/recommended',
    'plugin:@typescript-eslint/recommended',
  ],
  parser: '@typescript-eslint/parser',
  parserOptions: {
    ecmaFeatures: {
      jsx: true,
    },
    ecmaVersion: 12,
    sourceType: 'module',
  },
  overrides: [
    {
      files: ['*.ts', '*.tsx'],
      extends: ['plugin:@typescript-eslint/eslint-recommended', 'plugin:@typescript-eslint/recommended'],
      rules: {},
    },
  ],
  settings: {
    'import/resolver': {
      typescript: {},
    },
  },
  rules: {
    'prettier/prettier': ['error', { useTabs: false }],
    'import/extensions': [
      'error',
      'ignorePackages',
      {
        js: 'never',
        jsx: 'never',
        ts: 'never',
        tsx: 'never',
      },
    ],
    'react/jsx-filename-extension': [
      'warn',
      {
        extensions: ['.js', '.jsx', '.ts', '.tsx'],
      },
    ],
    'no-console': [
      'warn',
      {
        allow: ['warn', 'error'],
      },
    ],
    'import/no-unresolved': 'error',
    'react/react-in-jsx-scope': 'off',
    'no-use-before-define': 'off',
    '@typescript-eslint/no-use-before-define': 'off',
    'simple-import-sort/imports': [
      'error',
      {
        groups: [
          // Packages. `react` related packages come first.
          ['^react', '^@?\\w'],
          // Internal packages.
          ['@pay-stitches', '^(@/?$)(/.*|$)'],
          // Side effect imports.
          ['^\\u0000'],
          // Parent imports. Put `..` last.
          ['^\\.\\.(?!/?$)', '^\\.\\./?$'],
          // Other relative imports. Put same-folder imports and `.` last.
          ['^\\./(?=.*/)(?!/?$)', '^\\.(?!/?$)', '^\\./?$'],
        ],
      },
    ],
    'no-shadow': 'off',
    '@typescript-eslint/no-shadow': 'error',
    'simple-import-sort/exports': 'error',
    'import/first': 'error',
    'import/newline-after-import': 'error',
    'import/no-duplicates': 'error',
    '@typescript-eslint/no-unused-vars': 'off',
    'unused-imports/no-unused-imports': 'error',
    'unused-imports/no-unused-vars': [
      'error',
      {
        vars: 'all',
        varsIgnorePattern: '^_',
        args: 'after-used',
        argsIgnorePattern: '^_',
      },
    ],
    'react/require-default-props': 'off',
    'react/function-component-definition': [
      'warn',
      {
        namedComponents: 'arrow-function',
      },
    ],
    'react/jsx-props-no-spreading': ['warn', { exceptions: ['Button', 'AppComponent'] }],
    'import/order': 'off',
  },
};