CRA 없이 프로젝트 구성하기 2 - ESLint Airbnb룰 설정 + Prettier + Path alias 설정하기

Seungrok Yoon (Lethe)·2023년 7월 25일
1
post-thumbnail

이번 시간에는 기존에 creat-react-app 없이 구성한 리액트 프로젝트(링크)에

  • ESLint
  • Prettier
  • 절대경로 alias

를 설정해볼 예정입니다. 하나씩 차근차근 해보도록 하겠습니다.

Airbnb ESLint 룰 설치하기

링크: https://www.npmjs.com/package/eslint-config-airbnb

위 링크에서 설치법을 살펴보면 해당 패키지는 여러개의 다른 패키지들을 peer-dependencies로 요구하고 있습니다.

regular dependencies vs peer dependencies

의존성에는 크게 regular dependenciespeer dependencies가 존재합니다.

regular dependencies는 표준 의존성 패키지들로서, 특정 패키지가 올바르게 동작하기 위해서 요구하는 패키지들입니다. regualr dependencies는 특정 패키지가 설치될 때 함께 설치됩니다.

반면 peer dependencies는 특정 패키지 내부에 포함되어있지 않습니다. 가령, A패키지 설치를 위해 peer dependencies로 B,C,D 패키지가 필요한 경우에는 B,C,D를 따로 설치해주어야 합니다. 패키지에 포함하고 있지 않기에, peer dependencies들은 특정 버전이 명시된다는 것도 특징 중 하나입니다. 각 패키지들은 독립적으로 관리되고 있을테니 올바른 동작을 위해서는 특정 버전에 종속되는 것이 당연하다는 생각이 들었습니다.

비유하자면 직영점이 아닌 편집샵 느낌이려나요?ㅎㅎ

설치

아무튼, 저는 yarn을 사용하고 있기에, 아래 명령어를 통해서 peer dependencies 패키지들을 함께 설치해주었습니다.

npx install-peerdeps --dev eslint-config-airbnb

eslint-config-airbnb의 peer dependencies에는

  • eslint
  • eslint-plugin-import
  • eslint-plugin-react
  • eslint-plugin-react-hooks
  • eslint-plugin-jsx-a11y
    이 존재하는데요, 그 중에서 eslint-plugin-import이녀석은 나중에 우리가 webpack과 jsconfig.js를 이용해 절대경로 설정 시에 ``함께 사용되는 녀석이니 기억합시다 ㅎㅎ.

Prettier 설치

yarn add prettier --dev

ESLint와 Prettier 충돌 제거

린터와 포매터 사이에 중복되는 규칙이 존재하여 충돌이 발생할 수 있습니다.

이 경우, prettier와 충돌하는 규칙을 린터에서 비활성화하는 eslint-config-prettier플러그인을 설치해 설정해주면 충돌을 방지할 수 있습니다.

Prettier 설정파일 구성하기

.prettierrc.json 파일을 생성하고 원하는 포매팅 규칙을 추가해줍니다. 저는 간단하게 이렇게만 적용했습니다.

{
  "trailingComma": "es5",
  "tabWidth": 2,
  "semi": true,
  "singleQuote": true
}

ESLint 설정파일 구성하기

.eslintrc.json 파일을 생성하고 다음과같이 작성해줍니다.

{
  "env": {
    "browser": true,
    "node": true,
    "es2021": true
  },
  "extends": ["eslint:recommended", "airbnb", "airbnb/hooks", "prettier"],
  "rules": {
    //"semi": ["error", "always"],
    //"quotes": ["error", "single"],
    "react/react-in-jsx-scope": "off" //^React17, this is not mandatory
  },
}

extends 프로퍼티에 어떤 룰을 적용할 것인지 명시해줍니다. 포인트는 배열의 뒤에 놓을수록 적용이 나중에 돼서, 이전 규칙들을 덮어씌우는 것이 가능합니다. "prettier"는 아까 설치한 eslint-config-prettier 의 룰입니다. 배열 가장 마지막에 추가해주어야 이전에 적용한 룰들 중 prettier와 충돌하는 룰들을 비활성화시켜줄 것입니다.

rules 프로퍼티에 추가적인 eslint 규칙을 넣을 수 있습니다. 현재 semi, quotes는 prettier에 명시한 규칙이기에 eslint규칙에서는 사용하지 않아도 됩니다. 주의할 점은, rules 에 정의된 규칙들은 가장 힘이 강력해서, extends에 적용된 규칙들을 이기고 최종적으로 적용이 됩니다.

