Next.js + ESLint Flat Config / Prettier / Stylistic / biome 기본 세팅 방법 (TypeScript, Prettier, Import Alias, Type Checking)

chaen·2025년 4월 27일

REACT / NEXT.js

목록 보기
21/22
post-thumbnail

💻 Next.js 프로젝트 생성

npx create-next-app@latest my-app --typescript
cd my-app

이번 게시글에선 Next.js의 프로젝트 Formatter를 아래 세 가지 방법으로 세팅하는 방법을 소개합니다.

  • Eslint + Prettier
  • Eslint + Stylistic
  • Biome

💻 Eslint Flag Config + Prettier

1. 필요한 패키지 설치

yarn add --dev eslint prettier eslint-plugin-prettier eslint-config-prettier eslint-plugin-simple-import-sort eslint-plugin-import typescript-eslint @next/eslint-plugin-next
npm install --save-dev eslint prettier eslint-plugin-prettier eslint-config-prettier eslint-plugin-simple-import-sort eslint-plugin-import typescript-eslint @next/eslint-plugin-next

2. eslint.config.mjs

Flat Config란?

  • .eslintrc.json 같은 "계층적 상속" 방식을 버리고, eslint.config.mjs 하나로 직접, 명시적으로 룰들을 배열로 작성하는 방식.
  • ESLint 8.21+부터 지원, 9.x에서는 Flat Config가 공식 기본이 된다.
  • Flat Config = 미래 표준
// ✅ 기본 ESLint 추천 규칙 세트
import eslint from '@eslint/js';

// ✅ TypeScript용 ESLint 플러그인과 추천 규칙 세트
import tseslint from 'typescript-eslint';

// ✅ import 정렬과 관련된 플러그인 (순서 정리, 그룹화 등)
import importPlugin from 'eslint-plugin-import';
import simpleImportSort from 'eslint-plugin-simple-import-sort';

// ✅ Next.js 전용 린트 규칙
import nextPlugin from '@next/eslint-plugin-next';

// ✅ Prettier 연동 플러그인 (ESLint 내에서 코드 스타일 포맷팅 규칙 적용)
import prettierPlugin from 'eslint-plugin-prettier';

/** @type {import('eslint').Linter.FlatConfig[]} */
const config = [
  {
    // 🔹 분석 제외할 디렉토리 설정
    // .next, node_modules 제외하고 src 하위만 포함
    ignores: ['.next/*', 'node_modules/*', '!src/**/*'],
    languageOptions: {
      ecmaVersion: 'latest', // 최신 ECMAScript 구문 허용
      sourceType: 'module', // ES 모듈 사용
    },
  },

  // 🔹 ESLint 기본 추천 규칙 (eslint:recommended)
  eslint.configs.recommended,

  // 🔹 TypeScript ESLint 추천 규칙 세트
  ...tseslint.configs.recommended,

  {
    plugins: {
      // 🔹 ESLint 플러그인 목록 등록
      '@typescript-eslint': tseslint.plugin, // TypeScript 린트 규칙
      import: importPlugin, // import 구조 관련 린트 규칙
      'simple-import-sort': simpleImportSort, // import 정렬 자동화
      prettier: prettierPlugin, // Prettier 스타일 규칙을 ESLint 오류로 처리
      next: nextPlugin, // Next.js 프로젝트에 특화된 린트 규칙
    },

    rules: {
      // ✅ 코드 스타일 관련 규칙 (Prettier 사용 시 필수)
      // - prettier가 정한 스타일 가이드라인을 지키지 않으면 ESLint 오류 발생
      'prettier/prettier': 'error',

      // ✅ Next.js 권장 규칙
      'next/no-img-element': 'warn', // <img> 대신 next/image 사용 권장
      'next/no-sync-scripts': 'warn', // <script src="..." /> 등 동기 script 로딩 금지
      'next/no-head-element': 'warn', // <head> 직접 작성 금지 (next/head 사용)

      // ✅ Import 순서 자동 정렬 (simple-import-sort 사용)
      'simple-import-sort/imports': [
        'error',
        {
          groups: [
            ['^react$'], // 리액트는 항상 최상단
            ['^next', '^@?\\w'], // Next.js, 외부 라이브러리
            ['^(@|components|utils|hooks)(/.*|$)'], // 절대경로 alias
            ['^.+\\.d\\.ts$', '^.*\\btype\\b'], // 타입 선언 관련 import
            ['^\\u0000'], // 가상 모듈(import '\0virtual:')
            ['^\\.\\.(?!/?$)', '^\\.\\./?$'], // 상대경로 상위 (../)
            ['^\\./(?=.*/)(?!/?$)', '^\\.(?!/?$)', '^\\./?$'], // 현재경로 내 import(./)
            ['^.+\\.?(css|scss)$'], // CSS 또는 SCSS import는 가장 아래
          ],
        },
      ],
      'simple-import-sort/exports': 'error', // export 순서 정렬

      // ✅ 함수 작성 스타일 최적화
      'arrow-body-style': ['error', 'as-needed'], // 불필요한 중괄호 제거 (return만 하는 함수)
      'prefer-arrow-callback': ['error'], // 콜백 함수는 function 대신 화살표 함수 사용

      // ✅ TypeScript 관련 규칙
      '@typescript-eslint/no-explicit-any': 'warn', // any 타입 사용을 경고
    },
  },
];

