ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • eslint-plugin-import 도입기
    Build/Lint 2023. 9. 2. 16:23

    ESLint와 Prettier을 통해 기본적인 코드 컨벤션을 잡아 사용하던 중에 import 구문에 대한 컨벤션 필요성을 느끼게 되었습니다. 개발자마다 import구문을 추가하는 방식과 순서가 다르다 보니 가독성이 많이 떨어졌기 때문입니다. 그래서 import 구문을 lint로 잡고자 eslint-plugin-import를 찾아 도입하게 되었습니다.

     

    eslint-plugin-import?

    eslint-plugin-import의 GitHub을 보면 다음과 같이 설명하고 있습니다. 

    This plugin intends to support linting of ES2015+ (ES6+) import/export syntax, and prevent issues with misspelling of file paths and import names.

    ES2015+ (ES6+)의 import/export 구문을 lint 해주며 잘못된 import name을 막아주는 플러그인


    ESLint 설정을 위해  eslint-plugin-import의 옵션을 살펴보겠습니다.

     

    import/order

    order의 옵션으로 import 구문에 대한 컨벤션을 설정합니다.


    1. groups

    order의 기준이 되는 타입 기준으로 import 구문들에 대한 grouping을 설정하며 타입들은 총 8가지가 있습니다.
    ['builtin', 'external', 'internal', 'parent', 'sibling', 'index', 'object', 'type']


    각 타입 별로 살펴보겠습니다.

    // 1. 노드의 빌트인 모듈들 (node 'builtin' modules)
    import fs from 'fs';
    import path from 'path';
    
    // 2. 외부 모듈들 ('external' modules)
    import _ from 'lodash';
    import chalk from 'chalk';
    
    // 3. 내부 모듈들 ('internal' modules)
    // => 만약 path나 웹팩의 내부 경로를 다르게 설정했을 경우(alias 지정)
    import foo from 'src/foo';
    
    // 4. 부모 디렉토리에서 가져온 모듈들 (modules from a 'parent' directory)
    import foo from '../foo';
    import qux from '../../foo/qux';
    
    // 5. 형제의 디렉토리나 같은 디렉토리에서 가져온 '형제' 모듈들 ('sibling' modules from the same or a sibling's directory)
    import bar from './bar';
    import baz from './bar/baz';
    
    // 6. 현재 디렉토리의 '인덱스' 파일 ('index' of the current directory)
    import main from './';
    
    // 7. '오브젝트' import (타입스크립트에서만 가능) ('object'-imports (only available in TypeScript))
    import log = console.log;
    
    // 8. '타입' import (타입스크립트에서만 가능) ('type' imports (only available in Flow and TypeScript))
    import type { Foo } from 'foo';

     

    groups에 대한 선언 방식은 string 또는 Array<string> 입니다.

    // 선언 예시
    // groups 내부의 순서에 따라 order
    [
        'builtin',
        ['sibling', 'parent'], // Array<string>의 경우 해당 타입들은 섞일 수 있음.
        'index',
        'object',
    ]

     

    2.pathGroups

    디렉토리 경로에 따라 groups에 대한 타입을 지정합니다.

    {
      'import/order': ['error', {
        'pathGroups': [
          {
            'pattern': '~/**',
            'group': 'external'
          }
        ]
      }]
    }

    pathGroups의 option은 총 4가지가 있습니다.

    • pattern(required, string): 매칭 되는 패턴.
    • patternOptions(optional, object): 매칭에 대한 옵션.
    • group(required, string): 매칭되는 그룹.
    • position(optional, string(’before’ | ‘after’)): 매칭되는 그룹의 앞 혹은 뒤에 위치할 것인지 설정.

     

    3. pathGroupsExcludedImportTypes

    pathGroups에서 정의되지 않은 import types을 정의하며 대부분 외부 import 구문을 처리할 때 사용합니다.

     

    4.newlines-between

    import group 간의 줄 띄움 설정으로 option은 총 4가지가 있습니다.

    • ignore: import group간의 줄 간격에 대해 무시.
    • always: import group 간에 반드시 최소 한 줄의 줄 간격을 강제함.
    • always-and-inside-groups: always와 같으나 import group 안에서 줄 간격이 허용.
    • never: import 구문 전체 영역에서 줄간격이 허용 안됨.

     

    eslint-plugin-import 적용 예시

    /src/ 의 디렉토리 path alias를 @/로 적용한 프로젝트에서 import group 구분 case입니다.

    // .eslintrc.js
    ...
      plugins: ['import'],
      rules: {
        'import/order': [
          'error',
          {
            'newlines-between': 'always',
            groups: [
              'builtin',
              'external',
              'internal',
              'parent',
              'sibling',
              'index',
              'object',
              'type',
            ],
            pathGroups: [
              {
                pattern: 'react**',
                group: 'builtin',
                position: 'before',
              },
              {
                pattern: '@/api/**',
                group: 'internal',
                position: 'before',
              },
              {
                pattern: '@/store/**',
                group: 'internal',
                position: 'before',
              },
              {
                pattern: '@/components/**',
                group: 'internal',
                position: 'before',
              },
              {
                pattern: '@/router/**',
                group: 'internal',
                position: 'before',
              },
              {
                pattern: '@/styles/**',
                group: 'internal',
                position: 'before',
              },
            ],
            pathGroupsExcludedImportTypes: ['react**'],
          }
        ],
      },
    ...

     

    Issue 사항

    • 디렉토리의 alias를 @/를 사용해 경로를 찾는데 /src에 디렉토리에 추가가 될 때마다 pattern을 추가해야 하는 issue.
    • pattern 지정을 하나씩 다 하게 될 경우 줄 띄움이 너무 많이 발생하는 issue.


    팀 내에서 import 구문에 대한 적절한 코드 컨벤션을 정하여 grouping 옵션을 설정해서 사용해야 좀 더 깔끔하게 lint를 잡을 수 있지 않을까 싶습니다.

     


    참고 자료

    https://github.com/import-js/eslint-plugin-import

    https://github.com/import-js/eslint-plugin-import/blob/main/docs/rules/order.md

Designed by Tistory.