이 글은 ESLint 9.x(Flat Config)
를 기준으로 작성했습니다.
기존.eslintrc.*가 아니라
eslint.config.js/cjs파일을 사용합니다.
우아한테크코스 프리코스 8기 1주차
과제 유의사항을 살펴보는데
자바스크립트 코드 컨벤션을 지키면서 프로그래밍 한다.
- 기본적으로 JavaScript Style Guide를 원칙으로 한다.
요런 문구가 있어서 JavaScript Style Guide 를 공부하기 시작했습니다.
유의사항이 꽤 많기도 했고 (#1~#39)
자바스크립트 초심자이다 보니
숙지해도 계속 잊어버리더라구요 ㅜ.ㅜ
그래서 제가 개발을 할 때
자바스크립트 코드 컨벤션을 준수하면서
코딩을 할 수 있도록 도와주는 도구가 있는지
찾아보니 바로 ESLint 였습니다.
ESLint는 자바스크립트 코드의 문법, 스타일, 잠재적 오류를 자동으로 검사하고 수정해주는 정적 분석 도구다.
간단히 말하면,
"내가 짠 코드를 대신 검사해주는 자동 리뷰어"
라고 할 수 있다.
ESLint v9부터 설정 방식이 바뀌어 기존 .eslintrc.* 대신 Flat Config(eslint.config.js/cjs) 를 사용한다.
| 구분 | ESLint v8 이하 | ESLint v9 이상 |
|---|---|---|
| 설정 파일 이름 | .eslintrc.js | eslint.config.js / eslint.config.cjs |
| 구조 | 객체(Object) 하나 | 배열(Array) 구조 |
| 환경 설정 | env 속성 사용 | languageOptions.globals 사용 |
| 플러그인 로딩 | extends로 불러오기 | 모듈에서 직접 import/require |
Flat Config는 명시적이고 확장성 있는 구성이라 최신 프로젝트에 적합하다.
npm install -D eslint eslint-plugin-import globals
프로젝트 루트에 eslint.config.cjs 파일 생성하고
아래 코드 복붙하기
// javascript-style-guide 반영
// eslint.config.cjs (ESLint v9+ flat config)
// 필요한 패키지: eslint, eslint-plugin-import, globals
// $ npm i -D eslint eslint-plugin-import globals
const pluginImport = require('eslint-plugin-import');
const globals = require('globals');
module.exports = [
// 무시할 경로(옵션)
{
ignores: ['node_modules', 'dist', 'build', 'coverage'],
},
// JS 파일들에 적용
{
files: ['**/*.js', '**/*.mjs', '**/*.cjs'],
languageOptions: {
ecmaVersion: 'latest',
sourceType: 'module',
globals: {
...globals.browser,
...globals.node,
...globals.jest,
},
},
plugins: {
import: pluginImport,
},
rules: {
/* === 공백/들여쓰기/포맷 === */
indent: ['error', 2, { SwitchCase: 1 }],
'space-before-blocks': ['error', 'always'],
'keyword-spacing': ['error', { before: true, after: true }],
'space-in-parens': ['error', 'never'],
'array-bracket-spacing': ['error', 'never'],
'object-curly-spacing': ['error', 'always'],
'comma-spacing': ['error', { before: false, after: true }],
'eol-last': ['error', 'always'],
'no-multiple-empty-lines': ['error', { max: 1 }],
'no-trailing-spaces': ['error'],
'max-len': [
'warn',
{
code: 100,
ignoreComments: true,
ignoreStrings: true,
ignoreTemplateLiterals: true,
ignoreUrls: true,
},
],
/* === 문자열/세미콜론 === */
quotes: ['error', 'single', { avoidEscape: true }],
semi: ['error', 'always'],
'prefer-template': ['error'],
'template-curly-spacing': ['error', 'never'],
/* === 화살표 함수 === */
'arrow-parens': ['error', 'always'],
'arrow-spacing': ['error', { before: true, after: true }],
'prefer-arrow-callback': ['error'],
'arrow-body-style': ['error', 'as-needed'],
'no-confusing-arrow': ['error'],
/* === 변수/스코프 === */
'no-var': ['error'],
'prefer-const': ['error'],
'no-unused-vars': ['error', { argsIgnorePattern: '^_' }],
'no-undef': ['error'],
'no-use-before-define': [
'error',
{ functions: false, classes: true, variables: true },
],
'no-shadow': ['error'],
/* === 비교/제어문/블록 === */
eqeqeq: ['error', 'always'],
'no-else-return': ['error', { allowElseIf: false }],
curly: ['error', 'all'],
'default-case': ['error'],
'consistent-return': ['error'],
'guard-for-in': ['error'],
'dot-notation': ['error'],
/* === 함수 관련 === */
'func-names': ['error', 'as-needed'],
'no-empty-function': ['error'],
'no-loop-func': ['error'],
'no-param-reassign': ['error'],
'no-return-assign': ['error', 'always'],
'no-nested-ternary': ['error'],
'no-unneeded-ternary': ['error'],
'nonblock-statement-body-position': ['error', 'beside'],
'prefer-rest-params': ['error'],
/* === 객체/배열 === */
'object-shorthand': ['error', 'always'],
'quote-props': ['error', 'as-needed'],
'array-callback-return': ['error'],
'prefer-destructuring': [
'error',
{
VariableDeclarator: { array: false, object: true },
AssignmentExpression: { array: true, object: true },
},
],
'prefer-spread': ['error'],
/* === 모듈(import/export) === */
'import/first': ['error'],
'import/newline-after-import': ['error', { count: 1 }],
'import/no-duplicates': ['error'],
'import/no-mutable-exports': ['error'],
'import/extensions': [
'error',
'ignorePackages',
{ js: 'always', mjs: 'always', cjs: 'always' },
],
'import/prefer-default-export': ['warn'],
/* === 클래스/생성자 === */
'constructor-super': ['error'],
'no-this-before-super': ['error'],
'no-useless-constructor': ['error'],
'no-dupe-class-members': ['error'],
/* === 이터레이터/제너레이터 지양 === */
'no-restricted-syntax': [
'error',
{
selector: 'ForOfStatement',
message: '배열 반복엔 map/filter/reduce 등 메서드를 사용하세요.',
},
{
selector: 'ForInStatement',
message: '객체 반복엔 Object.keys/values/entries를 사용하세요.',
},
],
/* === 형변환/수치 === */
radix: ['error', 'always'],
'prefer-exponentiation-operator': ['error'],
'use-isnan': ['error'],
'no-new-wrappers': ['error'],
'no-multi-assign': ['error'],
yoda: ['error', 'never'],
'no-bitwise': ['error'],
/* === 기타 === */
'no-console': ['warn', { allow: ['warn', 'error'] }],
'no-debugger': ['error'],
'no-alert': ['error'],
'no-new': ['error'],
'no-continue': ['error'],
'no-plusplus': ['error', { allowForLoopAfterthoughts: true }],
},
},
];
npx eslint .
npx eslint src/index.js
npx eslint . --fix
package.json에 스크립트를 넣어두면 매번 명령어를 기억하지 않아도 된다.
{
"scripts": {
"lint": "eslint .",
"lint:fix": "eslint . --fix"
}
}
이제 아래처럼 실행 가능하다.
# 검사
npm run lint
# 자동수정
npm run lint:fix
.vscode/settings.json 추가 👇{
"editor.formatOnSave": true,
"editor.defaultFormatter": "dbaeumer.vscode-eslint",
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true
},
"eslint.validate": ["javascript", "javascriptreact"],
"eslint.format.enable": true
}
💡 이제 저장만 해도 ESLint가 자동으로 실행되어 코드가 깔끔하게 정리된다!
[Ctrl + S] (파일 저장)
↓
VSCode → ESLint 확장 플러그인 트리거
↓
프로젝트 루트에서 eslint 탐색
↓
1️⃣ Flat Config (eslint.config.cjs/js)
또는
2️⃣ 전통적 .eslintrc.*
↓
ESLint Core 엔진이 AST 분석 수행
↓
rules, plugins, globals 등 적용
↓
자동 수정 가능한 부분 (--fix) 즉시 수정
↓
VSCode에 수정 반영
| 규칙 | 설명 | 예시 |
|---|---|---|
eqeqeq | == 대신 === 사용 | if (a === b) |
no-var | var 금지, let/const 사용 | const x = 1 |
quotes | 작은따옴표 사용 | 'hello' |
semi | 세미콜론 필수 | console.log('hi'); |
no-console | 콘솔 사용 금지(경고) | console.warn() 가능 |
eslint.config.cjs의rules에서"error","warn","off"로 조정 가능
처음 ESLint를 사용해보면서
개발자들은 역시 천재들이구나라고 생각했습니다.
저장만 해도 코드가 자동으로 교정되다니...
아직은 배우는 입장이라서
자동교정기능 (npx eslint . --fix) 보다는
코드점검기능 (npx eslint .) 을 위주로
ESLint한테 혼나가며 코딩을 해야겠다고 생각을 했습니다.
그래도 언제나 제곁에서(?!)
매의눈으로 제 코드를 지켜봐주는
선생님이 생긴 것 같아
마음이 든든해졌습니다. ^^
한 줄 요약: ESLint는 내 코드를 검사하고 교정해주는 코치 선생님 ^^