Tech

[Tech] CRA없이 react 개발 환경 구축하기

lonnie(동현) 2022. 4. 14. 11:13

 React 환경에서 개발을 진행하면서 CRA를 통해 보통 개발 환경을 구축해왔다. 하지만, '프론트엔드 개발자라면 빌드 시스템을 직접 구축할 수 있어야 하지 않을까?'라는 생각이 들었다.

 또한 상황에 맞게 환경 설정을 수정하며, 성능을 개선해 나가는 작업이 필요하다고 생각했다. 이번 작업은 macOS 환경에서 진행하였고, CRA 없이 react 개발 환경 구축을 시작해보겠다.

package.json 만들기

가장 먼저 내가 작업하고자 하는 위치에 가서 프로젝트 초기화를 통해, 어떤 프로젝트를 진행하고자 하는지에 대한 정보를 입력한다.

  • yarn init 명령어를 통해서 내가 작업하고자 하는 폴더를 node.js 프로젝트로 초기화 시킨다
  • 해당 명령어를 진행하면 아래와 같은 question이 나오게 되는데, 내가 작성하고자 하는 프로젝트에 맞게 입력해주면 된다.

작업에 필요한 폴더 만들기

react 프로젝트를 진행할 때, 필요한 폴더들을 만드는 작업이다.

mkdir src public dist
  • src : react 작업을 할 폴더
  • public : 정적 파일이 위치할 폴더
  • dist : 빌드한 작업물이 들어갈 폴더 → 배포란 뜻으로 distribute를 의미한다

아래와 같이 정상적으로 폴더가 만들어진 것을 볼 수 있다.

public 폴더로 이동해서 index.html 파일을 만들어준다.

cd public
touch index.html

그리고 아래의 내용을 입력해준다.

// 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>Set React Development Environment without CRA</title>
  </head>
  <body>
    <div id="root""></div>
  </body>
</html>

Bable 설치 하기

babel 이 필요한 이유는 다음과 같다.

최신 버전의 자바스크립트 문법은 브라우저가 이해하지 못하는 경우가 있다. 따라서 브라우저가 이해할 수 있는 문법으로 변환해주기 위해서 필요하다. 아래의 명령어를 통해 필요한 라이브러리를 설치한다.

yarn add -D @babel/core @babel/preset-env @babel/preset-react
  • @babel/core : 바벨의 메인 패키지
  • @babel/preset-env : ES6+ 코드를 이하 버전(ES5)으로 변환해주는 라이브러리
  • @babel/preset-react : JSX 코드를 React.CreateElement 호출 코드로 변환해주는 것으로 아래와 같이 작동하는 것이다.
//바벨 컴파일 전
<div>before babel comfile</div>

//바벨 컴파일 후
React.createElement("div", null, "before babel comfile");

 여기서 babel은 런타임 때 사용되는 것이 아니라, 컴파일을 진행할 때 즉, 개발 환경에서 필요한 것이기 때문에 -D 또는 —dev를 통해 의존성을 devDependencies에 추가해주는 것이다.

 이제 설치한 파일을 사용하기 위해 babel의 환경을 설정할 파일을 만들어 준다.

touch .babelrc

아래와 같이 입력해주면 기본적인 babel 환경 설정을 마칠 수 있다.

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

Webpack 설치 하기

webpack 이 필요한 이유는 다음과 같다.

  • 웹 애플리케이션을 구성하는 자원 모듈화
  • 웹 개발 작업 자동화 도구로 이용
  • 웹 애플리케이션의 빠른 로딩 속도와 높은 성능

아래의 명령어를 통해 필요 라이브러리와 플러그인을 설치한다.

yarn add -D webpack webpack-cli webpack-dev-server webpack-bundle-analyzer style-loader css-loader babel-loader
  • webpack: 웹팩의 코어
  • webpack-cli: 웹팩을 커맨드 라인에서 사용
  • webpack-dev-server: 실시간 개발 서버 환경을 구동할 수 있게 해 줌
  • webpack-bundle-analyzer: 웹 팩으로 만든 번들러를 웹 상에서 분석할 수 있는 UI (필수 사항은 아님)

웹팩은 loader를 사용하여 다른 확장자를 가진 파일들을 번들링 한다.

  • style-loader : 변환된 CSS 파일을 <style> 태그로 감싸서 삽입
  • css-loader : CSS 파일을 자바스크립트가 이해할 수 있도록 변환
  • babel-loader : JSX, ES6+ 문법을 트랜스파일링

필요한 플러그인들도 설치해준다.

