ruby on rails의 프론트 코드를 next로 분리하면서 초기에 lint와 prettier 설정을 하지 않았고, 이런 저런 이유로 미루고 있었다. 초기 프로젝트는 두 명이 개발했고 코드베이스도 작아 코드 품질 도구의 필요성을 느끼지 못했는데, 최근 타 팀이 next 프로젝트에 기여하기 시작하면서 코드 일관성이 깨지고 오류가 발생하기 시작했다. 코드리뷰에 지엽적인 부분에 대한 코멘트도 많아졌고, 이에 lint 도입의 필요성을 느끼게 되었다. 사실 당연히 되어있어야 했다.
{
// ESLint가 TypeScript를 지원하도록 설정
"parser": "@typescript-eslint/parser",
// 파서의 옵션을 설정
"parserOptions": {
// ECMAScript 버전을 설정
"ecmaVersion": 2021,
// 모듈 시스템을 설정
"sourceType": "module",
// JSX 기능을 사용하도록 설정
"ecmaFeatures": {
"jsx": true
}
},
// ESLint 규칙의 확장을 설정
"extends": [
// 기본 권장 규칙을 적용
"eslint:recommended",
// TypeScript의 권장 규칙을 적용
"plugin:@typescript-eslint/recommended",
// Next.js의 웹 바이탈 규칙을 적용
"next/core-web-vitals",
// Prettier의 코드 스타일 규칙을 적용
"prettier"
],
// 사용 중인 플러그인을 설정
"plugins": [
// TypeScript 관련 규칙을 사용하기 위해 @typescript-eslint 플러그인을 추가
"@typescript-eslint"
],
// React의 설정을 자동으로 감지
"settings": {
"react": {
"version": "detect"
}
},
// 규칙을 설정합니다.
"rules": {
// React 17 이상에서는 JSX에 React를 import할 필요가 없으므로 이 규칙을 비활성화
"react/react-in-jsx-scope": "off",
// 'any' 타입 사용 시 경고를 발생시킴
"@typescript-eslint/no-explicit-any": "warn",
// 콘솔 사용 시 경고를 발생시킴
"no-console": "warn"
},
// Lint 검사에서 제외할 파일 및 디렉토리를 설정
"ignorePatterns": [
"node_modules/", // 의존성 모듈 디렉토리
".husky/" // Git 훅 설정 디렉토리
]
}
{
"tabWidth": 2,
"semi": true,
"singleQuote": false,
"bracketSpacing": true,
"arrowParens": "always",
"printWidth": 120
}
husky/pre-commit 생성
# lint-staged 명령어를 실행하여 스테이징된 파일에 대해 Lint 검사를 수행
yarn lint-staged
{
"scripts": {
// 모든 파일에서 ESLint를 실행하고 자동으로 수정
"lint:fix": "npx eslint . --fix",
// 모든 파일에서 Prettier를 실행하여 코드 스타일을 자동으로 수정
"prettier:fix": "npx prettier --write .",
// ESLint와 Prettier를 순서대로 실행하여 코드 포맷을 정리
"format:all": "yarn lint:fix && yarn prettier:fix"
},
"lint-staged": {
// 스테이징된 JavaScript, JSX, TypeScript, TSX 파일에 대해 lint와 format을 실행
"*.{js,jsx,ts,tsx}": [
// 최대 경고 수를 0으로 설정하여 경고가 발생하면 lint 검사 실패로 간주
"eslint --max-warnings=0",
// 코드 포맷 검사를 수행
"prettier --check"
]
}
}
prettier로 735개 파일이 수정되었다.
lint는 160개 파일이 auto fix 되었고, 2776개 error 및 warning은 수동 수정이 필요했다.
모두 일괄 수정하기엔 시간적 제약이 있어 일단 오류가 있는 파일에 대해 lint disable 해두고 관련 파일들에 대한 작업이 있을 때마다 수정하는 것으로 협의했다.
const { ESLint } = require('eslint');
const fs = require('fs');
const path = require('path');
async function runESLint() {
// ESLint 인스턴스를 생성
const eslint = new ESLint();
try {
// 현재 디렉토리의 모든 파일을 검사
const results = await eslint.lintFiles(['.']);
// 오류나 경고가 있는 파일을 필터링
const filesWithErrors = results
.filter((result) => result.errorCount > 0 || result.warningCount > 0)
.map((result) => result.filePath);
// 오류가 있는 파일마다 작업을 수행
filesWithErrors.forEach((file) => {
// 파일 경로를 절대 경로로 변환
const filePath = path.resolve(file);
// 파일 내용을 읽어옵니다.
const fileContent = fs.readFileSync(filePath, 'utf-8');
// 파일이 `/* eslint-disable */` 주석으로 시작하지 않으면 추가
if (!fileContent.startsWith('/* eslint-disable */')) {
// 주석을 추가한 새로운 파일 내용을 만듭니다.
const updatedContent = `/* eslint-disable */\n${fileContent}`;
// 파일에 새로운 내용을 씁니다.
fs.writeFileSync(filePath, updatedContent, 'utf-8');
console.log(`Added /* eslint-disable */ to ${file}`);
} else .
console.log(`이미 주석이 존재합니다. ${file}`);
}
});
console.log('주석 추가 작업이 완료되었습니다.');
} catch (error) {
console.error('ESLint 실행 중 오류가 발생했습니다:', error);
}
}
// ESLint를 실행
runESLint();
name: Lint
on:
pull_request:
branches:
- develop
jobs:
lint:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3
# GitHub 리포지토리의 코드를 체크아웃
- name: Set up Node.js
uses: actions/setup-node@v2
with:
node-version: "18"
- name: Install ESLint and Prettier
run: |
yarn add eslint@8.0.0 eslint-config-next@12.0.0 eslint-config-prettier@8.0.0 eslint-plugin-tailwindcss@3.10.1 prettier@3.3.3 --dev
# ESLint와 Prettier 및 관련 플러그인을 설치
#ESLint와 Prettier를 비동기로 검사
- name: Run ESLint
id: eslint
run: npx eslint src --max-warnings=0 &
# ESLint 실행
- name: Run Prettier check
id: prettier
run: npx prettier --check src &
# Prettier 실행
- name: Wait for linting to complete
run: wait
# 백그라운드에서 실행 중인 ESLint와 Prettier 작업이 완료될 때까지 기다림