export default config;

파일 경로

my-app/
├── eslint.config.mjs 
├── .prettierrc
├── next.config.mjs
├── tsconfig.json
└── src/

📍 주의할 점 (Flat Config 전용 주의사항)

1. 기존 .eslintrc.json, .eslintrc.js 파일은 무조건 삭제해야 한다
둘 다 있으면 ESLint가 충돌하거나, .eslintrc만 적용될 수 있음.

2. CLI 실행할 때 eslint.config.mjs를 자동으로 읽게 한다
eslint.config.mjs는 루트에 있어야 하고, Eslint 8.21+ 이상 필요.

3. VS Code 설정

// .vscode/settings.json
{
  "editor.codeActionsOnSave": {
    "source.fixAll": "explicit",
    "source.fixAll.eslint": "explicit"
  },
  "editor.formatOnSave": true,

  "eslint.useFlatConfig": true, // 필수!
  "eslint.validate": [
    "javascript",
    "javascriptreact",
    "typescript",
    "typescriptreact"
  ],

  "typescript.enablePromptUseWorkspaceTsdk": true
}

3. Prettier

파일 위치: my-app/.prettierrc

{
  "semi": true,
  "singleQuote": true,
  "printWidth": 100,
  "tabWidth": 2,
  "trailingComma": "all",
  "arrowParens": "avoid"
}

4. package.json

{
  "scripts": {
    "lint": "eslint . --ext .js,.jsx,.ts,.tsx",
    "format": "prettier --write .",
    "type-check": "tsc --noEmit"
  }
}
  • npm run lint → 코드 품질 검사
  • npm run format → 코드 포맷팅

5. Type Checking 병렬 실행

  • ESLint는 문법 검사 담당
  • TypeScript 컴파일러(tsc)는 타입 검사 담당
  • 타입 체크는 별도 type-check 스크립트로 실행하거나, CI/CD에 추가 가능

6. Import Alias 세팅 (tsconfig.json)

