Dog foot print

React 시작 환경 구축하기 본문

REACT

React 시작 환경 구축하기

개 발자국 2023. 3. 11. 11:36

CRA의 문제점

Tip : Jest는 테스팅 도구이다.
Tip : Parcel, Webpack, Rollup은 여러 파일들을 필요한 소수의 파일로만 다시 묶어주는 번들러이다.
Tip : Babel은 브라우저에서 지원하지 않는 최신문법이나 JSX문법을 브라우저가 읽을 수 있도록 변환해주는 트랜스파일러이다.
Tip : 이 시점에서 위 3개의 Tip을 이해하지 않아도 된다.

CRA로 시작하기 : 설치 - React

 

설치 - React

A JavaScript library for building user interfaces

reactjs-kr.firebaseapp.com

Create React App(이하 CRA)는 공식 홈페이지에서도 React를 시작 할 때, 추천하는 개발 환경에 필요한 라이브러리를 설치해주고 설정을 미리 다 해주는 보일러 플레이트이다.

 

나도 처음에는 CRA를 사용해 리액트의 여러기능들을 사용해보고 가르쳐보고 했지만, 문제는 이미 너무 많은 설정들이 되어 있어서, 이를 수정하기 매우 어려우며 Parcel이나 Rollup과 같은 번들러를 사용하려고 해도 이미 웹팩에 관련한 흔적들이 많이 남아 있어 이를 모두 지우기는 많이 힘들다.

 

설정을 볼 수 있는 yarn eject 명령어를 이용하여 각종 설정들과 모듈을 밖으로 꺼내면 아래와 같은 webpackjest , Babel 설정들이 생성된다.

 

물론 CRA는 충분히 처음 React를 시작하는 사람들이 설정을 무시하고 배울 수 있는 훌륭한 도구임에는 이견은 없다. 그러나 무지막지하게 잘 쓰여진 긴 설정 코드는 초보자들의 기를 팍 죽여 이런 도구 없이는 프로젝트를 실행조차 하지 못하게 하는 장애물이라 생각한다.

Git 과 Yarn init

$: git init 
$: yarn init

yarn init 명령어를 통해 값을 입력하면 프로젝트 폴더에 ‘package.json’ 파일이 생성 되었을 것이다.

{
  "name": "react-project",
  "version": "1.0.0",
  "description": "react boilerplate",
  "main": "index.js",
  "author": "호키도키 <substantiation@naver.com>",
  "license": "MIT"
}

폴더 및 파일 기본 구성

프로젝트 폴더 및 파일 구성

.
├── babel.config.js
├── package.json
├── public
│   └── index.html
├── src
│   ├── App.jsx
│   └── index.js
├── webpack.config.js
└── yarn.lock

public/index.html

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>React App</title>
</head>

<body>
    <main id="root" />
</body>

</html>

Src/App.jsx

export default function App() {
    return (
        <div>App</div>
    )
}

Src/index.js

import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
    <React.StrictMode>
        <App />
    </React.StrictMode>
);

./babel.config.js

module.exports = {} //추후에 작성 합니다.

./webpack.config.js

module.exports = {} //추후에 작성 합니다.

React 및 Webpack 설치

Tip : -D 표시는 개발의존성 모듈로 사용자에게 전달되는 코드가 아닌 개발시 필요한 라이브러리를 의미한다.

$: yarn add react react-dom
$: yarn add webpack webpack-cli webpack-dev-server -D

React : UI요소를 만들기 위한 라이브러리
React-dom : React 라이브러리로 만든 UI요소를 브라우저에 렌더링 할 때 사용되는 라이브러리

webpack : [js, ts, jpg, css,…] 의 여러 모듈을 결합하여 실행에 필요한 요소들로 묶어 제공해주는 정적 모듈 번들러
webpack-cli : webpack을 커맨드라인에서 입력할 수 있도록 도와주는 라이브러리
webpack-dev-server : 개발시 빠르게 결과물을 확인 할 수 있도록 가상의 서버를 띄어 볼 수 있는 라이브러리

만약 두개의 커맨드를 입력하여 설치가 완료 되었다면 package.json 파일에 이렇게 추가 되었을 것이다.

  "dependencies": {
    "react": "^18.2.0",
    "react-dom": "^18.2.0"
  },
  "devDependencies": {
    "webpack": "^5.75.0",
    "webpack-cli": "^5.0.1",
    "webpack-dev-server": "^4.11.1"
  }

Webpack 이란 ?

여기서 자세하게 다룰 만한 크기의 모듈은 아니지만 개념은 집고 넘어가야 할 것 같다. 웹팩은 ‘정적 모듈 번들러’다. 의미만 본다면 매우 어려우니, 쉽게 설명해보겠다.

 

모듈이라는 개념이 정립하기전에는 개발자가 스크립트를 구성할 때, 한 개의 파일에서 무수히 많은 코드를 작성하곤 하였다. 이로 인하여, 스크립트가 커질수록 유지보수가 매우 불편 하였다.

