본문 바로가기
Search/Code Formatter & Linter

Prettier vs Beautify

by egas 2021. 8. 10.

Code Formatter란 개발자가 작성한 코드를 정해진 코딩 스타일을 따르도록 변환해주는 도구를 뜻한다.

 

VSCode Extension 중 Javascript Code Formatter로는 대표적으로 PrettierBeautify가 존재한다.

 

Prettier
Beautify

TL;DR

custom .prettierrc

{
  "singleQuote": true,
  "trailingComma": "all",
  "printWidth": 120
}

 

기능적인 지원에서는 Prettier가 Beautify보다 적은 명령어를 보유하고 있음에도 불구하고 훨씬 다양했다(e.g. arrow function, JSX 고려 등). 옵션 이름에서도 Beautify보다 Prettier가 명확하고 다양한 기능을 제공한다는 것을 한눈에 알 수 있다. 또한, Prettier는 여러 형식(e.g. babel, markdown, graphql, yml, typescript 등 21개의 다양한 형식을 지원한다.)을 지원하고 있다. 기능이 더 다양함에도 Prettier의 Option 개수가 적은 이유는 스타일에 대한 모든 진행 중인 논쟁을 중단하는것에 목적이 있기 때문이다. 따라서, 최소한의 논쟁의 여지가 있는  Option들을 제외하고는 스타일을 강제한다.

 

beautify보다 prettier의 option들이 간단하고 의미도 명확함을 알 수 있다.

beautify
prettier

Code Formatter에 대해서 VSCode를 사용한다면 workspace setting의 Format On Save를 체크하면 ctrl + s를 누를 때마다 Code Formatting을 해준다.

따라서, 이 게시물에서는 인지도도 높고, 기능 측면에서도 많고, 활발한 기여(최근 커밋 beautify: 1월, prettier 10분 전..)가 이뤄지고 있는 prettier에 대해 자세히 알아볼 예정이다.

Beautify

Code>Preferences>Keyboard Shortcuts를 누르면 단축키를 설정할 수 있다.

beautify에서 html 파일은 아래와 같이 정렬된다.

before html formatting
after html formatting

Prettier와 한 가지 차이점이 눈에 띄었는데, 첫 번째 줄 개행 길이를 기준으로 formatting이 된다는 사실이다.

before js formatting
after js formatting

Prettier

아래 동영상은 Prettier를 만들면서 고민한 주요 원칙들에 대한 내용을 담고 있다.

Javascript code formatting - Christopher Chedeau, React London 2017

 

사람마다 여러 가지 스타일이 존재한다. 최소한의 option을 제공하기 위해 Prettier는 여러가지 사람마다 의견이 나뉘는 방식들에 대해서만 option을 제공한다. 아래는 Prettier의 주요 두 가지 규칙이다. 여러가지 스타일 중에 Prettier가 코드 형식을 맞춰주기 위해서 얼마나 많은 고민을 했는지 보인다.

Rule #1: If it fits in one line, stay in one line

Rule #2: Always break the outer one first

 

Prettier의 3가지 주요 원칙을 정했다. Prettier는 이 3가지 원칙을 중심으로 코드를 정제한다. (링크)

  • group
  • indent
  • ifBreak

prettier: conver IR Commands

아래는 AST이며, Prettier의 Printer는 분석된 AST를 이용해서 코드를 정제한다. IR(Intermediate Representation: 중간표현)은 AST 노드가 어떤 형식으로 바뀔지 서술한다.

 

IR Command (IR: Intermediate Representation)들은 다음 링크에서 확인 가능하다.

자세한 Prettier의 printer 알고리즘에 대한 이론은 Prettier PDF에서 확인 가능하다.

AST에 대한건 자바스크립트 개발자를 위한 AST(번역)을 참고하자.

AST
prettier 정제 과정

Code Formatter를 만드는 일은 쉬운 일이지만, 잘 만들기란 어렵다.

 

