프로젝트를 하다 보면, 코드 스타일 가이드의 중요성을 다시금 느끼게 됩니다. 코드 스타일 가이드가 있으면, 내가 작성하지 않은 코드라도 쉽게 이해할 수 있고, 특히 여러 명이 함께하는 팀 프로젝트에서는 효과가 더 커집니다. 혼자 하는 프로젝트에서도 도움이 됩니다. 며칠 전에 쓴 코드가 낯설게 느껴질 때가 있는데, 일관된 스타일을 유지하면 파악이 훨씬 빨라지기 때문입니다.
그래서 이번에는 React + TypeScript + Vite 환경에서 널리 쓰이는 코드 스타일 가이드를 찾아보고, 적용해보기로 결심했습니다.
막상 직접 설정해보니 생각보다 오래 걸렸고, 시행착오도 많았습니다.
이렇게 고생하면서 배운 내용을 정리해두면 다음에는 더 빠르고 쉽게 설정할 수 있을 것 같아, 이 글을 통해 코드 스타일 가이드의 필요성부터 ESLint와 Prettier를 설정하는 과정, 그리고 그 이유와 방법까지 정리해보고자 합니다.
코드 스타일 가이드는 프로그래머가 따라야 하는 일련의 규칙
또는 지침
으로, 코드가 일관되고 읽기 쉬운 방식
으로 작성될 수 있도록 도와줍니다. 단순히 들여쓰기나 줄바꿈 같은 포맷팅만 다루는 것이 아니라, 변수와 함수의 네이밍, 주석 작성 방식, 함수 분리 기준, 예외 처리 등 코드 전반에 걸친 Best Practice를 포함합니다.
일관된 코드를 작성하는 것은 단순히 '보기 좋은 코드'를 넘어서, 프로젝트의 유지보수
와 협업
효율성을 극대화하는 데 필수적입니다.
예를 들어, 우리가 글을 쓸 때 맞춤법, 띄어쓰기, 문장 부호 등에 대한 기본적인 규칙을 지키지 않는다면, 글을 읽는 사람은 내용을 쉽게 이해할 수 없습니다.
예시로 다음 문장을 생각해볼 수 있습니다.
'아버지가방에들어가신다.'
'아버지가 방에 들어가신다.'
'아버지 가방에 들어가신다.'
띄어쓰기를 무시하면, 첫 번째 문장이 ‘아버지가 방에 들어가신다’는 뜻인지, ‘아버지 가방에 들어가신다’는 뜻인지 알기 어렵습니다.
이처럼 글에도 읽기 쉽고 혼동을 줄이기 위한 규칙이 필요하듯, 코드에도 스타일 가이드라는 규칙이 필요합니다.
여러 명이 함께 작업하는 팀 프로젝트에서 코드 스타일이 통일되어 있으면, 내가 작성하지 않은 코드라도 쉽게 의도를 파악
할 수 있고, 새로 운 팀원이 합류 하더라도 빠르게 적응할 수 있습니다.
코드 스타일 가이드를 머릿속으로 기억하며 지키는 것도 좋지만, 실제 프로젝트에서는 도구를 활용해 자동으로 관리하는 것이 훨씬 효율적입니다. 여기서 대표적으로 사용되는 두 가지 도구가 바로 ESLint와 Prettier입니다.
ESLint는 자바스크립트와 타입스크립트 코드를 위한 정적 분석(linting) 도구입니다.
이 도구는 코드를 분석해 잠재적인 버그, 코드 품질 문제, 그리고 코드 스타일 위반 사항을 찾아냅니다. ESLint의 가장 큰 특징은 다양한 규칙을 내 프로젝트에 맞게 맞춤 설정할 수 있다는 점입니다.
즉, 코드가 팀 또는 프로젝트에서 정한 규칙을 잘 따르고 있는지 자동으로 검사해주고, 일부 문제는 자동으로 고칠 수도 있습니다
Prettier는 코드 포매터(formatter)입니다.
Prettier의 목적은 코드의 모양(들여쓰기, 줄바꿈, 따옴표, 세미콜론 등)을 일관되고 보기 좋게 자동으로 맞춰주는 것입니다. Prettier는 코드의 의미나 동작에는 관여하지 않고, 오직 "어떻게 보이는가"에만 집중합니다. 설정 옵션이 적고, 대부분의 포맷을 Prettier가 알아서 처리하기 때문에 개발자 간의 포맷팅 논쟁을 줄여줍니다
ESLint는 코드 품질과 버그 예방, 스타일 규칙 준수가 필요할 때 사용합니다.
예를 들어, 변수 선언 실수, 사용하지 않는 변수, 잘못된 스코프 사용 등 코드 동작에 영향을 줄 수 있는 문제를 잡아냅니다.
팀 프로젝트, 오픈소스, 개인 프로젝트 등 모든 규모에서 코드의 신뢰성과 일관성을 높이고 싶을 때 필수입니다.
Prettier는 코드 포맷팅을 자동화하고 싶을 때 사용합니다.
들여쓰기, 줄바꿈, 따옴표, 세미콜론 등 코드의 "모양"을 빠르고 일관되게 맞춰줍니다. 포맷팅에 드는 시간을 줄이고, 코드를 더 읽기 쉽게 만드는 데 도움이 됩니다.
보통 ESLint와 함께 사용하며, Prettier
가 포맷팅
을 담당하고 ESLint
가 코드 품질
을 담당하도록 설정하는 것이 일반적입니다.
도구 | 주요 역할 | 주로 다루는 것 |
---|---|---|
ESLint | 코드 품질 검사, 버그 탐지, 스타일 규칙 강제 | 코드의 동작, 코드 스타일, Best Practice |
Prettier | 코드 포맷팅 자동화, 일관된 코드 스타일 | 들여쓰기, 줄바꿈, 따옴표 등 코드의 모양 |
Prettier
는 코드를 예쁘게
만들어주고, ESLint
는 코드를 올바르게
만들어주는데 도움을 주는 도구입니다. 둘을 함께 사용하면, 코드의 품질과 스타일을 모두 자동으로 관리할 수 있습니다.
JavaScript나 TypeScript 프로젝트에서 ESLint와 Prettier를 대체할 수 있는 도구가 있는지 찾아보던 중, Biome이라는 새로운 도구를 발견했습니다.
Biome은 웹 프로젝트의 품질을 유지하기 위한 고성능 툴체인으로, JavaScript, TypeScript, JSX 등의 고속 포매터 역할을 합니다. Prettier와의 호환성은 무려 97%에 달합니다. 또한, ESLint와 typescript-lint에서 가져온 270개 이상의 규칙으로 풍부한 진단 정보를 제공하여 코드 품질을 높이는 데 도움을 줍니다.
이 도구는 Prettier보다 25배, ESLint보다 15배 빠른 속도 덕분에 개발자들에게 주목받고 있습니다.
다만, 2023년에 출시되었기 때문에 npm trends에 따르면 현재는 ESLint와 Prettier에 비해 사용 빈도가 낮은걸 볼 수 있습니다.
그러나 사이드 프로젝트에 적용해보면 Biome의 장점을 경험해 보면 좋을 것 같다고 생각합니다.
biome vs eslint vs prettier | npm trends 보러가기
이제 코드 스타일 가이드를 알아본 것을 바탕으로 사이드 프로젝트인 Receipto에 어떤 코드 스타일 가이드를 선택했는지 과정을 공유합니다.
Receipto는 모임에서 총무 역할을 맡은 사람이 결제 내역을 정리해 1/N로 분할하여 계산한 내역을 쉽게 공유할 수 있는 웹 애플리케이션입니다. SEO 최적화가 필요 없다고 판단하여 CSR(Client Side Rendering) 방식을 채택했고, 기술 스택으로는 React, TypeScript, Vite를 사용했습니다.
처음에는 익숙한 Airbnb JavaScript Style Guide를 선택하려 했습니다.
하지만, React에 더 적합한 가이드를 찾다 보니 Airbnb React Style Guide를 발견했습니다.
한 번더 다른 대안을 찾아 보던 중 Vercel의 스타일 가이드를 발견했습니다. 이 가이드는 Prettier, ESLint, TypeScript로 구성되어 있어 Receipto와 잘 맞아 보였습니다. 그러나 ESLint v8.x.x를 사용하고 있어 제가 사용하는 ESLint v9.x.x와의 호환성에 문제가 있었습니다.
ESLint v9.x.x가 최근(특히, v9.28.0은 5월 31일에 업데이트)에 업데이트 되어 대부분의 스타일 가이드 설정 아티클은 ESLint v8.x.x를 기준으로 작성되어 있었습니다. 공식 문서에서는 v9.x.x 사용 방법과 v8에서 v9로 마이그레이션 방법을 제공하지만, 추가로 참고할 만한 자료가 필요했습니다.
그러던 중 eslint-config-airbnb-extended
라이브러리를 발견했습니다. 이 라이브러리는 ESLint의 flat configuration system을 사용하여 자동으로 설정 파일(eslint.config.js)을 생성하고, Airbnb Style Guide를 사용합니다. 또한, TypeScript를 지원하고 커스터마이즈가 쉬운 장점이 있었습니다.
결국, eslint-config-airbnb-extended
라이브러리를 사용하여 Airbnb React Style Guide를 적용하기로 결정했습니다.
이번 과정에서 많은 시간이 소요되어, 다음 프로젝트에서는 더 효율적으로 스타일 가이드를 설정하기 위해 나만의 패키지를 만들어볼 계획입니다.
React + TypeScript + Vite 환경에 ESLint v9.x.x와 Prettier v3.x.x를 설정하는 방법을 알아보겠습니다. Airbnb 스타일 가이드와 함께 코드를 포맷하고 검증하는 방법을 배워보겠습니다.
# npm 사용 명령어 (npm v7 이상에서는 '--' 반드시 붙여주세요):
npm create vite my-app -- --template react-ts
# bun 사용 명령어:
bun create vite my-app --template react-ts
위 명령어를 통해 Vite로 React + TypeScript 프로젝트를 생성했습니다.
참고: Vite 프로젝트 만들어보기 | Vite 공식 문서
Vite로 생성된 프로젝트는 기본적으로 ESLint를 제공하지만, Airbnb 스타일 가이드를 적용하기 위해 재설정합니다.
eslint-config-airbnb-extended
라이브러리를 사용하여 ESLint를 설정해보겠습니다.
# npm 사용 시:
npx create-airbnb-x-config
# bun 사용 시:
bunx create-airbnb-x-config
명령어 실행 후, 아래 질문들에 답변합니다.
- ? Are you typescript? No / Yes
- ? Are you using prettier? No / Yes
- ? Are you using? > - Use arrow-keys. Return to submit.
React/React Router
...
- ? Should I create an eslint.config.mjs file for you? No / Yes
- ? Do you ant to skip the package installation? No / Yes
eslint.config.mjs 파일이 생성됩니다:
// eslint.config.mjs
/**
* THIS FILE WAS AUTO-GENERATED.
* PLEASE DO NOT EDIT IT MANUALLY.
* ===============================
* IF YOU'RE COPYING THIS INTO AN ESLINT CONFIG, REMOVE THIS COMMENT BLOCK.
*/
import path from 'node:path';
import { includeIgnoreFile } from '@eslint/compat';
import js from '@eslint/js';
import { configs, plugins } from 'eslint-config-airbnb-extended';
import { rules as prettierConfigRules } from 'eslint-config-prettier';
import prettierPlugin from 'eslint-plugin-prettier';
export const projectRoot = path.resolve('.');
export const gitignorePath = path.resolve(projectRoot, '.gitignore');
const jsConfig = [ /* Configuration details */ ];
const reactConfig = [ /* Configuration details */ ];
const typescriptConfig = [ /* Configuration details */ ];
const prettierConfig = [ /* Configuration details */ ];
export default [
// Ignore .gitignore files/folder in eslint
includeIgnoreFile(gitignorePath),
// Javascript Config
...jsConfig,
// React Config
...reactConfig,
// TypeScript Config
...typescriptConfig,
// Prettier Config
...prettierConfig,
];
VSCode와 같은 IDE에 Prettier를 적용하려면 설정 파일을 생성해야 합니다.
{
"tabWidth": 2,
"singleQuote": true,
"printWidth": 80,
"semi": true,
"bracketSpacing": true,
"objectWrap": "preserve",
"bracketSameLine": false,
"arrowParens": "always"
}
객체 리터럴의 중괄호 사이에 공백을 추가합니다.
// "bracketSpacing": true
const obj = {foo: 'bar'};
// "bracketSpacing": false
const obj = { foo: 'bar' };
닫는 괄호가 새 줄에 오도록 설정합니다.
// 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>
화살표 함수의 매개변수에 항상 괄호를 사용합니다.
// 'always'
(x) => x;
// 'avoid'
x => x;
// .prettierignore
node_modules/
dist/
build/
coverage/
*.min.js
*.png
*.jpg
package-lock.json
yarn.lock
.env
React 17부터 JSX 작성 시 React를 import하지 않아도 된다는 규칙과 함수 선언문으로만 컴포넌트를 작성하도록 강제하는 규칙을 설정합니다.
// eslint.config.mjs
...
const myCustomConfig = [
{
name: 'my-custom-config',
rules: {
'react/react-in-jsx-scope': 'off',
'react/function-component-definition': [
'error',
{
namedComponents: 'function-declaration',
unnamedComponents: 'function-expression',
},
],
},
},
];
export default [
/* 기존 설정 */
// My Custom Config
...myCustomConfig,
];
Receipto 프로젝트에 ESLint와 Prettier가 잘 적용되고 있는지 테스트 해보겠습니다.
ESLint를 테스트 해보기 위해 TestComponent.tsx 파일을 생성하고 함수 표현식으로 컴포넌트를 작성해 보세요. 아래와 같은 에러가 나타납니다:
// TestComponent.tsx
const TestComponent = function () {
return <div />;
}
export default TestComponent;
// Function component is not a function declaration eslint(react/function-component-definition)
TestComponent를 아직 저장 전인데 저장후 어떻게 코드가 변하는지 보겠습니다.
Prettier를 설정한대로 코드 포맷이 변경되는 걸 확인할 수 있습니다.
ESLint와 Prettier 설정을 통해 코드 스타일을 일관되게 유지할 수 있습니다.
이번 설정 과정을 통해 ESLint와 Prettier가 각각 린트 도구와 코드 포매터로서 다른 역할을 한다는 점과, 코드 스타일을 정하는 것이 주는 이점을 배웠습니다. 설정 방식에 대해 고민하느라 시간이 많이 걸렸지만, 라이브러리의 도움을 통해 빠르게 적용할 수 있었습니다. 다음에는 직접 규칙을 정의하고 패키지를 만들어보는 도전을 해보고 싶습니다. 이러한 과정을 통해, 사이드 프로젝트에서도 일관된 코드 스타일을 적용하고, 과거에 작성한 코드도 쉽게 이해할 수 있을 것 같습니다.