[React 정복기] React, Webpack, Babel (실전 리액트 프로그래밍) - 1

예흠·2020년 10월 30일
3

React 정복기!

목록 보기
1/8
post-thumbnail

React를 정복해보자 💪

실전 리액트 프로그래밍 개정판 - 이재승 지음 (참고자료)

React란?

*리액트는 페이스북에서 개발하고 관리하는 UI 라이브러리다.

앵귤러가 웹 애플리케이션 개발에 필요한 다수의 기능을 제공하는 것과는 대조적으로, 리액트는 UI기능만 제공한다.

=> 전반적인 시스템을 직접 구축할 수 있으니 각자의 환경에 맞게 최적화할 수 있다.

* 프론트엔드 라이브러리 혹은 프레임워크를 사용하는 이유?

가장 큰 이유 중 하나는 UI를 자동으로 업데이트해 준다는 점.

=> API 통신이나 사용자 이벤트를 통해 프로그램의 상탯값을 변경하면 리액트가 변경된 상탯값을 기반으로 UI를 자동으로 업데이트 한다.

리액트와 같은 도구를 사용하지 않으면 브라우저의 돔을 직접 업데이트해야 한다.

* React의 장점

이미지 출처

  • 리액트의 장점은 가상 돔(Virtual dom)을 통해서 UI를 빠르게 업데이트한다는 점이다.

가상 돔은 이전 UI상태를 메모리에 유지해서, 변경될 UI의 최소 집합을 계산하는 기술이다.
=> 가상 돔 덕분에 불필요한 UI 업데이트는 줄고, 성능은 좋아진다.

* 순수 함수와 불변 변수

리액트에서 코드를 작성할 때는 다음 조건을 지키는 게 좋다.

  • render 함수는 순수 함수로 작성한다.
  • state은 불변 변수로 관리한다.

render 함수는 순수 함수여야 하므로 인수 state가 변하지 않으면 항상 같은 값을 반환해야 한다. 컴포넌트의 상탯값을 수정할 때는 기존 값을 변경하는 게 아니라 새로운 객체를 생성해야 한다.

=> 복잡도가 낮아지고, 찾기 힘든 버그가 발생할 확률이 줄어든다. 더 중요한 것은 리액트에서 이 두 조건을 따르면 렌더링 성능을 크게 향상 시킬 수 있다.

React 개발 환경 직접 구축하기 🖥

리액트는 UI 라이브러리이기 때문에 UI를 제외한 나머지 요소들은 개발자가 신경 써서 관리해야 한다. create-react-app과 같은 도구를 사용할 수도 있지만 직접 구축하면서 바벨과 웹펙을 알아가 보자.

* Hello yeheum 페이지 만들기

https://unpkg.com/browse/react@16.14.0/umd/
https://unpkg.com/browse/react-dom@16.14.0/umd/

여기서 react.development.jsreact.production.min.js,
react-dom.development.jsreact-dom.production.min.js를 받는다.

그리고 같은 폴더에 내용이 없는 simple1.html, simple1.js 두 파일을 만든다.

simple1.html에 다음처럼 입하자.

<!-- simple1.html -->
<html>
  <body>
    <h2>안녕하세요. 저는 예흠이라고 해요. 좋아요 버튼 눌러 주세요!</h2>
    <div id="react-root"></div>
    <script src="react.development.js"></script>
    <script src="react-dom.development.js"></script>
    <script src="simple1.js"></script>
  </body>
</html>

simple.js 파일에는 좋아요 버튼을 보여 주는 리액트 컴포넌트를 작성해 보자. 버튼을 누르면 좋아요 취소 문구를 보여 준다.

//simple.js
function LikeButton() {
  const [liked, setLiked] = React.useState(false);
  const text = liked ? '좋아요 취소' : '좋아요';
  return React.createElement(
    'button',
    { onClick: () => setLiked(!liked) },
    text,
    );
}
const domContainer = document.querySelector('#react-root');
ReactDOM.render(React.createElement(LikeButton), domContainer);
  • 초기값과 함께 컴포넌트의 상탯값을 정의한다. 여기서 React 변수는 react.development.js 파일에서 전역 변수로 생성된다.
  • createElement 함수는 리액트 요소를 반환한다. 여기서 생성한 리액트 요소는 최종적으로 버튼 돔 요소가 된다.

리액트로 만든 첫 번째 웹 페이지가 완성됐다.
페이지를 브라우저에 띄우면 좋아요 버튼이 보이고 클릭하면 좋아요 취소 버튼으로 바뀌는 것을 확인 할 수 있다.

* createElement ?

createElement 함수의 구조는 다음과 같다.
React.createElement(component, props, ...children) => ReactElement

