create-react-app 없이 리액트 앱 빌드하기 1 - Babel

베이시스·2021년 9월 23일
0

들어서며

많은 사람이 처음 리액트 개발을 할 때 Facebook(현 Meta)이 제공하는 create-react-app (이하 CRA)을 사용하고 있습니다.

CRA는 번거로울 수 있는 초기 세팅을 모두 해 주기에 분명 편리하지만 리액트 앱을 자기 입맛대로 수정하려는 개발자에게는 일종의 족쇄이며 앱이 어떻게 빌드되는지 이해하고자 하는 주니어 개발자에게도 CRA를 사용하지 않는 리액트 앱의 빌드는 한 번쯤 시도해 볼 만한 일입니다.

그렇다면 CRA가 무엇을 잡아주기에 우리가 편하게 리액트 앱을 개발할 수 있는 걸까요? 그 질문에 대한 답을 내 보도록 합시다.

이젠 더 이상 yarn eject를 두려워하지 말자!

첫 번째, Babel

그래서 바벨이 뭔데? 바벨탑은 아는데?

Babel 은 자바스크립트 컴파일러입니다. 하지만 이 컴파일러는 입출력이 모두 자바스크립트 코드란 점에서 조금 특이한데 (트랜스파일러라고도 합니다), ES6+ 기반의 자바스크립트 코드를 ES5 스펙에 맞도록 컴파일할 뿐 아니라 현재는 리액트의 JSX 문법, 코드 압축, TypeScript 등 정말 많은 일을 합니다.

아래와 같은 ES6+ 스타일의 코드가 있다고 합시다. (ES6의 arrow-function 문법 사용)

const add = (a, b) => {
  return a + b;
}

이 채-신 코드는 바벨이 바꿔 버렸으니 안심하라구!

"use strict";

var add = function add(a, b) {
  return a + b;
};

이걸로 전부 해결된 것처럼 보이지만 Babel은 번역을 위한 수단일 뿐 실제 스펙에 대응하는 것은 플러그인입니다. 위에서 바벨이 바꿔 주었다 했지만 사실 플러그인과의 콜라보인 것이며, 바벨만 믿고 최신 자바스크립트 프레임워크와 스펙을 갖다 쓰다간 에러의 철퇴를 맞고 쫓겨납니다. 이 쪽은 플러그인과 프리셋이 해결합니다.

플러그인과 프리셋

플러그인

위에서 설명한 것과 같이 Babel이 제대로 코드를 번역하려면 플러그인의 도움이 필요합니다. 각 플러그인은 npm 패키지로 배포됩니다. 우선 대표적인 ES6 문법인 arrow-function을 번역하기 위한 플러그인인 plugin-transform-arrow-functions을 사용해 봅시다.

우선 실습에 들어가기 앞서 Babel 기본 모듈을 설치하고,

yarn add @babel/core @babel-cli -D
  • @babel/core : 바벨 핵심 기능이 들어간 기본 패키지
  • @babel/cli : CLI 환경에서 바벨 명령어를 사용할 수 있게 하는 패키지

그런 뒤 arrow-function을 변환하기 위한 플러그인을 설치합니다.

yarn add @babel/plugin-transform-arrow-functions -D

하지만 이것만으로는 Babel이 이 플러그인을 사용하지는 않습니다. 플러그인을 사용할 거라고 Babel한테 알려주어야 하는데, 그 설정 파일이 .babelrc (혹은 babel.config.js)입니다.

babel.config.js는 전역 설정, .babelrc는 지역 설정으로 사용합니다. 가령, 동일한 설정이 두 파일에서 서로 다르게 작성되어 있다면 지역 설정이 우선하게 됩니다.

.babelrc는 아래와 같이,

{
  "plugins": ["@babel/plugin-transform-arrow-functions"],
  "presets": []
}

babel.config.js는 아래와 같이 작성합니다.

module.exports = function (api) {
  api.cache(true);

  const presets = [];
  const plugins = ['@babel/plugin-transform-arrow-functions'];

  return { presets, plugins };
}

여기까지 작성하고 아무 파일이나 트랜스파일해 봅시다. 아래는 그 결과입니다.

이 방법으로 플러그인을 추가해 각 스펙에 대응할 수 있지만 일일이 플러그인을 추가한다는 건 여간 귀찮은 일이 아닙니다.

굉장히 머리아픈 일입니다. 눈썰미가 좋은 사람은 벌써 눈치챘겠지만 그런 우리를 위해 프리셋이란 게 있습니다.

프리셋

프리셋은 플러그인의 집합(번들)입니다. 앞서 리액트와 같은 스펙에 대응하려면 플러그인을 직접 설치해야 한다고 했지만 이 프리셋을 이용하면 간단하게 해결할 수 있습니다. 프리셋이 해당 스펙에 대응하도록 플러그인을 모아 놨으니까요.

이 중 Babel이 제공하는 공식 프리셋은 아래와 같습니다.

  • @babel/preset-env
  • @babel/preset-flow
  • @babel/preset-react
  • @babel/preset-typescript

기존에는 babel-preset-env와 같이 제공하고 연도별로 따로 제공하였으나 Babel 7부터 스코프 패키지로 변경됨과 동시에 @babel/preset-env로 통합되었습니다. 사용자 입장에서는 신경쓸 일이 많이 줄어든 것.

preset-env는 ES6+ 스펙을 번역하기 위한 프리셋이고, 나머지는 각각 Flow, React, TypeScript에 대응하는 프리셋입니다.

yarn add @babel/preset-env -D

그리고 바벨 설정 파일에 프리셋을 추가하면 끝납니다.

{
  "presets": ["@babel/preset-env"]
}

혹은 React 앱을 위한 프리셋이 필요하다면 아래와 같이 작성하면 됩니다.

{
  "presets": ["@babel/preset-env", "@babel/preset-react"]
}

그리고 빌드하면 ES6+ 스펙의 코드가 바벨을 통해 ES5로 변환됩니다(기본값). 10년 묵은 체증이 쑥 내려가는 기분.
이처럼 정말 간단하게 코드를 변환할 수 있습니다. preset-env는 설정을 통해 지원하는 브라우저 버전도 설정 가능한데, 이는 별도의 포스트에서 다루겠습니다.

마치며

여기까지 CRA 없이 리액트 앱을 빌드하기 위한 첫 단계를 통과했습니다.

그러나 Babel을 단독으로 쓰기보다는 Webpack과 연결하면 babel-loader를 통해 여러 의존성을 가진 모듈을 합쳐 줄 수 있어 매우 유용합니다. 다음에는 Babel과 함께 사용하는 Webpack에 대해 다루겠습니다.

profile
사진찍는 주니어 프론트엔드 개발자

0개의 댓글