웹팩은 아래와 같은 것들을 가능하게 하였다.

  1. 모듈 단위로 개발하여 이를 모아 한개의 스크립트로 만들 수 있다.
  2. 한개의 스크립트를 만드는 과정에서 압축, 난독화 같은 것을 가능케 한다.
  3. Css, jpg, mpeg 같은 파일도 모듈로써 해석하여, 번들 패키지에 포함시킬 수 있다.
  4. 파일을 병합하고 해석하는 과정에서 문장을 변경 할 수 있다.

이 같은 기능들로 우리는 .jpg파일을 문자열로 변경하여, js 내부에서 이미지 파일을 요청하지 않고, 렌더링 시킬 수 있으며 importrequire 구문으로 다른 파일에서 모듈을 쉽게 가져오는 것도 가능하다.

babel 설치

$: yarn add -D @babel/core babel-loader @babel/cli @babel/preset-env @babel/preset-react

babel-core : 최신 문법을 지원하지 않는 브라우저에서도 사용가능하게 변환해주는 트랜스 파일러
Babel-loader : javascript파일을 웹팩과 바벨을 이용해 변환 할 수 있게 해주는 라이브러리
babel-preset-env : es2015문법을 변환 할 때, 필요한 코드 조각
babel-preset-react : react를 변환 할 때, 필요헌 코드 조각

Babel 이란

간단하게 바벨에대해서 소개하고 넘어가도록 하겠다. 바벨은 최신버전의 자바스크립트를 지원하지 않는 브라우저에서도 최신 버전의 자바스크립트로 돌아갈 수 있도록 코드를 변경해주는 트랜스 파일러이다.

 

예를 들어 App.js 에서 사용된 return <h1>hello world</h1> 는 실제로 자바스크립트에서는 존재하지 않는 문법이다. 그래서 이를 그대로 브라우저에서 사용하면 에러를 발생 시킨다. 바벨을 통과한 코드는 createElement("h1") 처럼 브라우저가 해석 할 수 있는 코드로 변경시켜 준다.

Babel 설정

./babel.config.js

module.exports = {
  presets: ['@babel/preset-react', '@babel/preset-env'],
};

Webpack 설정

// Modules
const path = require("path");

// Module Regex
const scriptRegex = /\.(jsx|js|ts|tsx)$/;

// Env
const isProd = process.env.PRODUCTION === "true";
const port = process.env.PORT || 3000;

// Configuration
module.exports = {
    mode: isProd ? "production" : "development",
    entry: "./src/index.js", // main js
    output: {
        path: path.resolve(__dirname, "dist"), // output folder
        filename: "bundle.js"
    },
    module: {
        rules: [
            // Script file processing
            {
                test: scriptRegex,
                exclude: /node_modules/,
                use: {
                    loader: "babel-loader",
                },
            },
        ],
    },
    devServer: {
        port: port,
    },
};

실행

$: yarn dev

“App.jsx” 에서 작성한 컴포넌트가 출력된다.

번들된 파일의 행방

$: yarn webpack 명령어를 입력하면 빌드된 파일이 ‘/dist’ 폴더에 생성이 되는데, 이상하게 webpack-dev-server를 돌리면 ‘/dist’폴더 없이 localhost:3000에서 접속이 되고, 리로드까지 된다.

Webpack-dev-server does not place bundle in dist - Stack Overflow에 따르면 webpack-dev-server를 이용하면, 번들된 파일을 메모리에 보관했다가 파일을 전달한다고 한다.

이를 해결 하기위해서는 ‘webpack.config.js’ 파일의 devServer를 다음과 같이 구성하면 된다.

{
    ...
    devServer: {
        port: port,
        devMiddleware: {
            writeToDisk: true
        }
    },
    ...
}

HTML파일 번들 폴더에 포함시키기.

배포시, dist 폴더에 앱을 구동시키기 위한 모든 것들이 번들링 되어 있다면, 따로 여러 폴더에 걸쳐 파일들을 모으지 않아도 될 것이다. 지금은 webpackwebpack-dev-server 를 실행 시키더라도 ‘/dist’ 폴더에 bundle.js 파일 밖에 존재하지 않으니 빌드시 index.html 파일을 /dist 폴더로 이동 할 수 있도록 해야하며, webpack-dev-server 실행시 dist폴더에서 다른 파일들을 찾을 수 있도록 해야 한다.

$: yarn add -D html-webpack-plugin

html-webpack-plugin : 빌드 시 HTML 파일을 생성해주는 모듈

./webpack.config.js

...
const HtmlWebpackPlugin = require('html-webpack-plugin')
...

module.exports = {
    ...
    module : {...}
    plugins: [
            new HtmlWebpackPlugin({
            template: "/public/index.html"
        })
  ],
    devServer : {
        port: port,
        devMiddleware: {
            writeToDisk: true
        },
        static: {
            directory: path.join(__dirname, 'dist'),
              //Asset will served from here
        },
    }
}

#리액트 #config

반응형
Comments