예를 들어서, 일관성 있게 #1과 같이 작성하고 싶은 사람도 있는 반면, 어떤 사람들은 의미론적으로 #2로 작성하길 원할 수도 있다. keys는 Object의 메서드로 한 group으로 묶고 싶을 수도 있기 때문이다.

// #1
Object
  .keys(items)
  .map(() => {})
  .filter(() => {})
// #2
Object.keys(items)
  .map(() => {})
  .filter(() => {})

 

이외에도 Prettier를 구현하는데 많은 애매모호하고 어려운 부분들이 존재한다. 아래 코드를 보자. Prettier는 #1을 어떻게 해석할지도 결정해야 한다.

 

// #1
<div
	{ ...a === null ? : b : c }
/>
// #2
<div
	{ ...(a === null ? : b : c) }
/>

 

위 예시는 굉장히 드문 케이스라면 아래는 조금 더 평범한 케이스다. 

 

// #1
a && b || c && d
// #2
(a && b) || (c && d)

 

 

위의 코드는 연산자 우선순위로 결정할 수 있는 문제라면, 아래는 진짜 선호도의 문제이다. 이런 선택지를 어떻게 제공하는 게 좋은지 고민이 많이 된다.

facebook의 같은 프로젝트 코드에서 조차 개인 취향에 따라 다른 방식이 쓰이고 있다.

 

Rule #1: I can't push it on people, people have to pull it themselves

문법에서 선호도로 확실하게 나뉘지 않는 부분에 대해서는 강제하고 있다. 대신에 prettier는 몇 가지 선호도로 나뉘는 사항에 대해서만 options을 제공하려고 한다. Prettier를 채택한 가장 큰 이유는 스타일에 대한 모든 진행 중인 논쟁을 중단하는 것이다. 그러나 Prettier가 선택할 수 있는 옵션이 많을수록 위의 목표에서 더 멀어진다. 스타일에 대한 논쟁은 어떤 Prettier 옵션을 사용할 것인지에 대한 논쟁으로 바뀌게 된다. (Prettier Option Philosophy) Prettier는 이를 원하지 않는다.

또한, Prettier는 최소한의 비용을 투자해서 최대의 효과를 내기를 바란다. 때문에 단순 diff를 넘어서 문법 교정 기능도 제공한다.

 

아마 Prettier를 쓰는 주요 이유들에는 새로운 팀원이 팀에 배치되었을 때, 세세한 형식 교정에 쓰이는 시간을 줄이고, 자잘한 문법으로 다시 Version Control을 바꾸는 비용을 줄이기 위해서 등이 있다.

Rule #2: It's a journey that takes time

이미 많은 Javascript 진영에서 Prettier 가 제공되고 있다. (React, Jest, Immutable etc...) 이제 Prettier의 여정에 동참해보자!

 

Feature

VSCode Workspace Settings > Extensions > Prettier에서 VSCode의 기본 Workspace option을 설정할 수 있다. 또한,. vscode/settings.json으로도 설정할 수 있다.

 

VSCode에서 적용되는 Prettier 옵션의 설정 파일의 우선순위는 아래와 같다.

settings.json < .editorconfig < .prettierrc 

 

printWidth (default: 80)

한 줄의 길이를 정의한다. 설정한 글자 수가 넘게 되면 코드가 정리된다. 필자의 경우 120이 코드 읽기에 가장 적합했다.

tabWidth (default: 2)

들여 쓰기 공백수를 정의한다. Toast 코딩 컨벤션에서는 들여쓰기 2를 사용해서, 필자도 2로 사용한다.

useTabs (default: false)

  • true: 탭을 사용하여 들여 쓴다.
  • false: 공백을 사용하여 들여 쓴다.

semi (default: true)

  • true: 모든 문장의 끝에 세미콜론을 추가한다.
  • false: ASI 실패를 유발할 수 있는 줄의 시작 부분만 세미콜론을 추가한다.

singleQuote (default: false)

  • JSX 따옴표는 이 옵션을 무시한다.
  • 필자는 true: '' 를 사용한다. 

