코드의 품질을 위해 ESLint와 Preitter를 보통 혼합해서 쓴다.
왜 그럴까? 하는 역할은 비슷해보이는데 어떤 게 달라서 둘 다 같이 써야하는지 알아보고 각각 어떤 설정이 어떤 역할을 하는건지 파악해보자.
VSCode가 코드의 Lint Error를 잡는 것부터, 저장 시 자동 수정하는 설정까지 복잡한 조건 설정 과정을 적용해보자!
ESLint는 코드 품질을 개선하고 런타임에 버그가 발생하지 않도록 사전에 버그를 수정하는 데 도움이 되는 linter이다.
'Lint'는 실제로 보풀이라는 뜻이다. ESLint는 거슬리는 보풀 같은 코드를 깔끔하게 만들어준다는 뜻이라고 보면 된다.ㅎ
ESLINT_USE_FLAT_CONFIG 환경 변수를 false으로 설정해야 한다.이 글에서는 v9.x 버전으로 다룬다.
ESLint 에서 많이 사용하는 plugin 으로는 기본인 plugin:@typescript-eslint/recommended 가 있다.
그리고 Airbnb, Google 등에서 본인들의 ESLint style 을 작성하여 npm 모듈로 제공하고 있다.
공식 문서의 Rules Reference를 확인해보면, 각 규칙에는 있는 이모지 표시로 규칙 활성화와 자동 수정 여부를 확인할 수가 있다.
recommendedconfig 설정 시 활성화 되는 규칙세 가지 오류 수준을 통해 ESLint가 규칙을 적용하는 방식을 세부적으로 제어할 수 있다.
"off" or "0""warn" or "1""error" or "2"npm init @eslint/config@latest
- How would you like to use ESLint? // eslint를 어떤 방식으로 쓸거에요?
- To check syntax only // 문법적 오류만 잡을거에요
- To check syntax and find problems // 문법이랑 에러도 잡을거에요
- What type of modules does your project use? // 프로젝트에선 어떤 모듈화를 사용하나요?
- JavaScript modules (import/export)
- CommonJS (require/exports)
- None of these
- Which framework does your project use? // 어떤 프레임워크를 사용하나요?
- React
- Vue.js
- None of these // 안써요
- Does your project use TypeScript? // 프로젝트는 typescript를 사용하나요?
- y/s로 대답
- Where does your code run? // 당신의 코드는 어디서 돌리나요?
- browser
- Node
- Which package manager do you want to use? // 패키지 매니저 선택
- npm
- yarn
- pnpm
설치를 완료하면 eslint.config.mjs 파일이 생성된다. 생성된 파일에 설정들을 추가해보자.
export default defineConfig([
{ files: ["app.js", "server/**/*.js"], languageOptions: { globals: globals.node } },
{ files: ["features/**/*.js"], languageOptions: { globals: globals.browser }},
js.configs.recommended,
{
rules: {
"no-unused-vars": "warn",
// "no-undef": "warn",
},
},
]);
"eslint:recommended": ESLint가 권장하는 규칙. 위에서 본 ✅ 표시 적용rules: ESLint는 규칙이 있어야 그걸 보고 코드를 검사한다. 새 객체를 정의하여 규칙을 개별적으로 구성할 수 있다.no-undef: 코드에서 선언되지 않은 식별자를 사용하면 오류를 표시하는 규칙이다. 하지만 globals 설정을 해주면 이런 오류를 잡아주기 때문에 따로 처리하지 않았다. 또한, TypeScript 계획이 있다면 no-undef는 TS가 잡아주므로 끄는 편(off)이 일반적이다.browser 코드와 node 코드를 files 패턴으로 분리해 각각 globals를 적용해야 한다. globals.browser/globals.node를 languageOptions.globals에 넣어야 no-undef 오탐이 생기지 않는다.왜 globals 설정이 no-undef 오탐을 줄이나요?
- 문제: 브라우저/노드 환경에는 미리 제공되는 전역 식별자들이 있는데, ESLint가 이를 모르면 no-undef로 오탐한다.
- 브라우저 전역 예시:window,document,navigator,location등
- 노드 전역 예시:process,dirname,Buffer,global등
- 해결:globals패키지의globals.browser,globals.node를 ESLint 설정의languageOptions.globals에 주입하면, 해당 식별자들을 “이미 전역에 존재하는 읽기전용 변수”로 인식해서 no-undef 오탐이 사라진다.
Preitter는 포맷팅 역할을 해서 코드를 일관성 있게 만들어준다.
ESLint와 달리 규칙이 미리 세팅되어 있기 때문에 설정 없이도 npx prettier . --write 명령어로 바로 사용해볼 수 있는 간편함이 있다.
npm install --save-dev --save-exact prettier
.prettierrc 파일을 추가해서 직접 커스텀을 해도 된다.
{
------------------------
기본 포맷팅 설정
------------------------
// 한 줄의 최대 길이를 설정 (기본값: 80)
// 이 길이를 초과하면 자동으로 줄바꿈이 발생
"printWidth": 80,
// 들여쓰기 시 사용할 공백 문자 수 (기본값: 2)
// useTabs가 false일 때만 적용됨
"tabWidth": 2,
// 들여쓰기에 탭 문자 사용 여부 (기본값: false)
// true: 탭 문자 사용, false: 공백 문자 사용
"useTabs": false,
// 문장 끝 세미콜론 사용 여부 (기본값: true)
// true: 모든 문장 끝에 세미콜론 추가
// false: 필요한 경우에만 세미콜론 추가
"semi": true,
------------------------
따옴표 관련 설정
------------------------
// 문자열에 작은따옴표 사용 여부 (기본값: false)
// true: 'string', false: "string"
"singleQuote": true,
// 객체 속성에 따옴표 추가 방식 (기본값: "as-needed")
"quoteProps": "as-needed",
// - "as-needed": 필요한 경우에만 따옴표 추가
// - "consistent": 하나라도 따옴표가 필요하면 모든 속성에 따옴표 추가
// - "preserve": 입력된 따옴표 스타일 유지
// JSX에서 작은따옴표 사용 여부 (기본값: false)
// singleQuote 설정과 독립적으로 동작
"jsxSingleQuote": true,
------------------------
쉼표 및 괄호 설정
------------------------
// 객체, 배열 등의 후행 쉼표 설정 (기본값: "es5")
"trailingComma": "es5",
// - "all": 모든 구문에서 후행 쉼표 사용 (함수 인자 포함)
// - "es5": ES5에서 유효한 위치에만 후행 쉼표 추가
// - "none": 후행 쉼표 사용 안 함
// 객체 리터럴의 중괄호 주위 공백 추가 (기본값: true)
// true: { foo: bar }, false: {foo: bar}
"bracketSpacing": true,
// JSX 요소의 > 위치 설정 (기본값: false)
// true: 마지막 줄에 > 위치, false: 다음 줄에 > 위치
"bracketSameLine": false,
// 화살표 함수 매개변수 괄호 사용 방식 (기본값: "always")
"arrowParens": "always",
// - "always": (x) => x
// - "avoid": x => x (매개변수가 하나일 때)
------------------------
특수 포맷팅 설정
------------------------
// 줄 끝 문자 설정 (기본값: "lf")
"endOfLine": "lf",
// - "lf": \n (Unix)
// - "crlf": \r\n (Windows)
// - "cr": \r (Mac OS)
// - "auto": 첫 줄 끝 문자 유지
// 마크다운 텍스트의 줄바꿈 방식 (기본값: "preserve")
"proseWrap": "always",
// - "always": 항상 printWidth에 따라 줄바꿈
// - "never": 줄바꿈 하지 않음
// - "preserve": 원본 텍스트 줄바꿈 유지
// HTML 공백 처리 방식 (기본값: "css")
"htmlWhitespaceSensitivity": "strict",
// - "css": CSS display 속성 기준으로 처리
// - "strict": 모든 공백을 유지
// - "ignore": 모든 공백을 무시
}
하지만 Preitter는 단순히 코드를 예쁘게 만들어주는 역할만 하고, 코드 품질과 관련된 검사는 ESLint의 몫이다.
그래서 Preitter는 ESLint와 통합하는 방법을 제공한다.
eslint-plugin-prettier를 설치하면 된다.
공식문서에 설명된 것처럼 코드 포맷팅 관련 문제에는 Prettier를, 코드 품질 관련 문제에는 ESLint를 사용해보자.
"devDependencies": {
"@eslint/js": "^9.34.0",
"eslint": "^9.34.0",
"eslint-config-prettier": "^10.1.8",
"globals": "^16.3.0",
"prettier": "3.6.2"
}
지금까지 설치한 각 패키지들의 핵심 기능을 설명하면 다음과 같다.
핵심 린팅 도구
• eslint: JavaScript/TypeScript 코드의 문제점을 검사하는 린터
• @eslint/js: ESLint의 JavaScript 관련 기본 설정
코드 스타일링
• prettier: 코드 포맷터
• eslint-config-prettier: 서로 충돌하는 옵션이 있으면 Preitter 규칙을 사용하여 충돌 방지
ESLint와 Preitter의 충돌을 설정해주기 위해 eslint.config.mjs에서 설정을 해줘야 한다.
import prettierConfig from "eslint-config-prettier";
export default defineConfig([
{
files: ["app.js", "server/**/*.js"],
languageOptions: { globals: globals.node },
},
{
files: ["features/**/*.js"],
languageOptions: { globals: globals.browser }.
},
js.configs.recommended,
prettierConfig, // Prettier와 충돌하는 규칙 비활성화
]);
🐛eslint-plugin-prettier 설정은 뺐어요.
이렇게 통합하는 과정에서 여러 블로그 글을 참고하다보면 eslint-config-prettier뿐만 아니라 eslint-plugin-prettier 플러그인을 추가로 사용하는 경우도 있다.
이건 Prettier가 ESLint 규칙으로 통합돼서 실행할 수 있도록 해주는 기능이다.
그런데,, 나도 처음에 eslint-plugin-prettier 플러그인으로 다음과 같이 통합해주는 과정을 거쳤는데 그렇게 하니까 몇가지 부분에서 통합이 제대로 이뤄지지 않는 문제상황을 겪었다.
import prettier from 'eslint-plugin-prettier';
...
{
plugins: { prettier },
rules: {
"prettier/prettier": "error", // Prettier 규칙 위반 시 오류 표시
},
},
.prettierrc에서 분명 싱글 따옴표(') 규칙으로 설정을 했는데 ESLint로 통합해서 적용할 때 더블 따옴표(") 규칙으로 적용되면서 Prettier 규칙을 위반했다고 빨간줄이 생기는 오류가 발생했다.
이 부분에 대해서 왜 그런지 찾아보다가.. 처음에는 뭔말인지 잘 모르고 넘어갔던 공식문서에서 언급한 부분을 다시 한 번 보게 되었다.
이 플러그인은 특정 상황에서는 유용할 수 있지만 일반적으로 권장되지는 않는 방식이라고 하는데, 이렇게 통합이 잘 되지 않는 문제가 발생하기도 해서 권장되지 않는다고 설명한게 아닐까 생각이 든다..!
매번 npm run lint를 돌리거나 빨간줄을 직접 수정하기에는 상당히 귀찮다. 이걸 해결해주기 위해 코드를 저장할 때 자동으로 코드포맷팅을 해주는 자동화 설정을 해주자.
폴더 상위 디렉토리에 .vscode/settings.json를 추가한다.
{
// ESLint 확장 프로그램 활성화
"eslint.enable": true,
// 기본 코드 포맷터를 Prettier로 설정
"editor.defaultFormatter": "esbenp.prettier-vscode",
// 파일 저장 시 자동으로 코드를 포맷팅
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.fixAll.eslint": "explicit", // ESLint 오류 자동 수정
"source.organizeImports": "explicit" // import 문 자동 정리
},
// ESLint가 검사할 파일 타입들을 지정
"eslint.validate": [
"javascript",
"javascriptreact",
"typescript",
"typescriptreact"
],
"prettier.requireConfig": true, // .prettierrc 파일이 있을 때만 Prettier를 사용 (프로젝트별 설정 강제)
// .mjs 파일을 JavaScript로 인식하도록 설정
"files.associations": {
"*.js": "javascript",
"*.mjs": "javascript"
},
// 탭 크기를 2칸으로 설정하고, 탭 대신 스페이스 사용
"editor.tabSize": 2,
"editor.insertSpaces": true,
// 파일 저장 시 빈 줄 제거
"files.trimTrailingWhitespace": true,
"files.insertFinalNewline": true
}