ESLint v9에서 도입된 새로운 '플랫 구성(Flat Config)' 시스템에 관한 정리입니다.
이 문서는 Flat Config로 ESLint를 구현하며 겪었던 문제와, 관련 개념에 대해 설명하고 있습니다.
ESLint v9의 플랫 구성(eslint.config.js)은 기존의 .eslintrc.* 형식을 대체하는 새로운 접근 방식으로, 더 명확하고 유지보수하기 쉬운 린트 설정을 가능하게 합니다.
기존 방식이 중첩된 객체로 구성되었다면, 플랫 구성은 배열에 여러 구성 객체를 나열합니다:
// 이전 방식 (.eslintrc.js)
module.exports = {
extends: ['standard', 'plugin:react/recommended'],
rules: {
'no-console': 'warn',
},
overrides: [
{
files: ['*.ts'],
rules: {
// TypeScript 파일에만 적용되는 규칙
},
},
],
};
// 플랫 구성 (eslint.config.js)
export default [
// 모든 JavaScript 파일에 적용되는 설정
{
files: ['**/*.js'],
rules: {
'no-console': 'warn',
},
},
// 모든 TypeScript 파일에만 적용되는 별도 설정
{
files: ['**/*.ts'],
rules: {
// TypeScript 규칙
},
},
];
각 구성 객체는 자신이 적용될 파일을 명시적으로 지정합니다:
// 모든 파일에 적용
{ },
// JavaScript 파일에만 적용
{ files: ['**/*.js'] },
// 테스트 파일에만 적용
{ files: ['**/*.test.js', '**/*.spec.js'] },
// src 디렉토리의 TypeScript 파일에만 적용
{ files: ['src/**/*.ts'] }
플러그인과 규칙을 문자열로 참조하는 대신 직접 모듈로 임포트합니다:
// 이전 방식
{
plugins: ['react'],
extends: ['eslint:recommended', 'plugin:react/recommended']
}
// 플랫 구성
import js from '@eslint/js';
import reactPlugin from 'eslint-plugin-react';
export default [
js.configs.recommended, // eslint:recommended의 대응
reactPlugin.configs.recommended // plugin:react/recommended의 대응
];
기존 방식에서는 extends, overrides 등으로 설정을 중첩시켰지만, 플랫 구성에서는 모든 설정을 병렬로 나열합니다:
// 이전 방식
{
extends: ['eslint:recommended'],
rules: { /* 기본 규칙 */ },
overrides: [
{
files: ['*.ts'],
extends: ['plugin:@typescript-eslint/recommended'],
rules: { /* TypeScript 규칙 */ }
}
]
}
// 플랫 구성
import js from '@eslint/js';
import tseslint from 'typescript-eslint';
export default [
js.configs.recommended,
{ rules: { /* 기본 규칙 */ } },
{ files: ['**/*.ts'], ...tseslint.configs.recommended },
{ files: ['**/*.ts'], rules: { /* TypeScript 규칙 */ } }
];
CommonJS(module.exports) 대신 ESM(export default)을 사용합니다:
// 이전 방식
module.exports = {
// 설정...
};
// 플랫 구성
export default [
// 설정...
];
기존 .eslintrc.js:
module.exports = {
env: {
browser: true,
es2021: true,
},
extends: [
'eslint:recommended',
'plugin:react/recommended',
'plugin:@typescript-eslint/recommended',
],
parser: '@typescript-eslint/parser',
parserOptions: {
ecmaFeatures: {
jsx: true,
},
ecmaVersion: 12,
sourceType: 'module',
},
plugins: ['react', '@typescript-eslint'],
rules: {
'react/react-in-jsx-scope': 'off',
},
};
v9 플랫 구성 eslint.config.js:
import js from '@eslint/js';
import tseslint from 'typescript-eslint';
import reactPlugin from 'eslint-plugin-react';
import globals from 'globals';
export default [
// 기본 JavaScript 규칙
js.configs.recommended,
// TypeScript 규칙
...tseslint.configs.recommended,
// React 규칙
reactPlugin.configs.recommended,
// 기본 설정
{
languageOptions: {
ecmaVersion: 2021,
sourceType: 'module',
globals: {
...globals.browser,
},
parserOptions: {
ecmaFeatures: {
jsx: true,
},
},
},
// 모든 파일에 적용되는 규칙
rules: {
'react/react-in-jsx-scope': 'off',
},
},
// TypeScript 파일 설정
{
files: ['**/*.ts', '**/*.tsx'],
languageOptions: {
parser: tseslint.parser,
},
},
];
문제:
일부 플러그인이나 구성은 아직 플랫 구성 형식과 완전히 호환되지 않을 수 있습니다. 이 경우 @eslint/eslintrc 패키지의 FlatCompat 유틸리티를 사용합니다:
TailwindCss(4.1v 는 제공조차 안됩니다.), Tanstack query, react 등 플러그인은 아직 플랫 구성 형식과 완전히 호환되지 않을 수 있습니다.
A config object has a "plugins" key defined as an array of strings.
Flat config requires "plugins" to be an object.
해결 방법:
플러그인을 객체 형태로 지정:
// 잘못된 방법
{
plugins: ['react'];
}
// 올바른 방법
import reactPlugin from 'eslint-plugin-react';
{
plugins: {
react: reactPlugin;
}
}
// 또는 직접 구성 사용
reactPlugin.configs.recommended;
문제:
Error: ESLint configuration in eslint.config.js is invalid: cannot find plugin in config
해결 방법:
FlatCompat 유틸리티 사용:
import { FlatCompat } from '@eslint/eslintrc';
const compat = new FlatCompat();
export default [
...compat.config({
extends: ['plugin:react/recommended'],
}),
];
문제:
Insert `␍` prettier/prettier
해결 방법:
.prettierrc 파일에서 endOfLine 설정:
{
"endOfLine": "crlf"
}
ESLint v9의 플랫 구성 시스템은 초기에 적응이 필요하지만, 설정의 명확성과 유지보수성을 크게 향상시킵니다.
그러나! 아직 호환되는 플러그인을 찾으며 확인해야하고, 안되는 것들도 많기 때문에 대형 프로젝트에 사용하기에는 아직은 시기상조라고 생각합니다.