π‘οΈ ESLint
μ΄ νλ‘μ νΈμμλ ESLintβλ₯Ό μ¬μ©νμ¬ μ½λ νμ§μ μ μ§νκ³ , μΌκ΄λ μ€νμΌμ μ μ©ν©λλ€. ESLint λ JavaScript λ° TypeScript μ½λμμ μ μ¬μ μΈ μ€λ₯λ₯Ό μ°Ύμλ΄κ³ , μ½λ μ€νμΌμ κ²μ¬νλ λꡬλ‘, νμ μ μ½λ μ€νμΌμ μΌκ΄μ±μ μ μ§νλ λ° ν° λμμ΄ λ©λλ€.
μ€ν λ°©λ²
λͺ λ Ήμ΄
ESLint κ²μ¬λ lint
CLIλ₯Ό μ¬μ©νμ¬ μνν©λλ€. λ€λ§, λͺ
λ Ήμ΄λ₯Ό μ€ννλ μμΉμ λ°λΌ μ€ν λ°©λ²μ΄ λ¬λΌμ§λλ€.
pnpm run lint
νλ‘μ νΈ λ£¨νΈμμ μ€νν κ²½μ°
λ£¨νΈ package.json
μ μ μλ lint
λͺ
λ Ήμ΄λ turbo task λ₯Ό μ€ννλλ‘ μ€μ λμ΄ μμ΅λλ€.
μ¦, λ£¨νΈ λλ ν 리μμ pnpm run lint
λͺ
λ Ήμ΄λ₯Ό μ€ννλ©΄, Turboκ° λͺ¨λ μν¬μ€νμ΄μ€μ λν΄ ESLint κ²μ¬λ₯Ό λ³λ ¬λ‘ μνν©λλ€.
{
"scripts": {
"lint": "turbo run lint"
// ... λ€λ₯Έ μ€ν¬λ¦½νΈλ€
}
}
κ°λ³ μν¬μ€νμ΄μ€μμ μ€νν κ²½μ°
κ° μν¬μ€νμ΄μ€λ³ package.json
νμΌμλ λͺ¨λ lint
μ€ν¬λ¦½νΈκ° μ μλμ΄ μμΌλ―λ‘, μ΄λ₯Ό μ§μ μ€νν μλ μμ΅λλ€.
λ€λ§ μ΄ κ²½μ°, turbo task λ₯Ό μ¬μ©νμ§ μκ³ , ν΄λΉ μν¬μ€νμ΄μ€μλ§ ESLint κ²μ¬λ₯Ό μννκ² λ©λλ€.
μ¦, turbo μμ μ 곡νλ λ³λ ¬ μ€ν λ° μΊμ± κΈ°λ₯μ νμ©νμ§ μκ³ μ§μ ESLint κ²μ¬λ₯Ό μννκ² λ©λλ€.
{
"scripts": {
"lint": "next lint --max-warnings 0"
// ... λ€λ₯Έ μ€ν¬λ¦½νΈλ€
}
}
Turbo Task
μμ μΈκΈν λλ‘, νλ‘μ νΈ λ£¨νΈ λλ ν 리μμ pnpm run lint
λͺ
λ Ήμ΄λ₯Ό μ€ννλ©΄ turbo task λ‘ μ μλ lint
μμ
μ΄ μ€νλ©λλ€.
lint
μμ
μ νλ‘μ νΈ λ£¨νΈ λλ ν 리μ μλ turbo.json
νμΌμ λ€μκ³Ό κ°μ΄ μ μλμ΄ μμ΅λλ€.
{
"tasks": {
"lint": {
"dependsOn": ["build", "^lint"]
}
// ... λ€λ₯Έ μμ
λ€
}
}
λΉλ μ€ν νμ
μ΄ νλ‘μ νΈμμλ ν¨ν€μ§λ€μ λΉλ λ°©μμ νΉμ±μ, ESLint κ²μ¬ μ μ λ°λμ λΉλλ₯Ό λ¨Όμ μ€νν΄μΌ ν©λλ€.
κ° ν¨ν€μ§λ€μ΄ μ€μ λΉλλ μ½λλ₯Ό λ²λ€μ ν¬ν¨μν€κΈ° λλ¬Έμ,
λΉλκ° μλ£λμ§ μμ μνμμλ ESLint κ²μ¬κ° μ¬λ°λ₯΄κ² μνλμ§ μμ μ μκΈ° λλ¬Έμ
λλ€.
λ°λΌμ, lint
μμ
μ dependsOn
νλμ build
μμ
μ μμ‘΄νλλ‘ μ€μ λμ΄ μμ΅λλ€.
μ΄ νλ‘μ νΈμμ μ±ννκ³ μλ λΉλ λ°©μμ λν λ³΄λ€ μμΈν λ΄μ©μ ν¨ν€μ§ > λΉλ λ°©μ
λ¬Έμλ₯Ό μ°Έκ³ ν΄ μ£ΌμΈμ.
ESLint Config
κ³΅ν΅ Config
κ³΅ν΅ ESLint Config λ€μ configs/eslint-config
λλ ν 리 μλμ μμΉνκ³ μμ΅λλ€.
μ΄ λλ ν 리μλ μ¬λ¬ κ°μ ESLint Config νμΌμ΄ μμΌλ©°, κ° νμΌμ νΉμ λͺ©μ μ λ§κ² μ€μ λμ΄ μμ΅λλ€.
base.js
: κΈ°λ³Έ ESLint μ€μ μ ν¬ν¨ν©λλ€. μ΄ μ€μ μ λͺ¨λ ESLint Config νμΌμ 곡ν΅μ μΌλ‘ μ μ©ν κΈ°λ³Έ κ·μΉλ€μ μ μν©λλ€.react-internal.js
: React λ₯Ό μ¬μ©νλ μν¬μ€νμ΄μ€μ μ μ©λλ ESLint μ€μ μ λλ€. React κ΄λ ¨ κ·μΉλ€μ ν¬ν¨νκ³ μμ΅λλ€.next.js
: Next.js λ₯Ό μ¬μ©νλ μν¬μ€νμ΄μ€μ μ μ©λλ ESLint μ€μ μ λλ€. Next.js κ΄λ ¨ κ·μΉλ€μ ν¬ν¨νκ³ μμ΅λλ€.
κ³΅ν΅ Config μμνκΈ°
κ° μν¬μ€νμ΄μ€μμλ κ³΅ν΅ ESLint Config λ₯Ό μμλ°μ κ·Έλλ‘ μ¬μ©νκ±°λ, μΆκ°μ μΈ κ·μΉμ μ μν μ μμ΅λλ€.
κ·Έλλ‘ μ¬μ©νκΈ°
apps/docs
μν¬μ€νμ΄μ€μμλ configs/eslint-config/next.js
νμΌμ μ μλ Next.js κ΄λ ¨ ESLint μ€μ μ κ·Έλλ‘ μ¬μ©νκ³ μμ΅λλ€.
import { nextJsConfig } from "@repo/eslint-config/next-js";
/** @type {import("eslint").Linter.Config} */
export default nextJsConfig;
νμ₯νκΈ°
apps/frontend-workshop
μν¬μ€νμ΄μ€μμλ configs/eslint-config/react-internal.js
νμΌμ νμ₯νμ¬ React κ΄λ ¨ κ·μΉμ μ μ©νκ³ μμ΅λλ€.
import reactRefresh from "eslint-plugin-react-refresh";
import tseslint from "typescript-eslint";
import { config } from "@repo/eslint-config/react-internal";
export default tseslint.config(
{ ignores: ["dist", "storybook-static"] },
{
extends: [...config],
files: ["**/*.{ts,tsx}"],
// ... μΆκ°μ μΈ κ·μΉλ€
},
);
ESLint Plugins
μ§μ μμ±νκΈ°
μ΄ νλ‘μ νΈμμλ ESLint νλ¬κ·ΈμΈμ μ§μ μμ±νμ¬ μ¬μ©ν μλ μμ΅λλ€.
- μ ESLint νλ¬κ·ΈμΈμ μμ±νλ €λ©΄
ν¨ν€μ§ > μ ν¨ν€μ§ μΆκ° > ESLint νλ¬κ·ΈμΈ
λ¬Έμλ₯Ό μ°Έκ³ ν΄ μ£ΌμΈμ. eslint-plugin-sample
ν¨ν€μ§μ λν μμΈν λ΄μ©μν¨ν€μ§ > μν ν¨ν€μ§ > eslint-plugin-samples
λ¬Έμλ₯Ό μ°Έκ³ ν΄ μ£ΌμΈμ.
ESLint Config μ μ μ©νκΈ°
μμ±ν ESLint κ·μΉμ ESLint Config μ μ μ©ν μ μμ΅λλ€.
μλ₯Ό λ€μ΄, configs/eslint-config/base.js
νμΌμ 보면, eslint-plugin-sample
ν¨ν€μ§μμ μμ±ν κ·μΉμ λ€μκ³Ό κ°μ΄ μ μ©νκ³ μμ΅λλ€.
λ§μ°¬κ°μ§λ‘ μλ‘μ΄ ESLint κ·μΉμ μμ±ν ν, ν΄λΉ κ·μΉμ μ΄μ κ°μ΄ ESLint Config μ μΆκ°νμ¬ μ¬μ©ν μ μμ΅λλ€.
μμ‘΄μ± μΆκ°νκΈ°
μμ±ν ESLint νλ¬κ·ΈμΈμ ESLint Config μ μ μ©νκΈ° μν΄μλ ν΄λΉ νλ¬κ·ΈμΈμ eslint-config
ν¨ν€μ§μ devDependencies
μ μΆκ°ν©λλ€.
{
// ... λ€λ₯Έ μ€μ λ€
"devDependencies": {
"@repo/eslint-plugin-sample": "workspace:*",
// ... λ€λ₯Έ devDependencies
},
}
μ΄μ΄μ μλμ λͺ
λ Ήμ΄λ₯Ό μ€ννμ¬ eslint-plugin-sample
ν¨ν€μ§λ₯Ό eslint-config
ν¨ν€μ§ μμ‘΄μ±μΌλ‘ μ€μΉν©λλ€.
pnpm install --filter @repo/eslint-config
Config μ μ μ©νκΈ°
μ΄μ eslint-config
ν¨ν€μ§μ ESLint Config νμΌμ μμ±ν ESLint νλ¬κ·ΈμΈμ μ μ©ν μ μμ΅λλ€.
μ΄ μμμμλ base.js
νμΌμ ESLint νλ¬κ·ΈμΈμ μ μ©νλ λ°©λ²μ 보μ¬μ£Όκ³ μμ§λ§,
λ€λ₯Έ ESLint Config νμΌ(e.g. next.js
, react-niternal.js
, β¦)μμλ λμΌν λ°©μμΌλ‘
ESLint νλ¬κ·ΈμΈμ μ μ©ν μ μμ΅λλ€.
// ... λ€λ₯Έ import λ¬Έλ€
import samplePlugin from "@repo/eslint-plugin-sample";
/**
* A shared ESLint configuration for the repository.
*
* @type {import("eslint").Linter.Config[]}
* */
export const config = [
// ... λ€λ₯Έ ESLint Config λ€
{
plugins: {
sample: samplePlugin,
},
rules: {
"sample/no-new-date": "warn", // eslint-plugin-sample ν¨ν€μ§μμ μμ±ν κ·μΉμ μ μ©
},
},
];