Finally, run the CLI helper tool to find problems in the "rules" section of your .eslintrc.* file. (Remember, "rules" always “wins” over "extends"!)
https://github.com/prettier/eslint-config-prettier

"react/react-in-jsx-scope"규칙은 .jsx파일에 항상 React를 import해야하는 규칙입니다. 그렇지만 리액트 17버전 이상에서는 React를 반드시 import하지 않아도 되기 때문에 규칙을 꺼줬어요.

절대경로 설정하기

jsconfig.json 설정해주기

tsconfig.json의 js버전입니다. 타입스크립트를 적용하지 않은 JS프로젝트에 사용하면됩니다.

https://www.typescriptlang.org/docs/handbook/tsconfig-json.html

https://www.typescriptlang.org/tsconfig#compilerOptions

https://www.typescriptlang.org/tsconfig#paths

//jsconfig.json
{
  "compilerOptions": {
    "strict": false,
    "baseUrl": "src",
    "checkJs": true,
    "jsx": "react-jsx",
    "module": "ES6",
    "target": "ES5",
    "moduleResolution": "node",
    "paths": {
      "@Page/*": ["./pages/*"],
      "@Component/*": ["./components/*"]
    }
  },
  "include": ["src"],
  "exclude": ["node_modules"]
}

compilerOptions - jsx의 값은 "react", "react-jsx"가 올 수 있는데, React 17버전 이후로부터는 JSX가React.createElement가 아닌 _jsx로 변환되어 사용되니"react-jsx"로 설정해줍시다.

webpack.config.js

이제 webpack관련 파일에 설정을 추가해야 합니다.

아래 resolve 규칙을 추가해주세요!

...
 resolve: {
    extensions: ['.js', '.jsx'],
    alias: {
      '@Page': path.resolve(__dirname, './src/pages'),
      '@Component': path.resolve(__dirname, './src/components'),
    },
  },

주의할 점은 jsconfig.json에서는 특정 경로의 모듈을 이렇게 컴파일 해주세요~ 라는 의미에서 아래와같이 설정을 해야하고,

 "@Page/*": ["./pages/*"],

반면 webpack.config.js에서는 경로 자체에 대해 알려주는 것이라 아래처럼 설정을 해야합니다.

 '@Page': path.resolve(__dirname, './src/pages'),

eslint 설정파일에 웹팩관련 설정추가해주기

위 단계까지만 설정하면 eslint 에러가 날겁니다.

아래처럼요

import Home from '@Page/Home';
import Button from '@Component/Button';

export default function App() {
  return (
    <>
      <h1> Welcome to React from Scratch!</h1>
      <Button onClick={() => 1}>Click</Button>
      <Home />
    </>
  );
}
Unable to resolve path to module '@Page/Home'.

왜냐하면 ESLint는 webpack에서 절대경로 alias를 설정한 사실을 모르고 있거든요.

그리고 이 문제는 아까 airbnb 룰을 설치하는 과정에서 peer로 설치한eslint-plugin-importeslint-import-resolver-webpack가 해결해줍니다.

https://www.npmjs.com/package/eslint-plugin-import

https://www.npmjs.com/package/eslint-import-resolver-webpack

yarn add eslint-import-resolver-webpack --dev

eslint-import-resolver-webpack
은 ESLint가 Webpack에 정의한 alias와 모듈 resolution 설정을 이해할 수 있도록 도와주는 플러그인입니다.

우리는 Webpack으로 커스텀하게 alias를 설정했으니까 ESLint도 우리의 설정 내용을 알고 잘못된 에러를 발생시키지 않게 .eslintrc.json에 몇 줄 추가해주죠.

아래와 같이, "setting"->"import/resolver" 에 웹팩 환경설정파일을 연결해주세요.

이제 eslint도 import문에 사용된 절대경로를 알아차리고 에러를 내뿜지 않게될겁니다.

//.eslintrc.json
{
  "env": {
    "browser": true,
    "node": true,
    "es2021": true
  },
  "extends": ["eslint:recommended", "airbnb", "airbnb/hooks", "prettier"],
  "rules": {
    "react/react-in-jsx-scope": "off" //^React17, this is not mandatory
  },
  "settings": {
    "import/resolver": {
      "webpack": {
        "config": "./webpack.config.js"
      }
    }
  }
}
profile
안녕하세요 개발자 윤승록입니다. 내 성장을 가시적으로 기록하기 위해 블로그를 운영중입니다.

1개의 댓글

comment-user-thumbnail
2023년 7월 25일

잘 봤습니다. 좋은 글 감사합니다.

답글 달기