프로젝트를 시작할 때 하게 되는 첫번째 일은 개발 환경 세팅일 것이다. 나 역시도 몇 번의 개발 환경 세팅을 경험해봤다. 프론트엔드는 개발 환경을 세팅할 때 lint 설정이라는 것을 한다. 지금까지 내가 알고 있는 lint는 여러 사람들이 코드를 짤 때 통일성 있게 코드를 짤 수 있게 도와주는 도구이다. 하지만 이 정도만 알고 있을 뿐 정확한 기능과 세팅 방법, 커스텀 방법도 잘 모른다. 게다가 lint와 함께 언급되는 prettier의 정확한 기능을 아직까지 제대로 인지하지 못한 상태이다. 오늘은 lint와 prettier에 대해서 알아보겠다.
소스 코드를 분석하여 프로그램 오류나 버그, 스타일 오류, 의심스로운 구조체에 표시를 달아놓기 위한 도구를 말한다. 즉,
VSCode의 Plugin에 lint
를 검색하면 아래의 이미지와 같이 다양한 플러그인을 찾을 수 있다.
다른 사람과 협업을 할 때 각자 사용하는 코드의 형식이 다르기 때문에 이를 맞춰주기 위해 사용한다. 대부분의 프로그래밍 언어에는 컴파일 과정에서 수행되는 Linter(Lint의 동작을 도와주는 도구)가 기본적으로 내장되어 있지만, 자바스크립트는 컴파일 과정이 없는 인터프리터 언어이기 때문에 Linter가 내장되어 있지 않다. 때문에 런타임 환경에서 에러가 발생할 수 있다. 그렇기 때문에 lint를 이용해 소스 코드를 작성할 때, 사전에 에러들을 발견하고 해결하는 것이 중요하다.
현재 자바스크립트는 대부분 ESLint를 사용하는 추세이다.
타입스크립트에는 TSLint가 있었으나 deprecated되었고 결국엔 ESLint를 사용하고 있다.
ESLint는 EcmaScript(JavaScript)와 Lint를 합친 것으로 자바스크립트 문법에서 에러가 발생하면 표시해주는 도구이다. 뿐만 아니라 전반적인 코딩스타일까지 지정할 수 있으므로 협업에 유용한 도구이다.
💡 EcmaScript는 Ecma라는 기구에서 만든 Script라는 뜻이로 표준 JavaScript를 의미한다.
function fn() {
// ...
}
var fn = function () {
// ...
}
var fn = function test() {
// ...
}
var fn = (function () {
// ...
})()
var fn1 = (function (value = 0) {
let cnt = value
return function () {
cnt++
return cnt
}
})(1)
fn1() // 2
fn1() // 3
fn1() // 4
var fn = new Function()
var fn1 = new Function('a', 'b', 'return a + b')
fn1(2, 6)
var fn = () => {
// ...
}
const data = [0, 1, 2, 3, 4];
for(let i = 0; i < data.length; i++) {
console.log(i);
}
data.forEach((item) => console.log(item));
for(const item of data) {
console.log(item);
}
for(const key in data) {
console.log(data[key]);
}
여러가지 방식으로 구현할 수 있기 때문에 코드 방식을 일관성 있게 구현할 수 있도록 잡아주는 것이 ESLint가 하는 역할이다.
코드 포맷의 통일성을 유지시켜주는 JavaScript 라이브러리이다.
정리하자면 ESLint가 코드 퀄리티를 일관적으로 유지해준다면,
Prettier는 일관적인 코드 스타일을 유지할 수 있게 도와주는 툴이다.
function HelloWorld({greeting = "hello", greeted = '"World"', silent = false, onMouseOver,}) {
if(!greeting){return null};
// TODO: Don't use random in render
let num = Math.floor (Math.random() * 1E+7).toSTring().replace(/\. \d+/ig, "")
return <div className='HelloWorld' title={`You are visitor number ${ num }`} onMouseOver={onMouseOver}>
<strong>{ greeting.slice(0, 1).toUpperCase() + greeting.slice(1).toLowerCase() }</strong>
{greeting.endsWith(",") ? " " : <span style={{color: '\grey'}}>", "</span> }
<em>
{ greeted }
</em>
{ (silent)
? "."
: "!"}
</div>;
}
function HelloWorld({
greeting = "hello",
greeted = '"World"',
silent = false,
onMouseOver,
}) {
if (!greeting){
return null;
}
// TODO: Don't use random in render
let num = Math.floor (Math.random() * 1E+7)
.toSTring()
.replace(/\. \d+/ig, "");
return (
<div
className="HelloWorld"
title={`You are visitor number ${num}`}
onMouseOver={onMouseOver}
>
<strong>
{greeting.slice(0, 1).toUpperCase() + greeting.slice(1).toLowerCase()}
</strong>
{greeting.endsWith(",") ? (
" "
) : (
<span style={{color: '\grey'}}>", "</span>
)}
<em>{greeted}</em>
{silent ? "." : "!"}
</div>;
}
yarn add -D eslint
-D로 설치하는 이유
-D로 설치하면 package.json에 개발 시에만 사용하는 개발 의존성(devDependencies)으로 기록된다. 개발 의존성으로 설치된 패키지는 --production 옵션을 통해 운영 버전에서는 설치되지 않게 할 수 있다.
yarn eslint --init
주어진 질문에 답을 하면서 자신에게 알맞은 옵션들을 설정하면 아래와 같은 파일이 만들어진다.
// .eslint.cjs
module.exports = {
"env": {
"browser": true,
"es2021": true
},
"extends": [
"plugin:react/recommended",
"standard-with-typescript"
],
"overrides": [
],
"parserOptions": {
"ecmaVersion": "latest",
"sourceType": "module"
},
"plugins": [
"react"
],
"rules": {
// 원하는 룰 추가
}
}
// package.json
{
// ...
"devDependencies" : {
// ...
"eslint-config-standard-with-typescript": "^39.1.0",
"eslint-plugin-import": "^2.25.2",
"eslint-plugin-n": "^15.0.0 || ^16.0.0 ",
"eslint-plugin-promise": "^6.0.0",
"eslint-plugin-react": "^7.33.2",
}
}
lint 설정을 위해 중요한 부분은 plugins
, extends
, rules
이다.
root
true
이며, true
가 아니라면 eslintrc 파일을 찾을 때 상위의 디렉터리까지 검색하게 된다.root
가 없는 이유는 default가 true
였기 때문인 것 같다.env
"browser": true
라면 console.log()
를 에러 없이 사용할 수 있다."node": true
를 하게 되면 require
를 에러 없이 사용할 수 있다.extends
extends
에 추가해준다.extends
를 통해 plugin을 통째로 가져와 사용한다."extends": [
"eslint:recommended",
"plugin:@typescript-eslint/recommended"
],
parser
yarn add -D @typescript-eslint/parser
parserOptions
"parserOptions": {
"ecmaFeatures": {
"jsx": true
},
"ecmaVersion": 2020,
"sourceType": "module"
}
plugins
plugins
에 추가된다고 해서 바로 적용되는 것은 아니다. extends
나 rules
설정을 해야 적용할 수 있다.rules
각종 lint 룰 설정을 위해서는 프로젝트의 루트 디렉터리에 .eslintrc 파일을 만들어서 작성해줘야 한다. 위의 과정을 진행했다면 이미 파일이 생성되었으므로 따로 만들 필요는 없다. .eslintrc 파일의 확장자는 js, json, yml 등 다양하게 설정할 수 있다.
.eslintrc 파일에 사용할 수 있는 확장자 종류는 js, cjs, yaml, yml, json이 있다.
우선 순위는 다음과 같다.
.eslintrc.js > .eslintrc.cjs > .eslintrc.yaml > .eslintrc.yml > .eslintrc.json > package.json
yarn add -D prettier
ESLint처럼 설정 파일이 필요하며 각종 옵션을 직접 설정할 수 있다.
자세한 설정 항목은 이 곳을 참고하자 여기에도 잘 나와있다
{
"printWidth": 100, // 줄 바꿈할 줄 길이
"tabWidth": 2, // 들여쓰기 공백 수
"semi": true, // 명령문 끝에 세기콜론 인쇄
"singleQuote": true, // 인용 부호 ("대신 ')
"trailingComma": "all", // 후행 쉼표
"endOfLine": "auto" // 줄 끝 (auto: 기존 줄 끝 유지)
/*
"singleAttributePerLine": false // HTML, JSX에서 한 줄에 단일 속성 적용
*/
}
ESLint의 plugin들의 rule 중 스타일과 관련된 것들도 있기 때문에 종종 Prettier와 충돌하는 일이 생긴다.
이를 방지하기 위해 아래 두 가지 plugin을 이용할 수 있다.
eslint-plugin-prettier
: prettier를 ESLint plugin으로 추가한다. 즉, prettier가 인식하는 코드 포맷 오류를 ESLint 오류로 출력하도록 할 수 있다. (하지만 사용하지 말자. 특정 상황에서 유용할 수도 있지만 prettier를 직접 실행하는 것보다 느리다.)eslint-config-prettier
: ESLint의 코드 포맷과 관련된 rule 중 prettier와 충돌하는 부분을 비활성화할 수 있다.// .eslintrc
{
// eslint-config-airbnb의 설정 추가
// eslint-config-pretteir로 충돌되는 옵션 꺼버린다.
// prettier를 extends의 마지막에 추가한다.
"extends": ["airbnb", "prettier"]
}
멋져요!