Husky & GitHub Action을 통한 코드 검사

Hyeon·2024년 9월 6일
0
post-thumbnail

ruby on rails의 프론트 코드를 next로 분리하면서 초기에 lint와 prettier 설정을 하지 않았고, 이런 저런 이유로 미루고 있었다. 초기 프로젝트는 두 명이 개발했고 코드베이스도 작아 코드 품질 도구의 필요성을 느끼지 못했는데, 최근 타 팀이 next 프로젝트에 기여하기 시작하면서 코드 일관성이 깨지고 오류가 발생하기 시작했다. 코드리뷰에 지엽적인 부분에 대한 코멘트도 많아졌고, 이에 lint 도입의 필요성을 느끼게 되었다. 사실 당연히 되어있어야 했다.

.eslintrc

{
  // 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 훅 설정 디렉토리
  ]
}

.prettierrc

{
  "tabWidth": 2,
  "semi": true,
  "singleQuote": false,
  "bracketSpacing": true,
  "arrowParens": "always",
  "printWidth": 120
}

husky

husky/pre-commit 생성

# lint-staged 명령어를 실행하여 스테이징된 파일에 대해 Lint 검사를 수행
yarn lint-staged

package.json 스크립트 추가

{
  "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"
    ]
  }
}

lint, prettier 적용

prettier로 735개 파일이 수정되었다.
lint는 160개 파일이 auto fix 되었고, 2776개 error 및 warning은 수동 수정이 필요했다.

모두 일괄 수정하기엔 시간적 제약이 있어 일단 오류가 있는 파일에 대해 lint disable 해두고 관련 파일들에 대한 작업이 있을 때마다 수정하는 것으로 협의했다.

lint warn, error일 경우 disable 처리 script

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();

github action 추가

  • develop 브랜치로 PR이 올라왔을 때 체크하는 workflow를 작성
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 작업이 완료될 때까지 기다림

0개의 댓글