{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@/components/*": ["src/components/*"],
      "@/lib/*": ["src/lib/*"]
    }
  }
}

이후 import는 이렇게 사용 가능:

import Button from '@/components/Button';

💻 Stylistic

Eslint 공식 문서에 따라, prettierstylistic, dprint를 code formatter로 사용할 것을 권고하였습니다.
한국어 번역 참고
아래로는 prettier 대신 stylistic을 사용하는 코드를 공유합니다.

stylistic을 사용할 때 장단점이 무엇일까?

  • 코드 포맷팅을 eslint 하나로 통일할 수 있다.
  • flat config에 최적화 되어있다.
  • prettier에 비해 대중적이지 않음
  • prettier보다 속도가 느린 편이다.

1. 의존성 설치

npm i --save-dev "@stylistic/eslint-plugin

prettier 관련 의존성은 제거합니다.

2. eslint.config.mjs

// eslint.config.mjs

import eslint from '@eslint/js'; // ESLint 기본 추천 규칙
import nextPlugin from '@next/eslint-plugin-next'; // Next.js 전용 규칙
import stylistic from '@stylistic/eslint-plugin'; // 스타일 관련 규칙 (Prettier 대체)
import tsPlugin from '@typescript-eslint/eslint-plugin'; // TypeScript용 ESLint 플러그인
import importPlugin from 'eslint-plugin-import'; // import 순서 및 구조 규칙
import simpleImportSort from 'eslint-plugin-simple-import-sort'; // import 자동 정렬
import tseslint from 'typescript-eslint'; // TS용 기본 recommended config

/** @type {import('eslint').Linter.FlatConfig[]} */
const config = [
  {
    // 무시할 경로 지정
    ignores: ['.next/*', 'node_modules/*', '!src/**/*'],
    languageOptions: {
      ecmaVersion: 'latest',
      sourceType: 'module',
    },
  },

  // ESLint와 TypeScript의 기본 추천 규칙 적용
  eslint.configs.recommended,
  ...tseslint.configs.recommended,

  {
    // 사용하는 플러그인 등록
    plugins: {
      '@typescript-eslint': tsPlugin,
      '@stylistic': stylistic,
      import: importPlugin,
      'simple-import-sort': simpleImportSort,
      next: nextPlugin,
    },

    rules: {
      // 📌 스타일 규칙 (Stylistic 사용, Prettier 대체)
      '@stylistic/array-bracket-spacing': ['error', 'never'], // 배열 괄호 사이 공백 제거
      '@stylistic/object-curly-spacing': ['error', 'always'], // 객체 중괄호 내부 공백 유지
      '@stylistic/comma-dangle': ['error', 'always-multiline'], // 멀티라인에만 trailing comma 허용
      '@stylistic/semi': ['error', 'always'], // 세미콜론 필수
      '@stylistic/quotes': ['error', 'single'], // 작은 따옴표 사용

      // 📌 Next.js 권장 규칙
      'next/no-img-element': 'warn', // <img> 대신 <Image> 사용 권장
      'next/no-sync-scripts': 'warn', // 동기 스크립트 사용 경고
      'next/no-head-element': 'warn', // <Head> 대신 next/head 사용 권장

      // 📌 기타 코드 정리
      'arrow-body-style': ['error', 'as-needed'], // 화살표 함수에서 불필요한 중괄호 제거
      'prefer-arrow-callback': ['error'], // 콜백에 화살표 함수 사용 권장

      // 📌 import 정렬 (기본 import 순서 구성)
      'simple-import-sort/imports': [
        'error',
        {
          groups: [
            ['^react$'], // 리액트 최상단
            ['^next', '^@?\\w'], // 외부 라이브러리
            ['^(@|components|utils|hooks)(/.*|$)'], // 절대경로 alias
            ['^.+\\.d\\.ts$', '^.*\\btype\\b'], // 타입 선언
            ['^\\u0000'], // null 문자 (예: virtual modules)
            ['^\\.\\.(?!/?$)', '^\\.\\./?$'], // 상대경로 ../
            ['^\\./(?=.*/)(?!/?$)', '^\\.(?!/?$)', '^\\./?$'], // 현재경로 ./
            ['^.+\\.?(css|scss)$'], // CSS/SCSS
          ],
        },
      ],
      'simple-import-sort/exports': 'error', // export 정렬

      // 📌 TypeScript 전용 규칙
      '@typescript-eslint/no-explicit-any': 'warn', // any 사용을 경고
    },
  },
];

export default config;

이하 package.json와 vscode/setting.json은 동일합니다.

💻 Biome

Biome은 ESLint + Prettier를 대체할 수 있는 차세대 도구로, 한 번의 설치로 Lint + Format를 모두 해결합니다.

Biome을 사용할 때 장단점이 무엇일까?

  • 하나의 도구로 포맷팅 + 린팅 모두 처리 (Prettier, ESLint 불필요)
  • Flat Config나 VSCode에서 별도 플러그인 설정 없이 사용 가능
  • Rust로 작성되어 빠름
  • .biome.json만으로 설정 일관성 유지
  • 일부 커뮤니티나 조직에서는 아직 생소함
  • 커스텀 플러그인/생태계는 ESLint보다 작음

1. 의존성 설치

npm i --save-dev "@biomejs/biome"

기본으로 깔린 eslint 관련 packages는 모두 제거합니다.

2. .vscode/setting.json

{
  "editor.defaultFormatter": "biomejs.biome",
  "[javascript]": {
    "editor.defaultFormatter": "biomejs.biome"
  },
  "[typescript]": {
    "editor.defaultFormatter": "biomejs.biome"
  },
  "[typescriptreact]": {
    "editor.defaultFormatter": "biomejs.biome"
  },
  "[javascriptreact]": {
    "editor.defaultFormatter": "biomejs.biome"
  },
  "[json]": {
    "editor.defaultFormatter": "biomejs.biome"
  },
  "editor.formatOnSave": true,
  "editor.codeActionsOnSave": {
    "source.organizeImports.biome": "explicit"
  }
}

저는 vscode 전역에서 prettier를 기본으로 사용하고 있기 때문에 formateOnSave 설정 시 biomeprettier의 이중 교정으로 에러가 나서 defaultFormatter를 해당 프로젝트 한정으로 설정해주었습니다.
참고로, vscode extension에서 biome을 다운 받아 사용하였습니다.

3. package.json

"scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start",
    "lint": "biome check .",
    "format": "biome format . --write"
  },

4. biome.json

