ESLint, Prettier, TypeScript
ํ๋ก์ ํธ๋ฅผ ๋ง๋ค ๋๋ง๋ค ESLint, Prettier, TypeScript๋ถํฐ ์ค์ ํ๊ฒ ๋๋๋ฐ, ๋งค๋ฒ ๋ค๋ฅธ ์ค์ ์ ์ฐพ์๋ค๋๊ธฐ ํ๋ค์ด์ ๊ทธ๋ฅ ์ฌ๊ธฐ๋ค๊ฐ ์ ๋ฆฌํ๋ ค๊ณ ํ๋ค.
์ค์ ์ ํ์ฌ ์ฌ์ฉ๋๊ฐ ๋์ Next.js ๊ธฐ์ค์ผ๋ก ์ ๋ฆฌํ๋ค. ํจํค์ง ๋งค๋์ ๋ npm์ผ๋ก ํ๋, yarn์ด๋ ๋ญ๋ ์๊ด์ ์๋ค.
Dependencies
Prettier, ESLint
์ฐ์ Prettier, ESLint๋ถํฐ ๋ถํฐ ๊น์.
$ npm install -D prettier eslint eslint-config-prettier eslint-plugin-prettier
ESLint์ ๋ฆฐํธ๋ฅผ ์ค์ ํ๊ณ Prettier๋ ํฌ๋งคํ ์ ์ค์ ํ๋ ๊ฑฐ์ง๋ง, ๋ ์ค์ ๊ฐ ์ถฉ๋์ด ์๊ธธ ์ ์๋ค. ๋ฐ๋ผ์ eslint-config-prettier, eslint-plugin-prettier์ ์ค์นํ๋ค.
๊ทธ๋ฅ eslint, prettier, eslint-config-prettier, eslint-plugin-prettier๋ ๋จ์ง์ด๋ผ๊ณ ์๊ฐํ๊ณ ๊ฐ์ด ๊น์.
eslint-config-prettier - ESLint์์ Prettier์ ์ถฉ๋์ด ์๊ธธ ์ ์๋ ๊ท์น์ ์ ๊ฑฐํ๋ค.
// .eslintrc.js (๋๋ .json)
{
extends: [
// ...
"prettier" // ๋ง์ง๋ง์ ๋ฃ์.
]
}
eslint-plugin-prettier - ESLint์ Prettier ๊ท์น์ ์ถ๊ฐํด์ค๋ค.
๊ณต์ ๋ฌธ์์์ ์ถ์ฒํ๋ ์ต์
์ ๋ค์๊ณผ ๊ฐ๋ค. eslint-plugin-prettier๋ plugin:prettier/recommended
์ค์ ์ ํฌํจํ๊ณ ์๋๋ฐ, ์ด ์ค์ ์ eslint-plugin-prettier ๋ฟ ์๋๋ผ eslint-config-prettier ์ค์ ๊น์ง ํ๋ฒ์ ํด์ค๋ค. ์ฆ, ์ด์ ๋จ๊ณ์์ ํ๋ extends๋ ์์ ๋ ๋๋ค.
// .eslintrc.js
module.exports = {
plugins: ["prettier"],
rules: {
"prettier/prettier": "error"
},
extends: [
"plugin:prettier/recommended" // ์ถ์ฒ ์ต์
. ์ฌ์ฉํ๋ค๋ฉด extends ๋งจ ๋ง์ง๋ง์ ๋ฃ์ด์ผ ํ๋ค.
]
}
์ดํ์๋ ์ง์ .prettierrc
ํ์ผ์ ๋ง๋ค๋ฉด ๋๋ค.
TypeScript
ํ์ ์คํฌ๋ฆฝํธ ํ๋ก์ ํธ๋ฅผ ์ธ๊ฑฐ๋ฉด ๊น๋ฉด ๋๋ค.
$ npm install -D typescript
ํ์
์คํฌ๋ฆฝํธ๋ ์ค์ ์ ์ํด tsconfig.json
์ ์ด์ฉํ๋ค. ํ์
์คํฌ๋ฆฝํธ๋ ๋ค๋ฅธ ์ธ์ด์ ๋ฌ๋ฆฌ ํ๋ก์ ํธ์ ๋ฐ๋ผ ์ด๋ค ์ค์ ์ ๋๊ณ ์ผ์ ํ์
์ฒดํน์ ๋์จํ๊ฒ ํ๊ฑฐ๋ ๊ฐํ๊ฒ ํ๋ ๊ฒ์ด ๊ฐ๋ฅํ๋ค. ์ด๋ฐ ๋ด์ฉ์ด ๊ถ๊ธํ๋ค๋ฉด Effective TypeScript๋ฅผ ์ฝ์ด๋ณด๋ ๊ฒ์ ์ถ์ฒํ๋ค. ์ด ๋ธ๋ก๊ทธ์๋ ์ ๋ฆฌ๋์ด ์๋ค.
typescript-eslint
$ npm install @typescript-eslint/parser @typescript-eslint/eslint-plugin
ESLint์ TypeScript๋ฅผ ํจ๊ป ์ฌ์ฉํ ๊ฒ์ด๊ธฐ ๋๋ฌธ์ typescript์ ์ด์ด์ typescript-eslint๋ ์ค์นํ๋ค. (์ค์น ๋ฐฉ๋ฒ ๋ฐ ์ฉ๋)
@typescript-eslint/parser๋ ESLint ์ปค์คํ ํ์์ด๋ค. ํ์ ์คํฌ๋ฆฝํธ ์ฝ๋๋ฅผ ESLint์ ํธํ๋๋ ๋ ธ๋๋ก ํ์ฑํ๋ฉฐ ํ์ ์คํฌ๋ฆฝํ ํ๋ก๊ทธ๋จ์ ์ง์ํ๋ค.
์ด๋ ํ์
์คํฌ๋ฆฝํธ๊ฐ ์๋ฐ์คํฌ๋ฆฝํธ์๋ ๋ค๋ฅธ, ESLint์ ํธํ๋์ง ์๋ AST ์์์ ์ฌ์ฉํ๊ธฐ ๋๋ฌธ์ด๋ค. ํ์
์คํฌ๋ฆฝํธ ๋ฌธ๋ฒ์ ์๋ฐ์คํฌ๋ฆฝํธ์ superset์ด๋๊น(e.g., : number
).
@typescript-eslint/eslint-plugin๋ typescript-eslint์์ ์ ๊ณตํ๋ ๊ท์น๊ณผ ์ค์ ์ ESLint์์ ์ฌ์ฉํ๊ธฐ ์ํด ํ์ํ ํ๋ฌ๊ทธ์ธ์ด๋ค. ๋ง์ฐฌ๊ฐ์ง๋ก ๊น์์ผ ํ๋ค.
์ค๋ช ์ ๋ง์ณค์ผ๋ ์ด์ typescript-eslint์ ์ฌ์ฉํ๊ธฐ ์ํ config๋ ์ถ๊ฐํด์ค๋ค. ๊ณต์ ๋ฌธ์ ์ถ์ฒ ์ธํ ์ ๋ค์๊ณผ ๊ฐ๋ค.
// .eslintrc.js
module.exports = {
root: true,
parser: "@typescript-eslint/parser", // ์ปค์คํ
parser ์ค์
extends: ["eslint:recommended", "plugin:@typescript-eslint/recommended"],
plugins: ["@typescript-eslint"]
}
๋ง์ง๋ง์ ๋ชจ๋ ์ค์ ์ ์ ๋ฆฌํด์ ํ๋ฒ์ ์ฝ๋๋ก ์๋ ค์คํ ๋ ๊ฑฑ์ ๋ง๋๋ก!
Next.js
์์กด์ฑ๋ถํฐ ์ค์นํ์.
$ npm i -D @types/node @types/react @types/react-dom eslint-config-next eslint-plugin-jsx-a11y eslint-plugin-react eslint-plugin-react-hooks
React๋ Next.js๋ฅผ ์ธ ๊ฒฝ์ฐ ESLint๊ฐ ๋ชจ๋ .jsx, .tsx ํ์ผ๋ง๋ค import React
๋ฅผ ํ๋ผ๊ณ ์์ฐ์ฑ์น๋ ๋ชจ์ต์ ๋ณผ ์ ์๋ค.
'React' must be in scope when using JSX
์ด์ฐจํผ Next.js๋ฅผ ์ด๋ค๋ฉด React๊ฐ ๋ด์ฅ๋์ด ์์ผ๋ rule์ ์ถ๊ฐํ๋ค.
module.exports = {
rules: {
"react/react-in-jsx-scope": "off",
}
}
์ ๋ฆฌ
์ด์ ํ์ผ๋ณ๋ก ๋ด๊ฐ ์ฌ์ฉํ๋ ์ค์ ์ ์ ๋ฆฌํ๋ค.
ํฌ๋งคํ ์ ๊ฒฝ์ฐ ์ฌ๋๋ง๋ค ์๋ ์ทจํฅ์ด ๋ค๋ฅด๋ค. ๋ 2 spaces indentation์ semicolon์ ๋นผ๋ ๊ฒ์, trailing comma๋ ๋ฃ๋ ๊ฒ์ ์ ํธํ๋ค.
๊ทธ๋ฆฌ๊ณ C, Java, Rust ๋ฑ ๋ค๋ฅธ ์ธ์ด์์๋ ""
๊ฐ ๋ฌธ์์ด์ด๋ ๋ double quote("
)๋ก ํ๊ฒ ๋ค. ์ด์ฐจํผ Prettier ๋๋ฆฌ๋ฉด single quote('
) ์์์ double quote๋ก ๋ฐ๋๋ค.
// .prettierrc
{
"printWidth": 80,
"semi": false,
"singleQuote": false,
"trailingComma": "all",
"tabWidth": 2,
"bracketSpacing": true,
"endOfLine": "lf",
"useTabs": false,
"arrowParens": "avoid"
}
ESLint ์ค์ ์ ์์์ ์ค์ ํ ๊ฑธ ํฉ์น ๊ฒฐ๊ณผ์ด๋ค. rules์๋ ๋ด๊ฐ ์ข์ํ๋ ์ค์ ์ ์ถ๊ฐํ๋ค.
// .eslintrc.js
module.exports = {
root: true,
plugins: [
"prettier",
"@typescript-eslint"
"react",
"react-hooks"
],
extends: [
"next/core-web-vitals",
"plugin:react/recommended",
"plugin:react-hooks/recommended",
"eslint:recommended",
"plugin:@typescript-eslint/recommended",
"plugin:prettier/recommended" // ๋ง์ง๋ง ์ ์ง
]
rules: {
"prettier/prettier": "error",
"react/jsx-uses-react": "error",
"react/jsx-uses-vars": "error",
"react/react-in-jsx-scope": "off",
"no-console": "warn",
"object-shorthand": "error"
}
}
TypeScript ์ค์ ์ด๋ค. ๊ธฐ๋ณธ ์ค์ ์ ๋ด๊ฐ ํ์ํ๋ค๊ณ ์๊ฐํ๋ ์ต์ ์ ์ถ๊ฐ๋ก ๋ฃ๋๋ค.
{
"compilerOptions": {
"target": "es2022",
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"noUncheckedIndexedAccess": true, // ์ถ๊ฐ
"strict": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "bundler",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve",
"incremental": true,
"plugins": [
{ "name": "next" }
],
"paths": {
"@/*": ["./src/*"]
}
},
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
"exclude": ["node_modules"]
}
์ดํ์ ํ์ํ๋ค๊ณ ์๊ฐ๋๋ ํ๋ฌ๊ทธ์ธ์ด ์๋ค๋ฉด ์ถ๊ฐ ์์ ์ด๋ค.
Last updated
Was this helpful?