Node.js + TypeScript 에서 ESLint로 컨벤션 지키며 코딩하기 (feat. prettier)

Sunny·2023년 5월 20일
0

1. ESLint & Prettier

1.1 ESLint?

JavaScript 코드에서 발견된 문제 패턴을 식별하기 위한 정적 코드 분석 도구이다.

대부분의 프로그래밍 언어에는 컴파일하는 과정에서 수행되는 Linter가 기본적으로 내장되어 있다.

그러나, 인터프리터 언어인 JavaScript는 Linter가 존재하지 않는다.

따라서 런타임 환경에서 에러가 발생할 확률이 높다.

ESLint는 JavaScript 문법에서 에러를 표시하여 런타임 환경에서 발생하는 에러를 코드를 실행하지 않고도 잡을수 있도록 도와주는 도구이다.

ESLint는 에러로서 정말 문제가 되는 부분만을 지정할 수도 있고, 전반적인 코딩 스타일 까지도 지정할 수 있어 많은 사람들과 협업할때 코드 컨벤션을 지키면서 에러와 코딩 스타일을 잡아주는 역할을 하여 매우 유용하게 사용된다.

👉 TypeScript를 위한 lint인 TSLint도 존재하지만, 현재는 ESLint와 통합으로 사용되고있다.

이번 앱잼에서 우리 팀은 ESLint를 사용하여 코드작성 단계에서 에러를 잡고자 했고, 전반적인 코딩스타일과 컨벤션을 지키며 개발하고자 하여 ESLint를 사용하기로 했다.

1.2 Prettier

Prettier은 Code Formatter이다.

개발자들에게 일관적인 코딩 스타일을 유지할 수 있게 도와주는 툴이다.

깔끔한 코드와 협업을 위해서 일관성 있는 코드 스타일을 유지하는 것은 중요하다.

Prettier와 ESLint의 다른점은 ESLint는 문법에러를 잡아주거나, 더 좋은 문법을 사용하게 에러표기를 강제해주는 툴이지만, Prettier은 코드의 퀄리티가 아닌 스타일을 교정해준다.

간단히 말하면, ESLint를 적용한다면 코딩의 결과가 바뀌기도 하지만, Prettier는 단순히 스타일을 교정해주기 때문에 결과에는 영향이 없다

ESLint와 Prettier를 함께 사용하면, 문법 에러를 잡으며 코드의 퀄리티를 높이고, 코드의 스타일까지 교정하는 효과를 볼 수 있다.

2. Node.js + TypeScript + ESLint 적용 in VSCode

2.1 설치 및 적용

먼저, 기존에 ESLint를 사용한적이 없다면 vscode extention에서 eslint와 prettier을 설치해준다.

yarn add -D eslint prettier eslint-config-prettier eslint-plugin-import eslint-plugin-node eslint-plugin-prettier @typescript-eslint/eslint-plugin @typescr
ipt-eslint/parser

터미널에 위의 명령어를 입력해준다. 위의 패키지들을 다 설치할 필요는 없지만 이번 앱잼에서 우리는 위의 패키지들을 사용하였다.

eslintprettier를 설치해주고, typeScript와의 사용을 위해 @typescript-eslint/eslint-plugin@typescript-eslint/parser을 설치해 주었다.

node에서의 사용을 위해 eslint-plugin-node와 lint에 prettier 규칙 적용을 위한 eslint-plugin-prettier도 설치해주었다.

{
        "env": {
          "es2021": true,
          "node": true,
          "jest": true
        },
        "extends": [
          "eslint:recommended",
          "plugin:@typescript-eslint/eslint-recommended",
          "plugin:@typescript-eslint/recommended",
          "plugin:prettier/recommended",
          "prettier/prettier",
          "plugin:import/recommended"
        ],
        "parser": "@typescript-eslint/parser",
        "parserOptions": {
          "project": ["./tsconfig.json", "./jest.config.js"],
          "ecmaVersion": "latest",
          "sourceType": "module"
        },
        "plugins": ["@typescript-eslint", "prettier"],
        "rules": {
          "camelcase": "error",
          "comma-dangle": ["error", "always-multiline"],
          "no-console": ["warn"],
          "@typescript-eslint/no-var-requires": "off",
          "no-constant-condition": ["error", { "checkLoops": true }],
          "no-restricted-syntax": [
            "error",
            {
              "selector": "LabeledStatement",
              "message": "Labels are a form of GOTO; using them makes code confusing and hard to maintain and understand."
            },
            {
              "selector": "WithStatement",
              "message": "`with` is disallowed in strict mode because it makes code impossible to predict and optimize."
            }
          ],
          "no-use-before-define": ["off", { "functions": false }],
          "no-unused-expressions": ["error", { "allowTaggedTemplates": true }],
          "prefer-const": [
            "error",
            { "destructuring": "all" }
          ],
          "prefer-destructuring": ["error", { "array": false, "object": false }, { "enforceForRenamedProperties": true }],
          "spaced-comment": ["error", "always"],
          "import/extensions": ["error", "never"],
          "import/no-unresolved": "off",
          "import/order": [
            "error",
            {
              "groups": [
                "builtin",
                "external",
                "internal",
                "parent",
                "sibling"
              ],
              "newlines-between": "always",
              "alphabetize": {
                "order": "asc",
                "caseInsensitive": false
              }
            }
          ],
          "import/prefer-default-export": "off"
        },
        "ignorePatterns": ["dist/", "node_modules/", "jest.config.js", "babel.config.js", "__test__"]
      }

