ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 코딩 스타일 통일하기: 우아한 방식으로 시작하는 모노레포 구성하기(ESLint, Prettier 설정)
    React 2024. 7. 21. 19:10
    반응형

    배경

    최근 회사에서 신규 프로젝트를 시작하면서 React 레파지토리를 만들게 되었다. 하지만 내가 기존에 사용하던 ESLint 및 Prettier 규칙이 회사에서 사용하는 것과 달랐다. 같은 코드 스타일과 형식을 유지하기 위해 동일한 설정을 공유하고자 했지만, 기존 설정에는 주석이나 설명이 없어 왜 특정 규칙을 사용하고 있는지 이해하기 어려웠다. 무엇보다 이거 또 복붙해야하나(?) 평소에도 프론트엔드 개발자로 혼자 근무해서 극한의 효율을 갈구하고 있기에 관련 레퍼런스를 찾아보았다. 

     

    참고할 만한 자료를 찾던 중 우아한 기술블로그에서 바로 내 상황에 똑맞는 포스팅을 발견했다. 이 글에서는 기술블로그를 따라 공용 ESLint 및 Prettier 설정을 만들고 적용하는 과정을 공유하고자 한다.

     

    우아한 기술블로그의 영향

    나는 Airbnb의 eslint-config-airbnb 패키지를 사용하고있었는데, 포스팅 본문에 이런 글이있었다.

    이 글을 본 순간.. 심장을 관통하는 기분이었다. ㅎ 

    Airbnb 컨피그의 대안으로 Microsoft에서 관리하는 @rushstack/eslint-config 패키지를 사용하여 ESLint, Prettier를 설정하는 방법이 상세하게 작성되어있었다.


    🏗️ Structure

    📁 Monorepo: pnpm workspace로 관리
      📂 Packages:
        📂 eslint-config
          📁 (Main) @rushstack/eslint-config
        📁 prettier-config
        📂 example
          - Vite 기반
          - React 사용

     

     

    ⚙️ ESLint 설정

    1. packages/eslint-config/mixins/react.js
    React 프로젝트를 위한 ESLint 설정 파일이다. React 관련 플러그인을 포함하고 있으며, 다양한 규칙이 존재한다.

    module.exports = {
      plugins: ["react", "react-refresh", "jsx-a11y"],
      extends: [
        "plugin:react/recommended",
        "plugin:react-hooks/recommended",
        "plugin:react/jsx-runtime",
        "plugin:@tanstack/eslint-plugin-query/recommended",
      ],
      settings: {
        react: {
          version: "detect",
        },
      },
      overrides: [
        {
          files: ["**/__tests__/**/*.[jt]s?(x)", "**/?(*.)+(spec|test).[jt]s?(x)"],
          extends: ["plugin:testing-library/react"],
          rules: {
            "react-refresh/only-export-components": "off",
          },
        },
      ],
      rules: {
        "react-refresh/only-export-components": [
          "warn",
          { allowConstantExport: true },
        ],
        "jsx-a11y/alt-text": [
          "warn",
          {
            elements: ["img"],
          },
        ],
        "jsx-a11y/aria-props": "warn",
        "jsx-a11y/aria-proptypes": "warn",
        "jsx-a11y/aria-unsupported-elements": "warn",
        "jsx-a11y/role-has-required-aria-props": "warn",
        "jsx-a11y/role-supports-aria-props": "warn",
        "react/no-unknown-property": "off",
        "react/prop-types": "off",
      },
    };

     

    2. packages/eslint-config/index.js

    공통으로 사용할 ESLint 설정 파일이다. Rush Stack ESLint 설정을 기반으로 하며, 필요한 플러그인과 규칙을 정의되어있다.

    module.exports = {
      plugins: ["no-relative-import-paths"],
      extends: [
        "@rushstack/eslint-config/profile/web-app",
      ],
      rules: {
        "@typescript-eslint/explicit-function-return-type": "off",
      },
      settings: {},
    };

     

    3. packages/eslint-config/package.json

    ESLint 설정 패키지의 의존성과 메타 데이터관련 파일이다.

    {
      "name": "@org/eslint-config",
      "main": "index.js",
      "version": "1.0.0",
      "dependencies": {
        "@rushstack/eslint-config": "3.6.8",
        "@rushstack/eslint-patch": "1.10.1",
        "@tanstack/eslint-plugin-query": "4.38.0",
        "eslint-plugin-cypress": "2.15.1",
        "eslint-plugin-jsx-a11y": "6.8.0",
        "eslint-plugin-no-relative-import-paths": "1.5.3",
        "eslint-plugin-react": "7.34.1",
        "eslint-plugin-react-hooks": "4.6.0",
        "eslint-plugin-react-refresh": "0.4.6",
        "eslint-plugin-storybook": "0.8.0",
        "eslint-plugin-testing-library": "6.2.0"
      },
      "peerDependencies": {
        "eslint": ">= 8",
        "typescript": ">= 5"
      }
    }

     

    4. packages/eslint-config/patch.js

    Rush Stack의 ESLint 패치를 적용하기 위한 파일이다.

    require("@rushstack/eslint-patch/modern-module-resolution");

     

    ⚙️ Prettier 설정

    1. packages/prettier-config/index.js

    공통으로 사용할 Prettier 설정 파일이다.

    module.exports = {
      printWidth: 100,
      trailingComma: "all",
      tabWidth: 2,
      semi: true,
      singleQuote: true,
      bracketSpacing: true,
      arrowParens: "always",
      useTabs: false,
    };

     

    2. packages/prettier-config/package.json

    Prettier 설정 패키지의 의존성과 메타 데이터를 정의한 파일이다.

    {
      "name": "@org/prettier-config",
      "main": "index.js",
      "version": "1.0.0",
      "peerDependencies": {
        "prettier": ">= 3"
      }
    }

     

    ⚙️ 예제 프로젝트 설정

    우아한 기술 블로그에서 example 폴더를 만들어 공용 설정을 사용하는 예제를 참고해서 설정했다.

    1. example/.eslintrc.cjs

    require("@org/eslint-config/patch");
    
    module.exports = {
      env: { browser: true, es2020: true },
      extends: [
        "@org/eslint-config",
        "@org/eslint-config/mixins/react",
      ],
      settings: {
        react: {
          version: "18.2",
        },
      },
      parserOptions: {
        project: true,
        tsconfigRootDir: __dirname,
      },
    };

     

    2. example/package.json

    {
      "name": "example",
      "private": true,
      "version": "0.0.0",
      "type": "module",
      "scripts": {
        "dev": "vite",
        "build": "tsc && vite build",
        "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
        "preview": "vite preview",
        "prettier": "prettier --write \"**/*.{js,jsx,ts,tsx,css,html}\""
      },
      "dependencies": {
        "react": "18.2.0",
        "react-dom": "18.2.0"
      },
      "devDependencies": {
        "@org/eslint-config": "workspace:*",
        "@org/prettier-config": "workspace:*",
        "@types/react": "18.2.74",
        "@types/react-dom": "18.2.24",
        "@vitejs/plugin-react-swc": "3.6.0",
        "eslint": "8.57.0",
        "typescript": "5.4.4",
        "vite": "5.2.8"
      },
      "prettier": "@org/prettier-config"
    }

     

    ⚙️ 스크립트 실행

    공용 설정을 적용한 예제 프로젝트에서 ESLint와 Prettier를 실행한다.

     

    Linting

    pnpm --filter example lint

     

    Formatting

    pnpm example prettier

     

    결론

    이 과정을 통해 공용 ESLint 및 Prettier 설정을 만들고, 이를 신규 프로젝트에 적용함으로써 일관된 코드 스타일을 유지할 수 있게 되었다. 우아한 기술블로그에서 많은 영감을 받았으며, 주석을 통해 규칙의 목적을 명확히 하는 것이 특히 도움이 되었다. 앞으로도 이러한 설정을 통해 개발 생산성을 높이고, 팀 내 커뮤니케이션을 원활하게 할 수 있을 것으로 기대된다. (프론트엔드 개발자가 더 들어온다면..?)


     

    📚 참고 사이트

    https://techblog.woowahan.com/15903/

    반응형
Designed by Tistory.