VSCode에서 ESLint와 Prettier (+ TypeScript) 사용하기

정현진·2020년 4월 13일
24
post-thumbnail

0. 들어가기

안녕하세요.

VSCode 환경에서 ESLint, Prettier, 그리고 TypeScript를 사용하기 위해 개발 환경을 설정하던 중 글로 정리를 해두면 다른 분들(+ 미래의 나)에게 도움이 될 것 같아 글을 올립니다.

이해를 돕기 위해 이 글에서는 아주 간단한 Express 앱을 바탕으로 설정 과정을 진행할 예정입니다.

최종 설정 파일 내용을 바로 보고 싶으신 분들은 5. 최종 설정 파일들 내용 을 눌러주세요!

0-1. 그래서 저것들이 뭐야?

각각 툴들의 기능에 대해서는 검색을 해보면 정리글이 잘 나와 있을텐데, 한 줄로 정의해보자면 아래와 같은 기능들을 합니다.

TypeScript: JavaScript에 정적 타입 기능을 추가한 언어.
ESLint: JavaScript의 코드를 분석해 문제점을 찾고 고쳐주는 도구.
Prettier: 작성한 코드의 형식을 자동으로 맞춰주는 도구.

이 세 가지 툴을 같이 쓰면 생산성에 큰 도움이 될 수 있습니다!

하지만 각각의 툴을 사용하기 위해 신경써줘야 할 설정들이 있어서 3가지를 한꺼번에 설정하기는 꽤 복잡했는데요, 이 과정을 정리해보았습니다.

1. VSCode 확장 프로그램 설치

VSCode에서 ESLint와 Prettier를 쓰기 위해서는 우선 각각의 확장 프로그램을 설치해야 합니다.

Prettier의 경우 Prettier Now 라는 또 다른 플러그인도 있는데 이건 사용해보질 않아서 잘 모르겠네요.

2. TypeScript 설정

2-1. 초기 프로젝트 구조

우선 설정을 진행할 기본 프로젝트의 구조는 아래 스크린샷들과 같이 express 패키지만 설치되어 있는 간단한 프로젝트입니다.

프로젝트는 다음과 같이 생성되었습니다.

# 프로젝트 초기 설정
npm init -y
# express 패키지 설치
npm i express

그리고 app.js 파일의 내용은 아래와 같습니다.

const express = require('express');	// express 불러오기
const app = express();			// express 실행

app.listen(1234, () => {
    console.log('Hello, World!');	// 서버가 실행되면 콘솔에 'Hello, World!' 출력
});

2-2. TypeScript 설치

이제 프로젝트에 TypeScript를 설치해보겠습니다.

TypeScript를 설치하기 위해서 터미널에 다음 라인을 실행합니다.

# TypeScript 설치
npm i -D typescript

-D 옵션은 --save-dev와 같은 기능을 하는데, 해당 옵션을 붙여주면 package.json 파일의 devDependencies에 패키지가 저장됩니다. 개발 환경에서만 사용되는 패키지를 devDependencies에 설치해줍니다.
물론 옵션 없이 설치해도 무방합니다.

그리고, TypeScript를 사용하기 위해서는 프로젝트에서 사용하는 패키지들에 대한 타입들을 정의한 패키지를 추가로 설치해주어야 합니다. 이러한 패키지들의 네이밍 컨벤션은 @types/package-name 입니다.

이 프로젝트의 경우 express를 사용하고 있으므로 @types/express를 설치해줍니다.

# express에서 사용되는 types 패키지 설치
npm i -D @types/express	

2-3. tsconfig.json 파일 설정

TypeScript를 사용하기 위해서는 프로젝트에 tsconfig.json이라는 이름을 가진 파일을 설정해줘야 합니다.

직접 파일을 생성할 수도 있겠지만, 터미널에 다음 라인을 입력해주면 프로젝트에 tsconfig.json 파일이 생성됩니다.

# tsconfig.json 파일 생성
npx tsc --init

생성된 tsconfig.json 파일을 열어보면 엄청나게 많은 옵션들이 있을텐데요, 각각의 옵션들에 대한 설명은 tsconfig.json (한글), 혹은 더 자세한 설명을 원하시면 TypeScript Compiler Options (영어) 를 참조하시기 바랍니다.