yarn add -D html-webpack-plugin clean-webpack-plugin
  • html-webpack-plugin: script 태그를 사용하여 body에 모든 webpack 번들을 포함하는 HTML5 파일을 생성한다. HTML에 번들링 한 JS 파일을 삽입하고, HTML 파일을 번들링 된 결과물이 저장될 폴더에 옮겨준다. 여기서는 dist 폴더가 될 것이다.
  • clean-webpack-plugin: 번들링을 할 때마다 이전 번들링 결과를 제거해준다.

이제 설치한 파일을 사용하기 위해 webpack의 환경을 설정할 파일을 만들어 준다.

touch webpack.config.js

그리고 아래와 같이 작성한다.

// webpack.config.js
const path = require('path');
/* Plugin */
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer');

module.exports = {
// 웹팩에게 애플리케이션의 시작 지점을 정함
    entry: {
      index: './src/index.js',
    },
    resolve: {
// 웹팩이 해석할 확장자
      extensions: ['.mjs', '.js', '.jsx', '.css'],
    },
// 디버깅할 개발자 도구의 스타일을 정함
    devtool: 'eval-cheap-source-map',
// webpack-dev-server의 옵션을 설정
    devServer: {
      port: 8080,
// 번들된 코드가 실제로 어디 있는지 서버에게 알려줌static: {
        publicPath: '/dist/',
      },
// HMR을 사용할 것인지 여부, 새로 고침 없이 빌드 실패 같은 케이스에 HMR 적용
      hot: 'only',
// 서버 시작 후 바로 브라우를 열 것인지 정함
      open: true,
      client: {
// 컴파일 과정 퍼센티지로 브라우저에 보여줌
        progress: true,
// 컴파일 에러 또는 경고시에 브라우저에 풀스크린으로 보여줌
        overlay: true,
      },
    },
// 번들링 된 결과물을 어디다 둘 것인지에 대한 설정
    output: {
      filename: '[name].bundle.js',
      path: path.resolve(__dirname, 'dist'),
      assetModuleFilename: 'images/[hash][ext][query]',
    },
// export한 JS 모듈이 어떻게 변환되는지 정의
    module: {
      rules: [
        {
          test: /\.(js|jsx)$/,
          exclude: '/node_modules/',
          loader: 'babel-loader',
        },
        {
          test: /\.css$/,
          use: ['style-loader', 'css-loader'],
        },
        {
          test: /\.jpe?g/,
          type: 'asset/resource',
        },
        {
          test: /\.png/,
          type: 'asset/resource',
        },
        {
          test: /\.svg/,
          type: 'asset/inline',
        }
     ],
    },
    plugins: [
      new CleanWebpackPlugin(),
      new HtmlWebpackPlugin({
// 번들링된 JS를 주입하고 결과물을 옮길 대상이 되는 파일을 지정
        template: './public/index.html',
      }),
      new BundleAnalyzerPlugin(),
    ],
};

React 설치하기

yarn add react react-dom
  • 설치한 react 버전은 v18을 사용하였다.
  • src로 이동해서 App.js 파일을 만들어준다.
cd src
touch App.js

그리고 아래의 내용을 입력해준다.

// src/App.js
import React from 'react';

const App = () => {
  return(
    <div className="App">
      <h1>Without CRA</h1>
    </div>
  )
}

export default App;

이제 그 상태에서 index.js 파일을 만들어주고 아래의 내용을 입력한다.

touch index.js
// src/index.js
import React from 'react';
import * as ReactDOMClient from 'react-dom/client';
import App from './App';

const container = document.getElementById('root');
const root = ReactDOMClient.createRoot(container);

root.render(
  <React.StrictMode>
        <App />
  </React.StrictMode>,
);
  • v18을 사용하였기 때문에, 기존과는 다르게 root를 생성하고 그것을 렌더링 하는 방식으로 작동한다.
  • root는 react가 렌더링 할 트리를 추적하는 데 사용하는 최상위 데이터 구조에 대한 포인터이다.
  • index.html 에서 id 가 root 인 곳이 렌더링 위치가 되고, App 컴포넌트가 root에 의해 렌더링 되는 것이다.
  • React.StrictMode 는 개발 모드에만 활성되는 것으로, 애플리케이션 내의 잠재적인 문제를 잡아준다.(React Strict Mode)
  • 이제 모든 준비가 끝났다. 실행하기 위한 script를 작성해주자.

Script 작성 및 실행

package.json으로 이동해서 실행을 위한 스크립트를 추가한다.

"scripts": {
    "dev": "webpack-dev-server --mode development",
    "build": "webpack --mode production"
  }

yarn dev 명령어를 실행해보면 정상적으로 실행되는 것을 볼 수 있다.

서버를 실행한 화면

 이번을 계기로 번들러와 컴파일러들의 config를 수정하는 경험을 할 수 있었고, 앞으로 더 많은 공부를 통해서 이 부분에 대한 실력을 차츰차츰 늘려갈 생각이다.

 

728x90
반응형