LHJ

I'm a FE developer.

Prettier

02 Oct 2020 » node_webpack2

Prettier

프리티어는 코드를 “더” 이쁘게 만든다.
ESLint의 역할 중 포매팅과 겹치는 부분이 있지만 프리티터는 좀 더 일관적인 스타일로 코드를 다듬는다.
반면 코드 품질과 관련된 기능은 하지 않는 것이 ESLint와 다른 점이다.

ESLint의 기능이 두 가지라고 했다.

  1. 코드를 일관적으로 만들어주는 포매팅
  2. 코드 품질을 담당

ESLint의 포매팅을 더 강화한 것이 프리티어라고 이해하면 된다.

설치 및 사용 방법

npm i -D prettier
// app2.js
console.log()

ESLint에서는 ESLint 설정에 따라 ; 세미콜론을 써도되고 안 써도 됐다.
프리티어는 세미콜론을 어떻게 처리할까?

npx prettier app2.js

세미콜론이 뒤에 붙은걸 확인할 수 있다.
만약 파일 자체를 변경하고 싶다면 아래와 같이 --write 옵션을 준다.

npx prettier app2.js --write

app2.js 파일이 수정된 것을 확인할 수 있다.
반대로 ;;;;; 세미콜론이 여러개 붙어있다고 해도 한개로 일관되게 고쳐준다.

그리고 프리티어의 강점은 ESLint가 고칠 수 없는, 그래서 개발자에게 직접 고치라고 던져주는 코드도 프리티어가 자동으로 고쳐준다.
예를 들어 다음과 같다.

// app2.js
console.log('-------------------------------------------------------------매우 긴 문장입니다. 80자가 넘는 코드입니다.---------------------------------------------------------------');

보통 에디터에는 위와 같이 몇자 이상 넘어가지 말자는 설정이 되어있다.
이 설정은 물론 변경해 줄 수 있다.
아마 기본은 대부분 80자일거다.

ESLint 같은 경우는 max-length라는 규칙을 이용해서 위 코드를 검사한다.
검사하고 개발자에게 알려주기만 한다.
그런데 프리티어는 어떻게 다른지 확인해보자.

npx prettier app2.js --write

자동으로 개행시켜주는 걸 확인할 수 있다.

foo(test(), test2(), test3(), test4(), test5(), test6(), test7(), test8(), test9(), test10(), test11(), test12(), test13(), test14(), test15(), test16())

이런식의 코드는 프리티어가 어떻게 고치는지 확인해보자.

보시면 함수인자라는 것을 인식해서 좀 더 읽기 쉬운 코드로 변환해준다.
그러면 ESLint 뿐만아니라 Prettier 까지 같이 써야될 거 같은 느낌이 든다.
왜냐하면 프리티어가 포매팅을 더 이쁘게 해준다고 하더라도 ESLint가 코드 품질을 담당해주기 때문에 같이 써야된다.
프리티어가 코드 품질까지 담당하진 않는다.

결론은 ESLint와 Prettier를 둘 다 실행해야될 거 같은데, 그러면 좀 불편하겠지?
하나로 통합해서 사용하는 것이 더 편리할 것 같다.
그래서 Prettier는 ESLint와 통합할 수 있는 방법을 제공한다.

ESLint와 Prettier 통합방법

여전히 ESLint를 사용해야 하는 이유는 남아 있다.
포맷팅은 프리티어에게 맡기더라도 코드 품질과 관련된 검사는 ESLint의 몫이기 때문이다.
따라서 이 둘을 같이 사용하는 것이 최선이다.
프리티어는 이러한 ESLint와 통합 방법을 제공한다.
eslint-config-prettier는 프리티어와 충돌하는 ESLint 규칙을 끄는 역할을 한다.
둘 다 사용하는 경우 규칙이 충돌하기 때문이다.

npm i -D eslint-config-prettier

이 라이브러리는 확장가능한 설정이기 때문에 .eslintrc.js에 추가할 수 있다.

// .eslintrc.js
module.exports = {
    "env": {
        "browser": true,
        "es2021": true
    },
    "extends": [
        "eslint:recommended",
        "eslint-config-prettier"
    ],
    "parserOptions": {
        "ecmaVersion": 12,
        "sourceType": "module"
    },
    "rules": {
    }
};

위와 같이 설정하면 eslint:recomended 에 있는 규칙 중에 prettier와 겹치는 게 있다면 eslint-config-prettier가 해당 규칙을 꺼버린다.

// app2.js
var foo = '';

console.log();;;;;;

위와 같이 사용하지 않는 변수 foo를 ESLint는 에러로 잡을 것이다.
하지만 자동으로 삭제하진 않는다.
반면 세미콜론 여러개 붙은거는 ESLint도 자동 수정할 수 있다.

하지만 방금 세팅한 "eslint-config-prettier"에 의해 ESLint에 있는 중복 세미콜론 지우기 규칙disabled 처리할 것이다.
그리고 prettier가 스스로 수정한다.

npx eslint app2.js --fix

보시면 중복된 세미콜론은 체크하지 않고 사용하지 않는 변수 foo에 대해서만 체크했다.
대신에 프리티어가 세미콜론을 처리할 것이다.

npx prettier app2.js --write

그런데 이것도 불편하다.
매번 eslint, prettier 따로 돌리는 것은 불편한 작업이다.
이걸 한번에 돌려줄 수 있는 방법이 있다. 이 또한 프리티어에서 제공하는 방법이다.

  • eslint-plugin-prettier

위 모듈은 프리티어에 있는 모든 규칙을 eslint로 넣어버린다.
그래서 eslint만 돌리면 프리티어까지 같이 돌려지는 효과가 있다.

npm i -D eslint-plugin-prettier
// .eslintrc.js
module.exports = {
    "env": {
        "browser": true,
        "es2021": true
    },
    "extends": [
        "eslint:recommended",
        "eslint-config-prettier"
    ],
    "parserOptions": {
        "ecmaVersion": 12,
        "sourceType": "module"
    },
    plugins: [
        "prettier"
    ],
    "rules": {
        "prettier/prettier": "error"
    }
};

그리고 위와 같이 pluginsprettier를 추가하고 rules에 프리티어 규칙을 어기면 에러를 반환하라는 의미를 가진 키값을 넣어준다.
그리고 아까처럼 app2.js를 작성해보자.

// app2.js
var foo = "";

console.log();;;;;;;;;;;

첫줄은 eslint가 마지막줄은 prettier가 담당하는데, 지금은 prettier의 규칙을 모두 eslint로 넣어버렸기 때문에 eslint 만 실행시키면 위 코드가 고쳐질 것이다.

npx eslint app2.js --fix

세미콜론이 다 지워진걸 볼 수 있고 사용하지 않는 foo 변수에 대해 리포팅하는 걸 확인할 수 있다.

이렇게 세팅해도되고 다른 방법도 있다.
이 방법은 문서에 나온 방법이다.

ESLint와 Prettier를 동시에 쓰려면 npm으로 두 개의 패키지를 설치하고,

// .eslintrc.js
module.exports = {
    "env": {
        "browser": true,
        "es2021": true
    },
    "extends": [
        "eslint:recommended",
        "eslint-config-prettier",
        "plugin:prettier/recommended"
    ],
    "parserOptions": {
        "ecmaVersion": 12,
        "sourceType": "module"
    },
    "rules": {
    }
};

위와 같이 설정하면 된다.