기존 Eslint 설정 파일 특성

// NestJS eslint config
// @ts-check
import eslint from '@eslint/js';
import eslintPluginPrettierRecommended from 'eslint-plugin-prettier/recommended';
import globals from 'globals';
import tseslint from 'typescript-eslint';

export default tseslint.config(
  {
    ignores: ['eslint.config.mjs'],
  },
  eslint.configs.recommended,
  ...tseslint.configs.recommendedTypeChecked,
  eslintPluginPrettierRecommended,
  {
    languageOptions: {
      globals: {
        ...globals.node,
        ...globals.jest,
      },
      sourceType: 'commonjs',
      parserOptions: {
        projectService: true,
        tsconfigRootDir: import.meta.dirname,
      },
    },
  },
  {
    rules: {
      '@typescript-eslint/no-explicit-any': 'off',
      '@typescript-eslint/no-floating-promises': 'warn',
      '@typescript-eslint/no-unsafe-argument': 'warn',
      "prettier/prettier": ["error", { endOfLine: "auto" }],
    },
  },
);

// Vite eslint config
import js from '@eslint/js'
import globals from 'globals'
import reactHooks from 'eslint-plugin-react-hooks'
import reactRefresh from 'eslint-plugin-react-refresh'
import tseslint from 'typescript-eslint'
import { defineConfig, globalIgnores } from 'eslint/config'

export default defineConfig([
  globalIgnores(['dist']),
  {
    files: ['**/*.{ts,tsx}'],
    extends: [
      js.configs.recommended,
      tseslint.configs.recommended,
      reactHooks.configs.flat.recommended,
      reactRefresh.configs.vite,
    ],
    languageOptions: {
      ecmaVersion: 2020,
      globals: globals.browser,
    },
  },
])

기본 제공되는 NestJS의 Eslint config 파일은 정적 분석을 중시하여, 타입 안정성과 런타임 안정성을 챙겼습니다. 다만 tslint로 불러오는 config 매서드의 경우 Deprecated로 더이상 권장하지 않는 방식입니다. 또한 성능 이슈가 있는 eslint-plugin-prettier 를 사용하고 있습니다.

Vite에서 제공하는 Eslint config의 경우 타입 정보 해석 없이 문법 및 구조 수준의 안정성만 챙기는 등, 런타입 오류를 예방하는 수준은 아닙니다.

좀 더 엄격한 TS 타입 규칙 적용

// root/eslint.config.mjs
// @ts-check
import eslint from '@eslint/js';
import tseslint from 'typescript-eslint';
import { defineConfig } from 'eslint/config';
import prettierConfig from 'eslint-config-prettier';

export default defineConfig(
    // JS 기본 추천 규칙
    eslint.configs.recommended,

    // TS 추천 (타입 기반 버그 방지)
    tseslint.configs.strictTypeChecked,

    // TS 스타일 추천 (일관된 코드 스타일)
    tseslint.configs.stylisticTypeChecked,

    // Formatter는 prettier로 적용
    prettierConfig,

    {
        files: ['**/*.ts', '**/*.tsx'],
        languageOptions: {
            parserOptions: {
                projectService: true,
                tsconfigRootDir: import.meta.dirname,
            },
        },
        // 무시할 경로
        ignores: ['dist/**', 'build/**', 'node_modules/**'],
    },

    // JS 파일은 타입체킹 규칙 비활성화
    { files: ['**/*.js'], extends: [tseslint.configs.disableTypeChecked] }
);

// fe/eslint.config.mjs
import base from '../eslint.config.mjs';
import { defineConfig } from 'eslint/config';
import globals from 'globals';
import reactHooks from 'eslint-plugin-react-hooks';
import reactRefresh from 'eslint-plugin-react-refresh';

export default defineConfig(...base, {
    files: ['**/*.{ts,tsx,js,jsx}'],
    extends: [
        reactHooks.configs['recommended-latest'],
        reactRefresh.configs.vite,
    ],
    languageOptions: {
        globals: { ...globals.browser },
        parserOptions: {
            projectService: true,
            tsconfigRootDir: import.meta.dirname,
        },
    },
});

// be/eslint.config.mjs
import base from '../eslint.config.mjs';
import { defineConfig } from 'eslint/config';
import globals from 'globals';

export default defineConfig(...base, {
    files: ['**/*.{ts,js}'],
    languageOptions: {
        globals: { ...globals.node },
        parserOptions: {
            projectService: true,
            tsconfigRootDir: import.meta.dirname,
        },
        rules: {
            '@typescript-eslint/no-explicit-any': 'off',
            '@typescript-eslint/no-floating-promises': 'warn',
            '@typescript-eslint/no-unsafe-argument': 'warn',
        },
    },
});

fe와 be에 개별적으로 더 엄격한 규칙을 적용할 수 있지만, 공통적으로 FE / BE가 동일한 코드 품질 기준을 공유할 수 있도록 설정했습니다. 모든 TS 코드에서 Promise 누락, unsafe 접근, nullable 오용과 같은 실수를 막을 수 있습니다. 또한, eslint-config-prettier의 prettierConfig를 적용해, 코드 스타일인 prettier의 전적인 책임으로 수정하여 성능 문제를 해소했습니다.

fe 및 be 각각에 개별적으로 적용해야 하는 설정값은 위 처럼 root의 eslint 설정을 추가해서 구성할 수 있습니다.