ESLint V9 도입기

박요셉·2025년 6월 30일

Simple note

목록 보기
17/18

ESLint v9 플랫 구성(Flat Config) 가이드

ESLint v9에서 도입된 새로운 '플랫 구성(Flat Config)' 시스템에 관한 정리입니다.
이 문서는 Flat Config로 ESLint를 구현하며 겪었던 문제와, 관련 개념에 대해 설명하고 있습니다.

목차

ESLint v9 플랫 구성의 핵심

ESLint v9의 플랫 구성(eslint.config.js)은 기존의 .eslintrc.* 형식을 대체하는 새로운 접근 방식으로, 더 명확하고 유지보수하기 쉬운 린트 설정을 가능하게 합니다.

1. 평면화된 배열 구조

기존 방식이 중첩된 객체로 구성되었다면, 플랫 구성은 배열에 여러 구성 객체를 나열합니다:

// 이전 방식 (.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 규칙
    },
  },
];

2. 명시적 파일 패턴

각 구성 객체는 자신이 적용될 파일을 명시적으로 지정합니다:

// 모든 파일에 적용
{ },

// JavaScript 파일에만 적용
{ files: ['**/*.js'] },

// 테스트 파일에만 적용
{ files: ['**/*.test.js', '**/*.spec.js'] },

// src 디렉토리의 TypeScript 파일에만 적용
{ files: ['src/**/*.ts'] }

3. 직접적인 모듈 임포트

플러그인과 규칙을 문자열로 참조하는 대신 직접 모듈로 임포트합니다:

// 이전 방식
{
  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의 대응
];

4. 중첩이 아닌 병렬 구성

기존 방식에서는 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 규칙 */ } }
];

5. ESM(ES Modules) 사용

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,
    },
  },
];

장점

  1. 명확성: 각 설정이 어떤 파일에 적용되는지 명시적입니다.
  2. 유연성: 특정 파일 그룹에 대해 더 세밀하게 설정할 수 있습니다.
  3. 모듈화: 각 구성 요소가 독립적이어서 모듈화가 용이합니다.
  4. 타입스크립트 지원: ESM을 사용하여 타입스크립트와의 통합이 더 좋습니다.
  5. 성능 향상: 불필요한 설정 병합 과정이 줄어 성능이 향상됩니다.

문제와 해결 방법

1. 플러그인 로딩(호환성) 오류

문제:
일부 플러그인이나 구성은 아직 플랫 구성 형식과 완전히 호환되지 않을 수 있습니다. 이 경우 @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;

2. 레거시 extends 형식 오류

문제:

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'],
  }),
];

3. 라인 엔딩(EOL) 문제

문제:

Insert `␍` prettier/prettier

해결 방법:
.prettierrc 파일에서 endOfLine 설정:

{
  "endOfLine": "crlf"
}

결론

ESLint v9의 플랫 구성 시스템은 초기에 적응이 필요하지만, 설정의 명확성과 유지보수성을 크게 향상시킵니다.
그러나! 아직 호환되는 플러그인을 찾으며 확인해야하고, 안되는 것들도 많기 때문에 대형 프로젝트에 사용하기에는 아직은 시기상조라고 생각합니다.

profile
개발자 지망생

0개의 댓글