다음으로 프로젝트 폴더 루트에 .eslintrc.json파일을 만들고 위와 같은 내용을 넣어주면 된다. (우리 팀과 세팅이 똑같지 않다면 오류가 날것이다. 프로젝트에 맞도록 세팅할것) 뭐가 되게 많은거같아서 당황할수도 있지만 그냥 우리 프로젝트가 규칙을 좀 빡세게 정한거 뿐이다.. 가볍게 가고싶다면 lint 규칙이나 extends등을 빼면 된다.

파일 구성을 살펴보자면

  • env: 해당 환경에서 정의된 함수나 전역변수를 사용할 수 있게 해준다
    • "node":true로 설정했다면 require을 error없이 사용할 수 있다.
  • plugins: plugin설정을 통해 다른사람이 만든 규칙을 가져올 수 있다.
    • eslint-plugin-prettier: 린트 위에 사용할 프리티어 플러그인
    • @typescript-eslint/eslint-plugin: : 타입스크립트 전용 린트
    • 등이 있다
  • extends: 다른사람이 만들어둔 plugin package 컨벤션을 그대로 따르고 싶을때, plugin에서 다운 받은 것을 그대로 적어준다.
  • parser: ESLint는 구문 분석을 위해 기본적으로 Espree 파서를 이용한다. TypeScript 구문 분석을 위해서는 @typescript-eslint/parser를 사용하면 된다.
  • rules: 세세한 규칙을 수정할 수 있다. off 는 규칙을 사용하지 않는다는 것이고, warn 은 규칙을 경고로써 표시한다. error 는 규칙을 오류로 표시하여주고 해결하지 않을시 build등에 제약이 걸리게 된다.
  • parserOptions: Javascript 언어 옵션을 지정할 수 있다.
  • ignorePatterns: lint를 적용하지 않는 파일 및 폴더를 정의할 수 있다. 기본적으로 build파일인 dist, node_modules를 제외하는 편이고 추가적으로 우리는 테스트코드 작성을 위한 jest관련 세팅을 lint적용에서 제외했다.

lint rule의 종류는 정말 많고 규칙에 대한 내용은 공식문서에 정리되어있다. 필요한 규칙이 있다면 찾아서 추가해주면 된다!

rule에 대한 문서는 여기

Rules - ESLint - Pluggable JavaScript Linter

{
  "singleQuote": true,
  "semi": true,
  "tabWidth": 2,
  "trailingComma": "all",
  "printWidth": 100,
  "endOfLine": "auto"
}

마찬가지로 루트 디렉토리에 .prettierrc 파일을 만들어주고 lint 와 함께 사용할 prettier format을 정의해주면 된다.

{
	...
	"editor.defaultFormatter": "dbaeumer.vscode-eslint"
	...
}

이후 VS Code의 setting에서 프로젝트의 defaultFormatter을 lint로 설정해준다. setting.json에서 위와같이 추가해도 되고,

위와 같이 ui를 사용하여 설정해도 된다.

여기까지 설정하면 기존에 세팅했던 파일들이 에러가 와장창 뜨며 붉게 물들것이다.

  • 에러가 안나는데요? 일단 기본적으로 vsCode를 먼저 껐다 켜보시고 그래도 에러가 안난다면 뭔가를 잘못 설정하셨습니다… lint에서 정의한 프로젝트 세팅이 알고보니 안깔려있다던가 (예를들면 타입스크립트 lint설정을 했는데 타입스크립트를 안깔았거나) 하는 이유로.. 검색 화이팅

하지만 "format on Save(저장 시 알아서 수정해주는 기능)"은 아직 동작하지 않을 것이다. format on Save가 없다면 에러나는곳을 다 찾아가서 직접 수정을 해야하는 번거로움이 있다.

{
	...
	"editor.formatOnSave": true,
	"editor.codeActionsOnSave": {
        "source.fixAll.stylelint": true
    },
	...
}

default formatter 설정과 마찬가지로 VS Code의 setting.json에서 기존 내용에 위의 내용을 추가해서 설정 가능하다.

여기까지 했으면 이전에 에러가 와장창 나던 파일로 가서 컨트롤+s 혹은 커맨드+s 를 누르면 자동으로 알아서 슈슈슉!!! 에러에 대한 코드가 정리되며 빨간 줄들이 다 사라져 마음이 편안해질수 있다.

저장을 했음에도 없어지지 않는 오류들은 단순히 코드 스타일에 대한 오류가 아니기 때문에 직접 수정을 해주면 된다.

2.2 yarn eslint .

파일 하나하나 찾아다니며 에러를 찾는 방법도 있지만 터미널로 한방에 모든 린트 에러를 볼 수 있는 명령어가 있다.

yarn eslint .

마법처럼 lint 오류가 주루루룩 뜰것이다.

이렇게

2.3 with husky

husky는 Git 명령어가 실행되면 사용자가 지정한 스크립트를 실행시켜주는 Node.js 패키지이다.

git에 올리기 전에 사전 테스트로 에러 방지가 가능하고, lint와 함께 사용하여 컨벤션을 지켜 커밋할 수 있도록 도와준다.

husky의 pre-commit에 위의 전체 lint를 체크하는 명령어를 추가한다면 커밋 전 오류가 없는지 한번더 확인할 수 있다!

3. 마치며

Node.js Typescript를 쓰는 환경에서 ESLint와 Prettier을 설정해서 퀄리티 높은 코드를 작성할 수 있도록 하는것에 대해서 소개했다.

간혹 프로젝트 깃허브 코드를 구경하면 lint rules에 죄다 off 를 하고 쓰시는 분들이 계시는데…. 그건 lint를 안쓰는것과 마찬가지이니 꼭 주의하자. 마치 타입스크립트에서 any를 마구마구 쓰는것과 같은 느낌이랄까..?

이상으로 글을 마친다!

profile
FrontEnd Developer

0개의 댓글