본문 바로가기
개발개발/Date-project

[date] turborepo config 설정하기 - eslint

by yelimu 2025. 3. 5.

오늘 할당량을 아래와 같이 잡았다. 

  • eslint config ➡️
  • tsconfig 설정
  • pnpm-workspace.yaml
  • package.json의 script 설정
  • turbo.json 셋업

eslint config 먼저 세팅 해보자  ~ 


1. eslint config

turborepo 로 만든 mono repo 폴더 구조 안에 eslint.config.js 파일이 왜이렇게 많은가요.? 

폴더 구조

┌ apps 하위 각 앱마다 eslint.config.js가 있고, 

└ packages 에는 eslint-config 폴더(@repo/eslint-config), ui/eslint.config.js가 있다.

 

결론부터 정리하면 

 

├ packages/eslint-config/base.js 

    모든 프로젝트와 앱에서 공통으로 사용할 기본 ESLint 규칙 정의 

    다른 패키지에서 extends 로 적용할 수 있다.

 

packages/eslint-config/nextjs.js

    base.js를 상속하면서 + Next.js 프로젝트에 특화된 ESLint 설정

 

├ apps/*/eslint.config.js (삭제)

    공통 규칙(nextjs.js)을 상속받아 각 앱 또는 패키지에 대한 특정 ESLint 설정 정의 

 

├ esconfig.json (루트에 추가 ---> 프로젝트 전체에 적용) 

    공통 규칙(nextjs.js)을 상속받아 전체 앱 또는 패키지에 대한 특정 ESLint 설정 정의 

    나의 경우 루트 config파일을 추가하고 각 앱에서는 삭제했다. => 하위 디렉토리에 esconfig.js 없을 경우 그대로 상속


어디서 뭘 설정해야하는거지? 

일단 공식문서를 읽어보면서 뭐가 뭔지 정리하는 포스팅이다.

https://turbo.build/repo/docs/guides/tools/eslint

 

ESLint | Turborepo

Learn how to use ESLint in a monorepo.

turbo.build


packages/eslint-config/package.json 을 보면

  "name": "@repo/eslint-config",

으로 되어있다. 

 

@repo/eslint-config 안에 base.js , next.js , react-internal.js 파일이 들어있다.

이 파일들은 package.json에서 export 되어 => 다른 패키지에서 사용할 수 있다. 이때 위에서 본 name 속성으로 참조한다.

import baseConfig from "@repo/eslint-config/base";
import nextJsConfig from "@repo/eslint-config/next-js";
import reactInternalConfig from "@repo/eslint-config/react-internal";

 

next.js , react-internal.js 두 개의 파일은 base.js 를 확장하면서 추가적인 설정을 하는 파일이다. 

eslint-config의 package.json 이 레포지토리에 대한 모든 ESLint 의존성을 포함하므로 이를 사용하는 패키지에서 따로 의존성을 명시하지 않아도 된다. 

eslint-config/package.json

여기서 설정한대로 next-js 로 import 한다.


packages/eslint-config 에서 설정한 대로 apps/각각의 앱에 적용하려면

적용할 앱의 package.json 과 eslint.config.js (mjs)에 아래와 같이 import 해서 사용하면 된다. 

또는 루트(/)에 eslint.config.mjs 를 추가하면 별도의 설정 없이 루트 설정이 적용된다. => 나는 이 방법을 택했다.

workspace:*의 의미: 현재 레포지토리 내의 모든 패키지에서 @repo/eslint-config를 사용하도록 하며, 실제로는 @repo/eslint-config 패키지가 레포 내의 특정 경로에서 참조될 수 있도록 한다.

 

@repo/eslint-config / next-js 만 import 하여 사용한다. (base.js 를 확장한 파일이므로)

@repo/eslint-config /  react-internal-js 는 리액트 내부 프로젝트 에서 쓰라고 하네여.. 맞나.. 


package/ui/eslint.config.js 파일은 ui 패키지 내부에서만 적용이 된다. 


루트에 eslint.config.js 파일을 생성하면 전체적으로 적용이 된다. -> 다만 각 앱에서 오버라이드 할 수 있음

=>  루트  eslint.config.js에서 @repo/eslint-config 를 import 하기로! 

    & 각 앱/eslint.config.js 파일은 불필요하니 삭제한다

 

// @/package.json
{  
  ...
{
  "devDependencies": {
    "@repo/eslint-config": "workspace:*"
  }
}
}

 


@repo/eslint-config/base.jsnext.js 파일 살펴보기

turbo repo에서 세팅하면서 자동으로 추가된 파일 내용이다.

// base.js

import js from "@eslint/js";
import eslintConfigPrettier from "eslint-config-prettier";
import turboPlugin from "eslint-plugin-turbo";
import tseslint from "typescript-eslint";
import onlyWarn from "eslint-plugin-only-warn";

export const config = [
  js.configs.recommended,
  eslintConfigPrettier,
  ...tseslint.configs.recommended,
  {
    plugins: {
      turbo: turboPlugin,
    },
    rules: {
      "turbo/no-undeclared-env-vars": "warn",
    },
  },
  {
    plugins: {
      onlyWarn,
    },
  },
  {
    ignores: ["dist/**"],
  },
];

base.js

  • js.configs.recommended : ESLint에서 권장하는 기본 규칙을 포함하는 설정
  • eslint-config-prettier : Prettier와의 충돌을 방지하기 위한 ESLint 설정
  • typescript-eslint : TypeScript 코드에서 ESLint 규칙을 적용하기 위한 패키지에서 권장되는 규칙 설정
  • eslint-plugin-turbo : Turbo (배포 도구 또는 프레임워크) 관련 ESLint 플러그인
  • "turbo/no-undeclared-env-vars": "warn" 규칙은 사용되지 않은 환경 변수에 대해 경고를 발생시키는 규칙
  • eslint-plugin-only-warn : ESLint 규칙이 에러를 발생시키지 않고, 항상 경고(warn)로만 처리하도록 강제하는 플러그인
  • 빌드 또는 컴파일된 파일이 위치하는 dist 디렉토리는 검사하지 않음 
// next.js

import js from "@eslint/js";
import eslintConfigPrettier from "eslint-config-prettier";
import tseslint from "typescript-eslint";
import pluginReactHooks from "eslint-plugin-react-hooks";
import pluginReact from "eslint-plugin-react";
import globals from "globals";
import pluginNext from "@next/eslint-plugin-next";
import { config as baseConfig } from "./base.js";

export const nextJsConfig = [
  ...baseConfig,
  js.configs.recommended, // 중복-> 삭제
  eslintConfigPrettier, // 중복-> 삭제
  ...tseslint.configs.recommended, // 중복-> 삭제
  {
    ...pluginReact.configs.flat.recommended,
    languageOptions: {
      ...pluginReact.configs.flat.recommended.languageOptions,
      globals: {
        ...globals.serviceworker,
      },
    },
  },
  {
    plugins: {
      "@next/next": pluginNext,
    },
    rules: {
      ...pluginNext.configs.recommended.rules,
      ...pluginNext.configs["core-web-vitals"].rules,
    },
  },
  {
    plugins: {
      "react-hooks": pluginReactHooks,
    },
    settings: { react: { version: "detect" } },
    rules: {
      ...pluginReactHooks.configs.recommended.rules,
      // React scope no longer necessary with new JSX transform.
      "react/react-in-jsx-scope": "off",
    },
  },
];

next.js ➤ base.js 를 확장해 React, Next.js 관련 규칙이 추가된 파일이다. 

 

base.js와 중복된 부분은 삭제했다.

js.configs.recommended,
eslintConfigPrettier,
...tseslint.configs.recommended,

https://eslint.org/docs/latest/rules/

 

Rules Reference - ESLint - Pluggable JavaScript Linter

A pluggable and configurable linter tool for identifying and reporting on patterns in JavaScript. Maintain your code quality with ease.

eslint.org

✅되어있는 옵션들이  recommended 에 포함된다


 

기본 설정된 rules 외에 추가하고 싶다면 

  • 공통 eslint 규칙은 base.js
  • react,next.js 관련 규칙은 next.js에 추가

마지막으로 prettier와 eslint가 충돌하지 않도록 하는 패키지 추가

// 루트 package.json
"devDependencies": {
  //...
    "eslint-config-prettier": "^8.5.0",
    "eslint-plugin-prettier": "^4.0.0"
  },
import prettierPlugin from "eslint-plugin-prettier";

export const config = [
...
  {
    plugins: {
      turbo: turboPlugin,
      prettier: prettierPlugin, // <---추가
    },
    rules: {
      "turbo/no-undeclared-env-vars": "warn",
      "prettier/prettier": "warn", // <---추가
    },
  },
];