첫 번째 매개변수 component는 일반적으로 문자열이나 리액트 컴포넌트다.
=> 예를들어, 문자열 p를 입력하면 HTML p 태그가 생성된다.

두 번째 매개변수 props는 컴포넌트가 사용하는 데이터를 나타낸다.
=> 돔 요소의 경우 style, className 등의 데이터가 사용될 수 있다.

세 번째 매개변수 children은 해당 컴포넌트가 감싸고 있는 내부의 컴포넌트를 가리킨다.
div 태그가 두 개의 p 태그를 감싸고 있는 경우에 다음과 같이 작성할 수 있다.

<div>
  <p>hello</p>
  <p>yeheum</p>
</div>

createElement(
  'div',
  null,
  createElement('p', null, 'hello'),
  createElement('p', null, 'yeheum'),
)

바벨 사용해 보기 🏋️‍♀️

바벨(babel)은 자바스크립트 코드를 변환해 주는 컴파일러다.

바벨을 사용하면 최신 자바스크립트 문법을 지원하지 않는 환경에서도 최신 문법을 사용할 수 있다.

리액트에서는 JSX 문법을 사용하기 위해 바벨을 사용한다.
=> babel이 JSX문법으로 작성된 코드를 createElement 함수를 호출하는 코드로 변환해 준다.

이제 최초의 외부 패키지로 바벨을 추가해 보자.

현재까지의 코드는 너무 단순하므로 그 전에 몇 가지 컴포넌트를 먼저 추가해 보자.

=> 화면에 count 상탯값을 보여 주고 증가, 감소 버튼을 통해서 count 상탯값을 변경하는 코드를 작성해자.

  • simple1.html, simple1.js 파일을 복사해서 simple3.html, simple3.js 파일을 만들자.
function LikeButton() {
  //기존 코드와 같음
}

function Container() {
  const [count, setCount] = React.useState(0);
  return React.createElement(
    "div",
    null,
    React.createElement(LikeButton),
    React.createElement(
      "div",
      { style: { marginTop: 20 } },
      React.createElement("span", null, "현재 카운트: "),
      React.createElement("span", null, count),
      React.createElement(
        "button",
        { onClick: () => setCount(count + 1) },
        "증가"
      ),
      React.createElement(
        "button",
        { onClick: () => setCount(count - 1) },
        "감소"
      )
    )
  );
}
const domContainer = document.querySelector("#react-root");
ReactDOM.render(React.createElement(Container), domContainer);

simple3.html의 결과 화면이다.

단순한 기능인데도 UI코드가 상당히 복잡하다. 바벨의 도움을 받아서 이부분을 개선해 보자.

* JSX 문법 사용해 보기

simple3.html 파일을 복사해서 simple4.html 파일을 만든다.
src 폴더를 만든후 simple3.js 파일을 복사해 simple4.js 파일을 src폴더 안에 넣어보자.

폴더 구조는 아래와 같다.

이제 createElement 함수를 호출하는 코드를 JSX 문법으로 변경해 보자.

function Container() {
  const [count, setCount] = React.useState(0);
  return (
    <div>
      <LikeButton />
      <div style={{ marginTop: 20 }}>
        <span>현재 카운트: </span>
        <span>{count}</span>
        <button onClick={() => setCount(count + 1)}>증가</button>
        <button onClick={() => setCount(count - 1)}>감소</button>
      </div>
    </div>
  );
}

* JSX 문법을 바벨로 컴파일하기

JSX문법은 자바스크립트 표준이 아니기 때문에 simple4.js 파일을 그대로 실행하면 에러가 발생한다.
바벨을 이용해서 JSX 문법으로 작성된 파일을 createElement 함수로 작성된 파일로 변환해 보자.

다음 패키지를 설치해야 한다.

npm install @babel/core @babel/cli @babel/preset-react

  • bable/cli에는 커맨드 라인에서 바벨을 실행할 수 있는 바이너리 파일이 들어있다.
  • babel/preset-react에는 JSX로 작성된 코드를 createElement 함수를 이용한 코드로 변환해 주는 바벨 플러그인이 들어 있다.

설치된 패키지를 이용해서 자바스크립트 파일을 변환해 보자.

npx babel --watch src --out-dir . --presets @babel/preset-react

  • npx 명령어는 외부 패키지에 포함된 실행 파일을 실행할 때 사용된다.

위 명령어를 실행하면 src 폴더에 있는 모든 자바스크립트 파일을 @babel/preset-react 프리셋을 이용해서 변환 후 현재 폴더에 같은 이름의 자바스크립트 파일을 생성한다. watch 모드로 실행했기 때문에 src 폴더의 자바스크립트 파일을 수정할 때마다 자동으로 변환 후 저장한다.

