JS' 공부흔적
[ESLint] import 순서 자동 정렬하기 본문
올 상반기에 인턴으로 근무하면서 사내 코드 컨벤션에 의거하여 import 순서에 대해서 처음으로 신경 써봤다. 그러나 일일이 수작업으로 진행했던지라 가끔씩 지켜지지 않을 때도 있었고, 이런 경우 코드 리뷰 과정에서 수정하곤 했다.
이 부분에서 불편함을 느꼈기에 이번 사이드 프로젝트에서는 import 순서를 자동으로 정렬해 주는 Lint 설정을 직접 적용해 보자고 마음먹었다.
우선 eslint-plugin-import라는 라이브러리를 설치해야 한다. 이를 설치함으로써 import/export 구문에 대한 Lint를 지원한다.
문서를 확인해 보니 .eslintrc 파일에 추가 설정을 하라고 한다.
extends:
- eslint:recommended
- plugin:import/recommended
# alternatively, 'recommended' is the combination of these two rule sets:
- plugin:import/errors
- plugin:import/warnings
# or configure manually:
plugins:
- import
나는 plugins에 import를 추가했다.
이제 rules에 import/order 규칙을 추가하면 되는데, 나는 아래와 같이 사용했다.
"import/order": [
"error",
{
"groups": [
"builtin",
"external",
"unknown",
["sibling", "parent"]
],
"pathGroups": [
{
"pattern": "{react*,react*/*}",
"group": "external",
"position": "before"
}
],
"pathGroupsExcludedImportTypes": [],
"alphabetize": {
"order": "asc",
"caseInsensitive": true
},
"newlines-between": "always"
}
]
하나씩 살펴보자!
error
정해진 import rules에 어긋났을 때 어떻게 처리할 것인지를 정하는 옵션이다. off, warn, error 3가지가 있는데 나는 error로 처리하도록 했다.
groups
import문의 그룹을 정한다. 각 그룹은 공백으로 구분된다. builtin은 기본적으로 내장되어 있는 fs, path 등의 모듈, external은 외부 라이브러리, sibling은 ./로 표현할 수 있는 같은 디렉토리 내의 모듈, parent는 ../로 표현할 수 있는 부모 디렉토리 내의 모듈, unknown은 그룹화할 수 없는 것들이다. 특히 sibling과 parent는 internal로 합쳐질 수 있으며, 이밖에도 index, object, type이 있다.
내 프로젝트 내에서는 unknown으로 분류될 만한 것이 절대 경로 import 이외에는 없다고 생각하여 상대 경로 import보다 위에 위치하도록 설정했다. 또한 sibling과 parent는 그룹으로 묶어서 공백으로 구분되지 않도록 설정했다.
"groups": [
"builtin",
"external",
"unknown",
["sibling", "parent"]
]
pathGroups
import문의 패턴을 통해서 좀 더 세부적인 순서를 정할 수 있다.
{
"pattern": "{react*,react*/*}",
"group": "external",
"position": "before"
}
react로 시작하는 경로의 경우 external보다 앞에 위치하도록, 즉 어떤 외부 라이브러리보다도 위에 위치하도록 설정했다.
그러나 이렇게 설정했을 때 아래의 결과가 나타났다.
// 내가 의도한 것
import React from "react";
import ReactDOM from "react-dom";
import { useDispatch } from "react-redux";
import PropTypes from "prop-types";
// 실제 적용 결과
import PropTypes from "prop-types";
import React from "react";
import ReactDOM from "react-dom";
import { useDispatch } from "react-redux";
이처럼 pathGroups에서 정한 규칙이 적용되지 않는 것을 확인했고, 이를 이해하는 데에 상당히 오래 걸렸다. 이 에러의 해결법은 pathGroupsExcludedImportTypes 옵션을 사용하는 것이다.
pathGroupsExcludedImportTypes
pathGroups를 통해 설정한 규칙이 적용되지 않을 import type을 설정하는 옵션이다. 이 옵션의 기본값은 ["builtin", "external", "object"]이다. 즉, 이 옵션을 명시하지 않았을 때는 기본적으로 pathGroups에서 정한 규칙이 builtin, external, object에 적용되지 않는다는 뜻이다.
나는 pathGroups에서 react로 시작하는 경로가 external보다 앞에 위치하도록 설정했다. 그러나 external은 이 규칙이 적용되지 않기 때문에 위의 코드처럼 react로 시작하는 경로들도 똑같이 external 취급을 받는다.
따라서 이를 해결하기 위해서는 pathGroupsExcludedImportTypes 옵션에서 external을 제거해야 한다. 지금 상황에선 pathGroups 규칙이 하나밖에 없기 때문에 그냥 빈 배열로 설정했다.
"pathGroupsExcludedImportTypes": []
alphabetize
같은 그룹 내에서 알파벳 순서에 의한 정렬을 설정하는 옵션이다.
"alphabetize": {
"order": "asc",
"caseInsensitive": true
},
위처럼 설정하면 오름차순 정렬 및 대소문자 구분을 하지 않는다는 뜻이다.
newlines-between
그룹 사이에 공백 여부를 설정하는 옵션이다. always로 설정하면 항상 공백을 넣는다는 뜻이다.
"newlines-between": "always"
더 자세한 설정을 알고 싶다면 문서를 참고하길 바란다.
Lint 적용하기
package.json 파일에 아래와 같이 설정했다.
"scripts": {
"lint": "eslint 'src/**/*.{js,jsx}'",
"lint:fix": "eslint 'src/**/*.{js,jsx}' --fix",
},
# lint 검사만 진행
npm run lint
# lint 검사 후 자동 수정
npm run lint:fix