여기서는 프로젝트에 필요한 최소한의 옵션 몇 가지만 설정해주고 넘어가겠습니다.

{
  "compilerOptions": {
    "target": "es5",		// 컴파일 후 생성될 파일의 ECMAScript 버전
    "module": "commonjs",	// 컴파일 후 생성될 파일이 사용하는 모듈 버전
    "outDir": "dist/",		// 파일이 생성될 폴더
    "esModuleInterop": true	// 'require'와 'import' 호환
  },
  "include": ["src/*.ts"]	// 사용할 폴더 및 파일
}

2-4. TypeScript 적용

프로젝트의 app.js 파일 이름을 app.ts 파일로 변경해줍니다. 그리고 다음과 같이 1번째 줄을 import 문으로 변경해줍니다.

// 기존 코드: const express = require('express');
import express from 'express';	// express 불러오기

변경하는 이유는, require을 사용할 경우 express의 타입 추론이 any가 되기 때문입니다.

그리고 타입 추론이 잘 되는지 아무 곳이나 마우스를 올려 확인해봅니다. 저는 app.listen() 함수를 확인해봤습니다.

여기까지 되었으면 TypeScript 설정은 끝났습니다!

여기서 .ts 파일을 이용해 서버를 실행해보려면 한 가지 설정이 더 필요합니다. package.json 파일의 script 항목에 다음과 같은 줄을 추가합니다.

"scripts": {
  // .ts 파일 컴파일 후 생성된 .js 파일을 실행
  "start": "npx tsc && node dist/app.js"
}

npx tsc는 .ts 파일을 .js 파일로 컴파일하겠다는 의미이고, 그 뒤 node 명령을 통해 dist 폴더에 생성된 app.js 파일을 실행하게 됩니다.

그리고 다음과 같이 서버를 실행하면 됩니다.

# express app 실행
npm start

3. ESLint 설정

3-1. ESLint 설치

우선 npm을 통해 ESLint를 설치해줍니다.

# ESLint 설치
npm i -D eslint

3-2. .eslintrc.json 파일 설정

그 뒤 터미널에서 다음 명령을 실행합니다.

# .eslintrc.json 파일 생성 및 설정
npx eslint --init

tsconfig.json 파일을 생성할 때와는 다르게 여러 가지 사항을 물어볼텐데요, 프로젝트의 상황에 해당하는 답변들을 선택해주시면 되겠습니다.

저는 이 프로젝트에서 다음과 같이 설정해주었습니다.

  • How would you like to use ESLint?
    To check syntax and find problems
  • What type of modules does your project use?
    JavaScript modules (import/export)
  • Which framework does your project use?
    None of these
  • Does your project use TypeScript? (y/N)
    y
  • Where does your code run? (Press space to select, a to toggle all, i to invert selection)
    Node
  • What format do you want your config file to be in? (Use arrow keys)
    JSON
  • The config that you've selected requires the following dependencies:
    @typescript-eslint/eslint-plugin@latest @typescript-eslint/parser@latest
    Would you like to install them now with npm? (Y/n)
    Y

설정이 모두 끝나면, 해당 설정에 필요한 패키지들을 자동으로 설치합니다. 위와 같이 선택할 경우 @typescript-eslint/eslint-plugin, @typescript-eslint/parser 패키지들이 설치됩니다. (직접 eslintrc.json 파일을 생성할 경우에는 수동으로 설치해야 합니다)

패키지가 모두 설치되고 나면 프로젝트에 .eslintrc.json 파일이 생성됩니다. 생성된 .eslintrc.json 파일에 다음과 같은 설정을 추가해줍니다.

{
  ...
  "extends": [
    "eslint:recommended",
    "plugin:@typescript-eslint/eslint-recommended",
    "plugin:@typescript-eslint/recommended",
    "plugin:@typescript-eslint/recommended-requiring-type-checking"
  ],
  "parserOptions": {
    "project": "./tsconfig.json",
    "ecmaVersion": 2018,
    "sourceType": "module"
  },
  "ignorePatterns": ["dist/", "node_modules/"]
  ...
}

extends는 ESLint에 적용할 규칙들을 정의해주는 곳입니다. 나중에 정의된(= 밑에 있는) 옵션일수록 높은 우선 순위를 가집니다.
(설정 출처: typescript-eslint-plugin - Recommended Configs)