웹팩의 기본 개념 이해하기!

웹팩(webpack)은 자바스크립트로 만든 프로그램을 배포하기 좋은 형태로 묶어 주는 도구이다.

2000년대 초반의 웹 페이지는 페이지가 전환될 때마다 새로운 HTML 파일을 요청해서 화면을 새로 그렸다. 그 당시 자바스크립트는 돔을 조작하는 간단한 역할만 했기 때문에 코드의 양이 많지 않았다. 한두 개의 자바스크립트 파일을 HTML의 script 태그를 이용해서 서비스하는 방식이면 충분했다. Ajax가 유행했을 때는 자바스크립트의 비중이 조금 더 커졌지만 많아 봐야 페이지당 자바스크립트 파일 열 개 정도 수준이었다.

그런데 웹사이트 제작 방식이 단일 페이지 애플리케이션(single page application) 으로 전환되면서 상황은 달라졌다. 한 페이지에도 자바스크립트 파일이 수십 또는 수백 개 필요했기 때문에 더는 기존 방식이 통하지 않았다.

전통적인 방식으로 개발된 웹사이트의 HTML 코드와 같은 방식으로는 계속 늘어나는 자바스크립트 파일을 관리하기가 힘들다.

  • 파일 간의 의존성 때문에 선언되는 순서를 신경 써야 하기 때문
  • 뒤에 선언된 자바스크립트 파일이 앞에 선언된 파일에서 생성한 전역 변수를 덮어쓰는 위험도 존재

웹팩은 ESM(ES6의 모듈 시스템)과 commonJS를 모두 지원한다. 이들 모듈 시스템을 이용해서 코드를 작성하고 웹팩을 실행하면 예전 버전의 브라우저에서도 동작하는 자바스크립트 코드를 만들 수 있다.

웹팩을 실행하면 보통은 하나의 자바스크립트 파일이 만들어지는데, 원한다면 여러개의 파일로 분할할 수도 있다.

* 웹팩 사용해 보기

웹팩을 사용해서 리액트의 두 파일을 자바스크립트의 모듈 시스템으로 포함시켜 보자.
webpack-test라는 폴더를 만들고 그 폴더에서 다음 명령어를 실행한다.

npm init -y

명령어를 실행하면 package.json 파일이 만들어진다.

  • simple1.html 파일을 복사해서 webpack-test 폴더 밑에 index.html 파일을 만들고, index.html에 있는 simple1.js 문자열을 dist/main.js로 변경하자.
  • react.development.js, react-dom.development.js 파일을 포함하고 있는 script 태그를 지운다.

이 두 리액트 파일은 모듈 시스템을 이용해서 main.js 파일에 포함될 예정이다.

구조는 아래와 같다.

이제 필요한 외부 패키지를 설치해 보자.

npm install webpack webpack-cli react react-dom

웹팩과 함께 리액트 패키지도 설치했다. react 패키지에는 우리가 위에서 내려받았던 react.production.min.js, react.development.js 파일이 포함되어 있다. react-dom 패키지도 마찬가지다.

이전에는 url을 직접 입력해서 각각의 파일을 내려받았지만, 이제는 모듈 시스템과 npm 덕분에 외부 패키지를 프로젝트에 쉽게 포함할 수 있게 되었다.

먼저 index.js 파일에 다음 내용을 입력한다.

//index.js
import React from "react";
import ReactDOM from "react-dom";
import Button from "./Button";

function Container() {
  return React.createElement(
    "div",
    null,
    React.createElement("p", null, "버튼을 클릭해 주세요."),
    React.createElement(Button, { label: "좋아요" }),
    React.createElement(Button, { label: "싫어요" })
  );
}

const domContainer = document.querySelector("#react-root");
ReactDOM.render(React.createElement(Container), domContainer);

Button.js 파일에는 Button 컴포넌트를 작성하고, ESM 문법을 이용해서 필요한 모듈을 가져오고 Button 컴포넌트를 내보내도록 하자.

//Button.js

import React from "react";

export default function Button(props) {
  return React.createElement("button", null, props.label);
}

이제 웹팩을 이용해서 두 개의 자바스크립트 파일을 하나의 파일로 합쳐 보자.

npx webpack

위 명령어를 실행하면 dist 폴더 밑에 main.js 파일이 생성된다.

index.html을 실행해 보니 원했던 대로 잘 나온다.

웹팩에는 이 외에도 다양한 기능이 있다.
다음번 정복기에서 더 자세하게 알아보도록 하자.

참고자료: 실전 리액트 프로그래밍 개정판

profile
노래하는 개발자입니다.

0개의 댓글