ESLint로 코딩 컨벤션 맞추기

이예슬·2023년 10월 20일
0

블로그를 이전했습니다(https://yeseul-blog.vercel.app/)


ESLint란?

💡 Find and fix problems in your JavaScript code

자바스크립트 코드에서 발생할 수 있는 잠재적인 문제를 찾아 수정해 주는 정적 분석 도구이다.

ESLint와 같은 정적 분석 도구가 필요한 이유는 아래와 같다

  • 문법 오류나 오타 등의 잠재적 에러 발견
    • 자바스크립트는 다른 언어에 비해 유연한 문법 구조를 가진다. 그리고 이러한 특징으로 인해 문법적으로 오류가 없음에도 버그가 발생할 수 있으며 컴파일 단계가 없으므로 코드를 실행하기 전까지는 알 수 없다.
  • 코딩 컨벤션 검증
  • IDE와 연동가능한 빠른 피드백

ESLint 동작방식

그렇다면 ESLint는 어떻게 우리의 코드를 분석하고 에러를 발견할 수 있을까?

ESLint는 아래와 같은 순서로 우리의 코드를 분석한다.

1️⃣ Parser

ESLint 실행시 Espree라는 parser가 자바스크립트 코드를 분석하여 AST(Abstract Syntax Tree)를 만든다.
이 때 parser는 기본적으로 Espree를 사용하지만 설정을 통해 다른 parser를 사용할 수도 있다. 예를 들어 typescript 구문 분석을 위해서는 @typescript-eslint/parser 를 사용한다.

2️⃣ AST

ESLint가 동작하는 방식을 이해하기 위해서는 먼저 AST에 대해 알아야 한다. Abstract Syntax Tree는 추상 구문 트리로 프로그래밍 언어로 작성된 소스코드의 추상 구문 구조의 트리를 말하며 컴파일러에서 널리 사용되는 자료구조이다.
트리의 각 노드는 소스코드에서 발생되는 구조를 나타내며 노드 타입, 소스코드에서 노드의 위치 하위 자식 노드들에 대한 레퍼런스 등을 가지고 있다.

내가 작성한 코드를 AST로 확인하고 싶다면 해당 사이트에서 확인할 수 있다.

아래는 자바스크립트로 변수를 선언했을 때 AST가 어떤식으로 생성되는지 확인해 본 예제이다.

var foo = bar;
{
  "type": "Program",
  "start": 0,
  "end": 14,
  "body": [
    {
      "type": "VariableDeclaration",
      "start": 0,
      "end": 14,
      "declarations": [
        {
          "type": "VariableDeclarator",
          "start": 4,
          "end": 13,
          "id": {
            "type": "Identifier",
            "start": 4,
            "end": 7,
            "name": "foo"
          },
          "init": {
            "type": "Identifier",
            "start": 10,
            "end": 13,
            "name": "bar"
          }
        }
      ],
      "kind": "var"
    }
  ],
  "sourceType": "module"
}

3️⃣ Linter + Rule

린터는 설정에 있는 규칙들을 생성한 뒤 AST를 순회하며 AST 노드 타입과 같은 이름의 이벤트를 발생시킨다.

발생한 이벤트는 규칙의 리스너에게 전달되어 해당 노드가 규칙을 지키고 있는지 검사한다. 규칙에 맞지 않은 경우 이에 대해 보고하며 가능한 경우 코드를 알아서 규칙에 맞게 수정해주는 fixer를 생성할 수 있다.

4️⃣ Report + Fixer

context.report({
    node,
    data: {deprecatedFunc: name},
    message: `'{{deprecatedFunc}}()' 은 deprecated 되었습니다.`,
    // ...
});

reporter는 어떤 규칙을 어겼는지 어떤 부분이 문제인지를 전달해주는 역할을 하며 이 때 노드의 실제 소스코드 위치 정보가 포함되어 있으므로 규칙을 어긴 코드의 위치도 확인할 수 있다.

Fixer는 에러 발생시 코드를 규칙에 맞게 수정하는 역할을 한다.

eslint 실행시 -fix 옵션을 사용하면 동작하게 되며 fixer가 제공하는 메서드를 통해 특정 토큰, 노드가 가지고 있는 값을 수정하거나 노드를 삭제, 삽입할 수 있다.

ESLint는 위와 같은 방식으로 동작하며 이러한 동작원리를 이해하고 있다면 원하는 규칙을 만들수도 있다.

ESLint 옵션

ESLint에는 다양한 옵션들이 존재하며 아래와 같은 옵션들은 다양한 방식으로 활용될 수 있다.

root

ESLint는 여러 개의 설정 파일을 사용할 수 있으며 이는 모노레포의 경우에 유용하게 사용될 수 있다.

{
  "root": true
}

ESLint는 현재 린트 대상 파일이 위치한 폴더 안에서 설정 파일이 있는지 우선적으로 확인해보고 없으면 그 상위 폴더를 한 단계씩 거슬러 올라가면서 설정 파일을 찾는다. 이 때 root 옵션이 true로 설정되어있는 ESLint 설정 파일을 찾으면 더 이상 상위 폴더로 올라가지 않는다.

즉 모노레포의 경우 각각의 프로젝트 개별 설정 파일에는 root 옵션을 false로 하고 코드 저장소 최상위 경로에는 root 옵션을 true로 설정하면 코드 저장소의 공통 설정과 프로젝트별 설정을 분리해서 관리할 수 있다.

plugin

{
  "plugins": ["import", "react"]
}

ESLint에서 기본으로 제공하지 않는 다양한 규칙을 정리한 패키지(ex. eslint-plugin-jsDoc)

플러그인은 단순히 설정이 가능한 상태로 만들어줄 뿐 규칙을 적용해주지는 않는다.

extends

{
  "plugins": ["import", "react"],
  "extends": ["plugin:import/recommended", "plugin:react/recommended"]
}

plugin이나 rule들을 모아서 설정으로 만든 것(ex. eslint-config-airbnb)

또한 대부분의 eslint 플러그인은 추천 설정을 제공하며 extends 옵션 사용시 추천 설정을 사용할 수 있다.

rules

rules 옵션은 규칙 하나하나를 세세하게 제어하기 위해서 사용된다.

즉 extends 옵션을 통해서 설정된 규칙을 rules로 덮어쓸 수 있다.

위의 옵션들 외에도 overrides나 ignorePatterns 등 eslint는 옵션이 굉장히 많다!!

ESLint로 컨벤션 맞추기

ESLint에는 이미 충분히 다양한 규칙들이 존재하며 잘 만들어진 plugin 또한 많기 때문에 이미 존재하는 규칙을 잘 활용하기만 해도 팀의 컨벤션을 맞추는 데 도움이 된다.

예를 들어 나는 현재 회사에서 vue로 프로젝트를 진행하고 있는데 vue에서 제공하는 eslint plugin을 활용해 팀 컨벤션에 맞는 규칙들을 설정할 수 있다.

예시) vue의 template 안에서 component를 사용할 때는 PascalCase를 사용한다 라는 규칙은 아래와 같이 작성할 수 있다.