parserOptions.project는 타입 정보를 필요로 하는 규칙들을 사용하고 싶으면 설정해야 하는 속성입니다. (출처: @typescript-eslint/parser - ParserOptions.project)
프로젝트의 tsconfig.json 파일의 위치를 적어줍니다.

ignorePatterns는 ESLint가 무시할 폴더, 파일을 적어주는 옵션입니다.

이 밖에 ESLint의 자세한 설정을 알고 싶으시면 Configuring ESLint 를 참고하시기 바랍니다.

3-3. ESLint 적용 확인

설정이 끝나고 나면 app.ts 파일에 잘못된 문법을 가진 코드를 적어, 제대로 오류가 발생하는지 확인해 봅니다.

위와 같이 에러 및 경고가 잘 생성되면 ESLint 설정이 잘 끝난 것입니다!

4. Prettier 설정

4-1. Prettier 설치

마지막 단계인 Prettier 설정입니다.
마찬가지로 npm을 통해 패키지를 설치해줍니다.

# Prettier 설치
npm i -D prettier

그리고 ESLint와 Prettier가 서로 충돌이 되지 않고 잘 작동하도록 eslint-config-prettiereslint-plugin-prettier를 설치해줍니다.

# ESLint 호환
npm i -D eslint-config-prettier eslint-plugin-prettier

eslint-config-prettier는 Prettier와 충돌되는 ESLint 규칙들을 무시하는 설정이고, eslint-plugin-prettier는 Prettier를 사용해 포맷팅을 하도록 ESLint 규칙을 추가하는 플러그인입니다. (출처: Prettier - Integrating with Linters)

4-2. .eslintrc.json과 .prettierrc.json 파일 설정

우선 프로젝트 폴더에 .prettierrc.json 파일을 생성해줍니다. Prettier는 다른 툴들과 달리 직접 파일을 생성해줘야 합니다. 이 파일에서 설정할 수 있는 다양한 옵션들이 있는데, Prettier - Options 를 참고해서 원하시는 스타일로 설정하면 되겠습니다.

아래는 제가 설정한 스타일입니다.

{
  "printWidth": 80,			// 한 줄의 라인 수
  "tabWidth": 2,			// tab의 너비
  "useTabs": false,			// tab 사용 여부
  "semi": true,				// ; 사용 여부
  "singleQuote": true,			// 'string' 사용 여부
  "quoteProps": "consistent",		// 객체 property의 따옴표 여부
  "trailingComma": "es5",		// 끝에 , 사용 여부
  "bracketSpacing": true,		// Object literal에 띄어쓰기 사용 여부 (ex: { foo: bar })
  "arrowParens": "always",		// 함수에서 인자에 괄호 사용 여부 (ex: (x) => y)
  "endOfLine": "lf"			// 라인 엔딩 지정
}

그리고 ESLint도 설정을 해줘야 합니다. eslintrc.json 파일에서 다음과 같이 설정을 변경해줍니다.

{
  ...
  "extends": [
    "eslint:recommended",
    "plugin:@typescript-eslint/eslint-recommended",
    "plugin:@typescript-eslint/recommended",
    "plugin:@typescript-eslint/recommended-requiring-type-checking",
    "plugin:prettier/recommended",
    "prettier/@typescript-eslint"
  ],
  ...
}

ESLint에서 Prettier를 extends에 사용하기 위해 plugin:prettier/recommended, prettier/@typescript-eslint를 추가해주었습니다. (설정 출처: typescript-eslint - Usage with prettier, Prettier - Recommended configuration)

extends에 추가할 때 유의할 점은, 위에서 언급했듯이 아래에 있는 것일수록 우선 순위가 높습니다. 따라서 Prettier 관련 규칙들이 위의 코드처럼 목록의 최하단에 위치해야 합니다. (출처: eslint-config-prettier - Installation)

4-3. VSCode Format On Save 설정

내가 작성한 코드가 Prettier에 포맷팅이 맞지 않으면 수동으로 다 바꿔줘야 할까요? 아닙니다!
Preferences > Settings > Workspace > Editor: Format On Save 옵션에 체크해주면, 파일을 저장할 때마다 Prettier의 설정값에 맞춰 자동으로 파일이 포맷팅이 됩니다.

4-4. Prettier 적용 확인