{
  // 📌 Biome 스키마 버전 명시 (필수)
  "$schema": "https://biomejs.dev/schemas/1.9.4/schema.json",

  "vcs": {
    "enabled": true,               // Git 같은 버전관리 시스템과 연동 활성화
    "clientKind": "git",           // 사용할 VCS 종류: git
    "useIgnoreFile": true          // .gitignore, .biomeignore 등 무시 파일 적용
  },

  "files": {
    "ignoreUnknown": false,        // 미지정 확장자도 포맷/린트 시도
    "ignore": [                    // Biome이 무시할 파일/폴더 목록
      "dist/**/*",                // 빌드 결과물
      "node_modules/**/*",        // 외부 패키지
      ".pnp.loader.mjs",          // Yarn Plug'n'Play 환경 관련
      ".yarn/**/*",               // Yarn 관련 파일
      ".next/**/*"                // Next.js 빌드 결과물
    ]
  },

  "formatter": {
    "enabled": true,               // 코드 포매터 기능 활성화
    "attributePosition": "auto",   // HTML/JSX 속성 줄바꿈 자동 처리
    "indentStyle": "space",        // 공백 기반 들여쓰기
    "indentWidth": 2,              // 들여쓰기 너비: 2"lineWidth": 100,              // 최대 줄 길이 (Prettier의 printWidth와 동일)
    "lineEnding": "lf",            // 줄바꿈 문자: LF (Unix 스타일)
    "formatWithErrors": true       // 문법 오류가 있더라도 가능한 한 포맷 시도
  },

  "organizeImports": {
    "enabled": true                // import 정렬 기능 활성화 (자동 import 순서 정리)
  },

  "linter": {
    "enabled": true,               // 린터 기능 활성화
    "rules": {
      "recommended": true,         // Biome의 기본 추천 린트 규칙 사용
      "suspicious": {
        // 배열 index를 key로 쓰는 JSX 경고 비활성화 (상황에 따라 유용함)
        "noArrayIndexKey": "off"
      }
    }
  },

  "javascript": {
    "formatter": {
      "arrowParentheses": "always",     // 화살표 함수 매개변수에 항상 괄호 사용
      "bracketSameLine": false,         // JSX 닫는 태그는 줄 바꿈 (Prettier와 동일)
      "bracketSpacing": true,           // 객체 리터럴 중괄호에 공백 허용: { foo: 1 }
      "jsxQuoteStyle": "double",        // JSX에서는 double quote 사용: "<div>"
      "quoteProperties": "asNeeded",    // 객체 키에 따옴표는 필요할 때만
      "semicolons": "always",           // 세미콜론 항상 사용
      "trailingCommas": "all"           // 마지막 요소에도 항상 콤마
    }
  },

  "json": {
    "formatter": {
      "trailingCommas": "none"          // JSON에서는 trailing comma 제거
    }
  }
}

👀 프로젝트 적합성

다음은 ESLint + Prettier, ESLint + Stylistic, Biome을 사용하는 경우에 따라 어떤 프로젝트에 적합한지 조건별로 비교한 표입니다.

조건 \ 도구 조합ESLint + PrettierESLint + StylisticBiome
✅ 협업 중심널리 쓰여 익숙함, 팀 내 합의 용이상대적으로 비주류, 합의 필요새 도구이므로 팀 합의 필수
🧠 사용 난이도쉬움 (Prettier 자동 처리)ESLint 숙련도 필요설정은 간단하지만 개념은 새로움
⚙️ 설정 유연성보통 (Prettier는 설정 제한적)높음 (룰을 직접 제어 가능)포매팅/린팅을 통합적으로 구성
🚀 속도 / 성능보통보통빠름 (Rust 기반, 단일 도구)
🔧 설정 간결함약간 복잡 (두 도구 연동 필요)간결함 (Flat Config에 최적화됨)매우 간결 (하나의 biome.json으로 해결)
📦 도구 수2개 (eslint + prettier)2개 (eslint + stylistic)1개 (biome만 설치)
🏗️ 전통적인 프로젝트✅ 가장 익숙하고 안정적⚠️ 도입 시 팀 교육 필요⚠️ 생소함, 전통 환경에는 부적합할 수 있음
🆕 최신 기술 수용✅ 유지보수 잘 되는 안정된 조합✅ Flat Config 기반으로 최신 트렌드 대응 가능✅ All-in-One 도구로 미래 지향적
🛠️ CI/CD 적용설정 가능 (eslint + prettier 따로 실행)동일biome lint + format만 실행하면 됨
🖥️ VSCode 연동 편의성매우 좋음좋음기본 포맷터 설정 필요 (extension 설치 필요)

✅ 요약 추천

  • ESLint + Prettier: 팀이 크고 협업에 익숙한 전통적인 프로젝트
  • ESLint + Stylistic: Flat Config 기반의 커스터마이징이 필요한 현대형 프로젝트
  • Biome: 설정을 최소화하고 빠른 속도와 일관성을 원하는 최신 프로젝트 (소규모 팀, 개인, 신생 팀에 적합)

0개의 댓글