
npx create-next-app@latest my-app --typescript
cd my-app
이번 게시글에선 Next.js의 프로젝트 Formatter를 아래 세 가지 방법으로 세팅하는 방법을 소개합니다.
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
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/
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
}
파일 위치: my-app/.prettierrc
{
"semi": true,
"singleQuote": true,
"printWidth": 100,
"tabWidth": 2,
"trailingComma": "all",
"arrowParens": "avoid"
}
{
"scripts": {
"lint": "eslint . --ext .js,.jsx,.ts,.tsx",
"format": "prettier --write .",
"type-check": "tsc --noEmit"
}
}
npm run lint → 코드 품질 검사npm run format → 코드 포맷팅type-check 스크립트로 실행하거나, CI/CD에 추가 가능{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/components/*": ["src/components/*"],
"@/lib/*": ["src/lib/*"]
}
}
}
이후 import는 이렇게 사용 가능:
import Button from '@/components/Button';
Eslint 공식 문서에 따라, prettier 와 stylistic, dprint를 code formatter로 사용할 것을 권고하였습니다.
한국어 번역 참고
아래로는 prettier 대신 stylistic을 사용하는 코드를 공유합니다.
stylistic을 사용할 때 장단점이 무엇일까?
- 코드 포맷팅을 eslint 하나로 통일할 수 있다.
- flat config에 최적화 되어있다.
prettier에 비해 대중적이지 않음prettier보다 속도가 느린 편이다.
npm i --save-dev "@stylistic/eslint-plugin
prettier 관련 의존성은 제거합니다.
// 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은 ESLint + Prettier를 대체할 수 있는 차세대 도구로, 한 번의 설치로 Lint + Format를 모두 해결합니다.
Biome을 사용할 때 장단점이 무엇일까?
- 하나의 도구로 포맷팅 + 린팅 모두 처리 (Prettier, ESLint 불필요)
- Flat Config나 VSCode에서 별도 플러그인 설정 없이 사용 가능
- Rust로 작성되어 빠름
.biome.json만으로 설정 일관성 유지- 일부 커뮤니티나 조직에서는 아직 생소함
- 커스텀 플러그인/생태계는 ESLint보다 작음
npm i --save-dev "@biomejs/biome"
기본으로 깔린 eslint 관련 packages는 모두 제거합니다.
{
"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 설정 시 biome과 prettier의 이중 교정으로 에러가 나서 defaultFormatter를 해당 프로젝트 한정으로 설정해주었습니다.
참고로, vscode extension에서 biome을 다운 받아 사용하였습니다.
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "biome check .",
"format": "biome format . --write"
},
{
// 📌 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 + Prettier | ESLint + Stylistic | Biome |
|---|---|---|---|
| ✅ 협업 중심 | 널리 쓰여 익숙함, 팀 내 합의 용이 | 상대적으로 비주류, 합의 필요 | 새 도구이므로 팀 합의 필수 |
| 🧠 사용 난이도 | 쉬움 (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 설치 필요) |