여기까지 설정한 뒤, 확인을 해보겠습니다.
코드에 엔터를 여러 번 입력하면 아래 스크린샷처럼 ESLint에서 Prettier 관련 에러가 나타납니다.

그리고 Ctrl+s를 눌러 저장을 했을 때, Enter가 자동으로 없어진다면 설정이 잘 된 것입니다!

5. 최종 설정 파일들 내용

설정을 마친 뒤 최종적으로 설정 파일들의 내용을 모아서 보여드리겠습니다.

5-1. 프로젝트 구조

위의 사진과 같이 프로젝트 폴더에 .eslintrc.json, .prettierrc.json, tsconfig.json 설정 파일들이 각각 있습니다.
Format on Save 옵션을 설정해서 vscode의 설정 파일인 .vscode/settings.json 파일도 보이네요.

5-2. package.json

최종적으로 package.json의 dependency들은 다음과 같습니다.

...
"dependencies": {
  "express": "^4.17.1"
  },
"devDependencies": {
  "@types/express": "^4.17.6",
  "@typescript-eslint/eslint-plugin": "^2.27.0",
  "@typescript-eslint/parser": "^2.27.0",
  "eslint": "^6.8.0",
  "eslint-config-prettier": "^6.10.1",
  "eslint-plugin-prettier": "^3.1.3",
  "prettier": "^2.0.4",
  "typescript": "^3.8.3"
}
...

5-3. tsconfig.json

2-3. tsconfig.json 파일 설정 내용과 같습니다.

{
  "compilerOptions": {
    "target": "es5",
    "module": "commonjs",
    "outDir": "dist",
    "esModuleInterop": true,
  },
  "include": ["src/*.ts"]
}

5-4. .eslintrc.json

{
  "env": {
    "es6": true,
    "node": true
  },
  "extends": [
    "eslint:recommended",
    "plugin:@typescript-eslint/eslint-recommended",
    "plugin:@typescript-eslint/recommended",
    "plugin:@typescript-eslint/recommended-requiring-type-checking",
    "plugin:prettier/recommended",
    "prettier/@typescript-eslint"
  ],
  "globals": {
    "Atomics": "readonly",
    "SharedArrayBuffer": "readonly"
  },
  "parser": "@typescript-eslint/parser",
  "parserOptions": {
    "project": "./tsconfig.json",
    "ecmaVersion": 2018,
    "sourceType": "module"
  },
  "plugins": ["@typescript-eslint"],
  "rules": {},
  "ignorePatterns": ["dist/", "node_modules/"]
}

5-5. .prettierrc.json

4-2. .eslintrc.json과 .prettierrc.json 파일 설정 파일 내용과 동일합니다.

{
  "printWidth": 80,
  "tabWidth": 2,
  "useTabs": false,
  "semi": true,
  "singleQuote": true,
  "quoteProps": "consistent",
  "trailingComma": "es5",
  "bracketSpacing": true,
  "arrowParens": "always",
  "endOfLine": "lf"
}

6. 마치며

이 글에서는 Express 앱에 대해서 환경 설정을 진행했지만, TypeScript를 사용하는 프로젝트라면 설정 방법은 비슷합니다.

TypeScript, ESLint, Prettier를 같이 쓰기 위해서 필요한 설정이 아주 간단하지는 않습니다. 하지만 초기에 이렇게 한 번만 설정해두면 코드를 짤 때 굉장히 편하게 짤 수 있습니다. 그리고 ESLint에 발생하는 에러들을 잡으면서 줄어드는 에러 수에 희열을 느낄 수도 있어요!

원래 여기에 React 사용 환경 및 ESLint에 Airbnb 규칙을 적용하는 것까지 적으려고 했는데 시간이 생각보다 많이 걸리네요... 그 내용은 다음 편에 적어보도록 하겠습니다.

긴 글 읽어주셔서 감사합니다!

4개의 댓글

comment-user-thumbnail
2020년 5월 9일

너무 유익합니다 ^^

답글 달기
comment-user-thumbnail
2020년 8월 19일

매번 설정하는거 복잡했는데, 깔끔하게 정리 잘해주셨네요. 감사합니다!

답글 달기
comment-user-thumbnail
2021년 1월 9일

감사합니다 잘 읽었습니다.

답글 달기
comment-user-thumbnail
2021년 2월 1일

감사합니다!!

답글 달기