오늘은 eslint
에 대해서.. 정말 마지막으로 ESLint에 대해서 뿌셔보려고 합니다..!
그래도 이전에 @typescript-eslint
나 styleslint
등을 사용하면서 eslint
를 그래도 잘 사용하고 있다고 생각하고 있었는데요!
매번 사용을 할 때마다 계속 헷갈려하는 제 모습을 보고.. 이해를 못하고 있다고 생각이 들었습니다.
매번 적용을 하다보면 궁금해 하는 질문은 공통적이었습니다.
1. eslint-config
와 eslint-plugin
의 제대로 된 차이점은 무엇인가?
2. extends
, rule
, recommended
는 어떻게 해석하는가?
3. .eslintrc.js
파일은 어떤 방식으로 작성해야 하는가?
이렇게 적고보니.. 그냥 아예 lint
를 모르는 사람 같았습니다.. 🤦♂️
그래서 오늘은 다시 한 번 정리와 함께 더 이상의 이론은 공부하지 않겠다는 다짐으로 작성해보려고 합니다.
eslint
란?eslint-config-react-app
이라는 설정이 세팅되어 있다.정적 분석 도구
... 정말 많이 들었던 것 같습니다.. ㅎ
그리고 CRA 과정에서 eslint
관련된 라이브러리가 설치 된다는 것을 처음 알았습니다.
plugin
과 config
사실 eslint
를 사용하면서 가장 구분이 잘 되지 않고, 제대로 이해하기 어려웠던 부분이었습니다.
예를 들면 eslint-plugin-import
, eslint-config-prettier
, eslint-plugin-prettier
이런식으로 점점 추가해서 사용하라고 이야기하는데.. 추가하면 할수록 뭐가 뭔지 점점 헷갈리게 됩니다.
오늘은 확실하게 구분지어서 개념을 정리해보겠습니다. 🪓
eslint-plugin-*
짧게 플러그인이라고 하겠습니다.
플러그인 패키지는 룰을 정리한 패키지입니다.
예를 들면 eslint-plugin-react
라는 패키지는 리액트와 관련된 룰을 정의한 패키지입니다.
그렇다면 사용은 어떻게 할까요?
{
"plugins": ["react"]
}
eslint
설정을 할 때 흔히 보던 명칭입니다.
하지만 이렇게 작성하면 아무런 동작을 하지 않습니다.. 🤯
위의 의미는 "나는 이제 eslint-plugin-react
를 추가할거야!" 라고 하는 것과 동일합니다.
선언만하고 사용은 하지 않은 것이죠..
그러면 해당 패키지를 사용하려면 어떻게 해야할까요?
rules
에서 관리를 해줘야 합니다.
{
"plugins": ["react"],
"rules": {
"react/jsx-uses-react": error
}
}
이런식으로 해당 플러그인에 대한 룰(규칙)을 직접 입력해서 사용할 수 있습니다.
하지만 이렇게 플러그인을 사용하려면 매번 모든 플러그인의 룰을 알고 있어야하고, 활용할 줄 알아야합니다.
그리고 사용할 모든 룰을 직접 작성해줘야 합니다.
하나의 플러그인만 사용한다면 모를까 대부분의 사람들은 여러 플러그인을 설치해서 사용합니다.
사실상 모든 룰을 다 숙지한다는 것은 매우 어렵습니다.
그렇기 때문에 대부분의 플러그인은 자체 설정을 제공합니다.
그 자체 설정이 recommended
, strict
, all
과 같은 단어입니다.
해당 플러그인에서 제공하는 자체 설정을 사용하려면
{
"extends": ["plugin:react/recommended"]
}
위와 같은 코드로 작성해줘야 합니다.
흔히 보던 recommended
라는 키워드가 나왔습니다.
그렇다면 여기서 궁금증이 생길 수 있습니다.
자체 설정은 뭐고.. 좀전에 플러그인은 plugins
안에서 사용한다고 했는데.. 왜 extends
라는 영역에서 사용하는거지? 🤔
recommended
, all
, strict
등)자체 설정은 플러그인에서 룰에 대한 세팅을 해놓고 제공하는 것을 의미합니다.
그리고 해당 플러그인에서 제공하는 자체 설정의 경우에는 extends
영역에서 사용해야 합니다.
(하지만 왜 extends
영역에서 사용해야 되는지는.. 잘모르겠습니다.. 🥲)
// eslint-plugin-react/configs/recommended
'use strict';
const all = require('./all');
module.exports = Object.assign({}, all, {
languageOptions: all.languageOptions,
rules: {
'react/display-name': 2,
'react/jsx-key': 2,
'react/jsx-no-comment-textnodes': 2,
'react/jsx-no-duplicate-props': 2,
'react/jsx-no-target-blank': 2,
'react/jsx-no-undef': 2,
'react/jsx-uses-react': 2,
'react/jsx-uses-vars': 2,
'react/no-children-prop': 2,
'react/no-danger-with-children': 2,
'react/no-deprecated': 2,
'react/no-direct-mutation-state': 2,
'react/no-find-dom-node': 2,
'react/no-is-mounted': 2,
'react/no-render-return-value': 2,
'react/no-string-refs': 2,
'react/no-unescaped-entities': 2,
'react/no-unknown-property': 2,
'react/no-unsafe': 0,
'react/prop-types': 2,
'react/react-in-jsx-scope': 2,
'react/require-render-return': 2,
},
});
// this is so the `languageOptions` property won't be warned in the new config system
Object.defineProperty(module.exports, 'languageOptions', { enumerable: false });
위와같이 recommended
설정에는 직접 입력해야하는 룰들이 이미 입력이 되어있습니다.
그리고 이미 플러그인을 포함하고 있습니다.
하지만 plugins
이 안 보이실겁니다..!
그 이유는 all
자체 설정에서 플러그인을 포함하고 있고 해당 설정을 불러와서 다시 로직을 처리하기 때문에 plugins
영역을 recommended
설정에서 찾을 수 없습니다!
위의 코드를 보면 all
config 설정을 불러와서 Object.assign()
함수를 통해서 recommended
config 설정을 하는 모습을 볼 수 있습니다.
eslint-config-*
그렇다면 config 패키지는 무엇일까요? 😁
eslint-plugin
패키지들이나 룰들을 모아서 설정으로 만든 것이 eslint-config-*
패키지입니다.
eslint
에 관심이 있으시다면 많은 분들이 보셨던 eslint-config-airbnb
패키지를 예를 들 수 있습니다.
eslint-config-airbnb
패키지 내부에는 아래의 플러그인과 룰들을 조합해서 만든 설정 패키지입니다.
eslint
eslint-plugin-import
eslint-plugin-react
eslint-plugin-react-hooks
eslint-plugin-jsx-a11y
{
"extends": ["airbnb"]
}
사용할 때는 위와 같이 간단하게 사용할 수 있습니다.
parser
대부분 저처럼 eslint-plugin
이나 eslint-config
에 빠져서 지나치는 경우가 있습니다.
parser
는 무엇일까요?
코드를 분석하기 위한 파싱 툴입니다.
기본 값은 espree
입니다. 오늘은 parser
에 대해서는 자세하게 다루지는 않으려고 합니다..!
보통 자바스크립트에서는 @babel/eslint-parser
를 사용합니다.
타입스크립트에서는 @typescript-eslint/parser
를 사용합니다.
이번에 알게 된 사실인데 아래처럼 recommended
자체 설정을 사용하게 되면 @typescript-eslint/parser
가 자동적으로 포함됩니다..!
{
extends: ["plugin:@typescript-eslint/recommended"]
}
// typescript-eslint/packages/eslint-plugin/src/config/base.ts
export = {
parser: '@typescript-eslint/parser',
parserOptions: { sourceType: 'module' },
plugins: ['@typescript-eslint'],
};
순간 @typescript-eslint
조차도 plugin
이라고 생각했던.. 저를 반성하며.. 🤦♂️
@typescript-eslint
는 parser
도 있고 플러그인도 있고, 자체 설정도 포함되어 있었던 것이죠.. ㅎ
eslint-plugin
eslint
에 대한 룰만 정의한 패키지이다. (아직 사용한다고 말 안했다.)eslint
설정 파일의 plugins
, extends
영역에서 사용 가능하다.config
)을 사용하지 않는다면 개인적으로 룰을 숙지하고 설정해줘야 한다.extends
영역에서 plugin:패키지이름/config이름
으로 사용해야 한다.eslint-plugin
도 포함되어 있다.eslint-plugin-*
, @<scope>/eslint-plugin
, @<scope>/eslint-plugin-*
식으로 사용할 수 있다.eslint-config
eslint-plugin
패키지들과 룰을 모아서 설정으로 만든 패키지이다.eslint
설정 파일들을 공유하기 위한 목적으로 만들어진다.eslint
설정 파일의 extends
영역에서 사용해야 한다.extends
영역에서 plugin:패키지이름/config이름
으로 사용해야 하는데 eslint-config
는 패키지 이름만 써주면 된다.eslint-config-*
, @<scope>/eslint-config
, @<scope>/eslint-config-*
식으로 사용할 수 있다.자신만의 규칙도 만들고 설정도 만들고 싶다면 eslint-plugin
을 사용하거나 만드는 것을 추천합니다. 하지만 airbnb
처럼 기존의 설정들을 모아서 공유하려는 목적이 강하다면 eslint-config
를 사용하거나 만드는 것을 추천합니다.
다양한 eslint-plugin
이나 eslint-config
패키지들에 관심을 가지면서 이렇게 정리를 해보게 되었습니다.
알고 쓰는 것과 모르고 쓰는 것의 차이는 크다고 생각합니다.
앞으로는 과거보다는 더 잘 알고 쓴다는 생각에 조금 더 뿌듯하긴 합니다. 😎
그리고 사용하다보니 불편한 점도 있었고, 커스텀해보고 싶다는 생각도 들었습니다.
시간이 될 때 개인적으로 eslint-plugin
, eslint-config
패키지 하나씩 만들어 보려고 합니다.
개인적으로 프로젝트 만들때마다 설정하는 것도 귀찮기도하고.. 회사에서 협업용으로 하나 만들어서 가져가보려고 합니다!