{
  "vue/component-name-in-template-casing": ["error", "PascalCase", {
    "registeredComponentsOnly": true,
    "ignores": []
  }]
}

https://eslint.vuejs.org/rules/component-name-in-template-casing.html

위와 같은 방법을 통해서 팀에서 정한 컨벤션들을 eslint로 강제할 수 있다.

ESLint의 Share Configuration

이처럼 다양한 옵션들과 설정들을 기억하고 매 프로젝트마다 설정 파일을 만들어서 일일이 설정하는 것은 비효율적일 것이다. ESLint는 이러한 문제를 해결하기 위해 share configuration을 제공한다.

다양한 자바스크립트 정적 정적 분석 도구 사이에서도 ESLint가 가장 많이 사용되는 이유는 쉬운 커스터마이징과 확장성 때문이다. ESLint는 본인만의 규칙을 만들고 이를 config로 만들어 npm을 이용해 쉽게 공유할 수 있다.

아래와 같은 프로젝트를 만들어서 npm에 배포하면 eslint 설정을 공유할 수 있다.

📦eslint-config-my-rules
┣ 📜index.js
┣ 📜package.json
┣ 📜react.js // options
┗ 📜typescript.js // options

Husky

eslint와 prettier 설정들을 잘 세팅해 놓아도 이를 적용하지 않는다면 의미가 없다.

이처럼 열심히 정해놓은 설정들을 지킬 수 있도록 도와주는 도구가 git hook이며 husky는 이러한 git hook 설정을 도와주는 npm package이다.

  • git hook: git 이벤트(ex. commit, push)가 발생했을 때 자동으로 특정 스크립트를 실행할 수 있도록 하는 기능

husky 사용방법

npx husky-init && npm install

생성된 husky 폴더 안의 pre-commit 파일 안에 아래와 같은 코드를 작성하면 commit 전에 해당 스크립트를 실행한다.

. "$(dirname -- "$0")/_/husky.sh"

npm run lint
profile
꾸준히 열심히!

0개의 댓글