quoteProps (default: as-needed)

개체의 속성이 인용될 때 변경한다.

jsxSingleQuote (default: false)

  • false: JSX에서 작은따옴표를 사용한다.
  • true: JSX에서 큰따옴표를 사용한다.

trailingComma (default: es5)

  • es5: ES5에서 유효한 경우 후행 쉼표(객체, 배열 등)를 사용한다. 단, TypeScript의 유형 매개변수에 후행 쉼표가 없다.
  • none: 뒤에 쉼표를 사용하지 않는다.
  • all: 가능하면 후행 쉼표(함수 매개변수 및 호출 포함)를 사용한다. TypeScript의 유형 매개변수에 후행 쉼표를 사용할 수 있다. (TypeScript 2.7부터 지원)

bracketSpacing (default: true)

객체 리터럴에서 대괄호 사이에 공백을 인쇄한다

  • true: { foo: bar }
  • false: {foo: bar}

jsxBracketSameLine (default: false)

  • true
    • <button
        className="prettier-class"
        id="prettier-id"
        onClick={this.handleClick}>
        Click Here
      </button>
  • false
    • <button
        className="prettier-class"
        id="prettier-id"
        onClick={this.handleClick}
      >
        Click Here
      </button>

arrowParens (default: always)

  • always: (x) => x
  • avoid: x => x

rangeStart, rangeEnd (default: 0~Infinity)

prettier를 적용할 파일의 범위

parser (default: None)

Prettier는 입력 파일 경로에서 자동으로 파서를 유추하므로 이 설정을 변경할 필요가 없다.

filepath (default: None)

사용할 파서를 유추하는 데 사용할 파일 이름을 지정한다.

requirePragma (default: false)

Prettier는 파일 상단에 pragma라고 하는 특별한 주석이 포함된 파일만 포맷하도록 제한할 수 있다. 이것은 형식이 지정되지 않은 대규모 코드 베이스를 Prettier로 점진적으로 전환할 때 매우 유용하다.

insertPragma (default: false)

Prettier는 @format파일이 Prettier로 포맷되었음을 지정하는 특수 마커를 파일 상단에 삽입할 수 있다. requirePragma와 같이 사용할 경우, insertPragma는 무시된다.

proseWrap (default: preserve)

마크 다운에서 공백 및 줄 바꿈 같은 것이 중요한 요소이므로 여러 줄에 걸쳐 산문을 랩핑을 한다.

htmlWhitespaceSensitivity (default: css)

HTML, Vue, Angular 및 Handlebars에 대한 전역 공백 감도를 지정할 수 있다. (참고 링크)

vueIndentScriptAndStyle (default: false)

Vue 파일 내부의 코드 <script>와 <style>태그의 들여쓰기 여부를 결정할 수 있다.

  • true: Vue 파일에서 스크립트 및 스타일 태그 들여 쓴다.
  • false: Vue 파일에서 스크립트 및 스타일 태그를 들여 쓰지 않는다.

endOfLine (default: lf)

OS에 따라서 EOL의 기준이 다 다르다. \n (LF)는 Linux 및 macOS에서 일반적이고, \r\n (CRLF)는 Windows에서 사용된다.

  • lf: Line Feed only (\n)
  • crlf: Carriage Return + Line Feed characters (\r\n)
  • cr: Carriage Return character only (\r)
  • auto: 첫 번째 줄 사용 패턴을 보고 이후 EOL 결정

embeddedLanguageFormatting (default: off)

  • auto: Prettier가 자동으로 식별할 수 있는 경우 포함된 코드를 포맷한다.
  • off: 포함된 코드를 자동으로 포맷하지 않는다.

모두 prettier의 여정에 함께하자.

728x90

'Search > Code Formatter & Linter' 카테고리의 다른 글

husky && lint-staged  (0) 2021.08.12
Javascript Linter 조사  (0) 2021.08.10
ESLint를 설정해보자!  (0) 2021.05.23

댓글