eslint-plugin-import는 eslint plugin으로 import/export 구문의 Liting을 지원해주고 import 철자가 틀린 것을 찾거나 가져오기 경로를 보장해준다.
최근 새로운 팀원이 합류하고 여러 프로젝트의 import/export 구문의 코드를 작성할 때 규약을 정립하기 위해 해당 Plugin을 사용하기로 했다.
린트(Lint)나 린터(Linter)로 불리는 이 녀석은 컴퓨터 과학 용어로, 소스 코드 내의 프로그래밍 오류, 스타일 오류, 의심스러운 구조 등을 표시하는 데 사용되는 정적 코드 분석 도구이다.
일단, npm install eslint-plugin-import --save-dev 명령어를 활용하여 eslint-plugin-import 라이브러리를 설치한다.
이후 .eslintrc.{js|yaml|json}에 코드를 추가해준다.
여기서는 .eslintrc.js를 기준으로 설명한다!
module.exports = {
//...
plugins: ['import'] // 'import' 추가
// ...
rules: {
'import/order': [
'error',
{
groups: [],
pathGroups: [
{
pattern: 'SRC/**',
group: 'unknown',
position: 'before',
},
{
pattern: '**/*.{service,controller,module}',
group: 'unknown',
position: 'before',
},
{
pattern: '**/*.{type,interface,const,enum}',
group: 'unknown',
position: 'before',
},
{
pattern: '**/*.dto',
group: 'unknown',
position: 'before',
},
//...
],
pathGroupsExcludedImportTypes: [],
'newlines-between': 'always',
alphabetize: {
order: 'asc',
caseInsensitive: true,
},
},
],
}
}
위는 .eslintrc.js에 들어가는 import/order의 예시 코드이다.
각의 property들이 어떤 역할을 하는 지 살펴보자
groups 프로퍼티는 문자열 배열 값을 가져야 한다.
허용되는 문자열은 ["buildtin", "external", "internal", "unknown", "parent", "sibling", "index", "object", "type"]으로 9개의 문자열만 들어올 수 있다.
9개의 문자열이 전부 들어올 필요는 없으며 생략된 유형은 암시적으로 마지막 요소로 함께 그룹화가 이루어진다.
{
groups: [
'builtin', // 빌트인 모듈
['parent', 'sibling'], // 상대 경로(부모 경로, 자식 경로)
'index', // index.{js|ts} 파일
// Then the rest: internal and external type
]
}
아래와 같은 예시 코드로 활용할 수 있다.
"import/order": [
"error",
{
"groups": [
"index",
"sibling",
"parent",
"internal",
"external",
"builtin",
"object",
"type"
]
}
]
pathGroups는 기본적으로 제공되는 그룹화가 아닌 경로별로 추가로 그룹화가 가능하게하는 프로퍼티이다.
{
pathGroups: [
{
pattern: string, // 이 그룹에 포함될 최소한의 경로
patternOptions: object, // 최소 일치 옵션: default {nocomment: true}
group: string, // groups 내의 그룹을 선택 <- 해당 그룹의 기준으로 위치가 결정된다.
position: string, // group에 정의된 그룹을 기준으로 앞/뒤에 경로한다.
// 제공되지 않으면 같은 위치에 그룹화 된다.
}
]
}
{
pattern: 'SRC/**', // SRC로 시작하는 모든 경로 ex)SRC/api/... SRC/libs/...
group: 'unknown', // 기준 그룹: unknown
position: 'before', // unknown 그룹 앞에 그룹화
},
import 그룹 간에 새 줄을 적용할지의 여부를 결정하는 프로퍼티입니다.
import 그룹 내 순서를 알파벳순으로 정렬하도록 한다.
📝 더 자세한 설명은 eslint-plugin-import /docs/rules/order.md를 참고하자!
{
"compilerOptions": {
"paths": {
"app/*": ["./src/app/*"],
"config/*": ["./src/app/_config/*"],
"environment/*": ["./src/environments/*"],
"shared/*": ["./src/app/_shared/*"],
"helpers/*": ["./src/helpers/*"],
"tests/*": ["./src/tests/*"]
},
}
😀 만약 위와 같이 타입스크립트의 경로 매핑 기능을 사용하고 있다면, 절대 경로 그룹마다 새 줄 추가를 하고 싶을 수 있다.
하지만, 아래와 같이 추가로 그룹화를 해주더라도 각 매핑 경로마다 새 줄 추가가 되지 않고, group에 선언된 특정 그룹에 속해 함께 매핑해 버린다.
pathGroups: [
{
pattern: 'app/**',
group: 'unknown',
position: 'before',
},
{
pattern: 'config/**',
group: 'unknown',
position: 'before',
},
{
pattern: 'environment/**',
group: 'unknown',
position: 'before',
},
'newlines-between': 'always',
eslint-plugin-import Resolvers 탭을 보면 이유가 나와 있다.
모듈 번들러의 출현과 모듈 구문 사양으로 module에서 필요한 기능을 가져 올 때 모듈 뒤에 있는 파일의 위치가 명확하지 않는다고 한다.
v0.10 버전까지는 resolve 플러그 인을 직접 구현하여 사용했지만 웹팩과 타입스크립트의 import 경로 별칭 체계들이 Node가 허용하지 않는 기능들이 있어 두 가지 모두를 지원하기 위해 v0.11부터는 리졸버를 도입했다고 한다.
🔥 이를 해결하기 위해 typescript resolver를 활용하여 타입스크립트에서 제공하는 경로 별칭들도 그룹화 해보자
아래 패키지가 없다면 다운로드 해주자!
1. @typescript-eslint/parser
2. typescript-eslint/eslint-plugin
3. eslint-import-resolver-typescript
4. eslint-plugin-import
1, 2번 라이브러리는 타입스크립트 lint를 더 잘 사용하게 해주는 라이브러리이다. 해당 링크를 참조하자
실제로 경로 resolver를 활용하기 위해서는eslint-import-resolver-typescript가 필요하다.
추가로 아래와 같이 eslint settings 구문을 추가해 주면 정상적으로 해당 경로 별칭에 대해서도 그룹화가 진행되는 것을 확인할 수 있다!!
// .eslintrc.js
settings: {
'import/resolver': { // import 문을 사용 할 때 어떻게 찾을 건지에 대한 설정
typescript: {
alwaysTryTypes: true, // 타입 정의 파일(.d.ts)을 찾는다.
project: './tsconfig.json', // tsconfig.json 파일의 경로
},
},
},
import 구문이 정리되니 무엇보다 보기가 좋아져서 기분이 좋았다 :)