[React] CRA, Vite 없이 개발환경 구축하기

프로젝트 초기 설정

1. 프로젝트 폴더 생성

 

2. HTML 파일 생성

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>No CRA</title>
    </head>
  <body>
    <div id="root"></div>
    <script>
      const App = () => {
        return (
          <>
            <h1>Hello World</h1>
          </>
        );

        const root = ReactDOM.createRoot(document.getElementById("root"));
        root.render(<App />);
      };
    </script>
  </body>
</html>

 

3. React와 ReactDOM CDN 추가

<script src="https://unpkg.com/react@18/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>

 

 

Babel 적용해 JSX 사용하기

위의 문법에서 오류가 발생하는 이유는 아직 현재 프로젝트에서 JSX 문법을 모르기 때문이다.

 

트랜스파일러

프로그래밍 언어의 코드를 다른 프로그래밍 언어 또는 동일한 언어 내에서 다른 버전이나 형식으로 변환하는 도구

JSX 등의 최신 확장 문법의 JS들을 구버전 JS로 변경

 

1. Babel 설치

<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>

 

2. scrpit tag 수정

- type="text/babel"설정 추가해 babel이 어떤 스크립트를 트랜스파일 할지 지정

 

3. 패키지 초기화

npm init -y
npm install --save-dev @babel/core @babel/cli @babel/preset-react
  • babel-cli @babel/core: 빌드타임에 바벨을 실행시키기 위한 CLI 명령어 도구.
  • @babel/preset-react: React 용 바벨 문법 변환 패키지

 

+ .babelrc 파일 생성

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

 

4. build 스크립트 작성

package.json에 build 스크립트 입력

"scripts": {
    "build": "babel src -d dist"
 },

 

src 폴더 생성 > app.js 파일 생성 후 html의 script type="text/babel" 태그 내용을 옮겨주기

 

npm run build를 통해 실행시키면 dist 폴더에 app.js가 생성됨!

 

5. index.html 수정

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>No CRA</title>
    <script src="https://unpkg.com/react@18/umd/react.development.js"></script>
    <script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
  </head>
  <body>
    <div id="root"></div>
    <script src="./dist/app.js" type="module"></script>
  </body>
</html>

 

Webpack 도입 및 설정

번들러

여러개의 파일로 구성된 코드나 리소스를 하나의 파일 (또는 몇개의 파일)로 묶어주는 도구

여러 JS, CSS, 이미지 파일 등을 하나의 파일로 결합하여 배포 및 로드 성능을 개선하는 데에 사용

-> 브라우저는 한 번에 6개씩 나눠서 네트워크 요청을 받아옴 (6개 끝나면 다음 6개)

-> 파일이 여러개일수록 그만큼 로드가 지연됨

 

1. 패키지 설치

npm install --save-dev webpack webpack-cli babel-loader
  • webpack webpack-cli: 빌드타임에 웹팩을 실행시키기 위한 CLI 명령어 도구.
  • babel-loader: 바벨과 통합하기 위한 바벨 로더

 

2. Webpack 설정 파일 생성

프로젝트 루트에 webpack.config.js 파일 생성

const path = require("path");

module.exports = {
  entry: "./src/app.js",
  output: {
    path: path.resolve(__dirname, "dist"),
    filename: "bundle.js",
  },
  module: {
    rules: [
      //.css .js 등 서로 다른 확장자를 가진 파일을 처리할 때 어떤 규칙을 적용할지 정의
      {
        test: /\.js$/, // 어떤 파일을 대상으로 할지 정규표현식으로 작성
        exclude: /node_modules/, // node_modules 폴더는 제외
        use: {
          loader: "babel-loader", // babel-loader를 사용
        },
      },
    ],
  },
  mode: "development", // 없으면 warning 이 남
};
  • entry: 번들링의 시작점(엔트리)입니다. 여기서는 src/index.js를 엔트리로 지정합니다.
  • output: 번들링 결과물의 출력 위치와 파일명을 지정합니다. dist/bundle.js로 설정됩니다.
  • module.rules: Babel을 사용해 JavaScript 파일을 트랜스파일링하기 위해 babel-loader를 설정합니다.
  • mode : 개발모드를 설정해줄 수 있음.

 

3. 로더 설정

// 이미지 파일 로더
{
  test: /\.(png|jpe?g|gif|svg|webp)$/i,
  use: {
    loader: 'file-loader',
    options: {
      name: '[name].[contenthash].[ext]',
    },
  },
},

 

4. 프로젝트 빌드 및 실행

package.json의 script 항목에 다음 명령어 추가

"scripts": {
    "build": "webpack"
},

 

여기까지하고 npm run build 실행시 dist 폴더에 bundle.js 생성

 

 

Plugin

Webpack 플러그인

빌드 과정 중 특정 기능을 추가하거나 개선하는 역할

 

1. 파일 이름에 해시값 추가하기

캐시 문제를 해결하기 위해 빌드된 파일 이름에 해시값을 추가함

이 설정을 통해 코드가 변경될 때마다 새로운 파일 이름이 생성되어, 브라우저에서 업데이트된 js 파일을 캐시하지 않도록 할 수 있음

output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'bundle.[contenthash].js'
}

 

2. HTML Webpack Plugin 설정

npm install --save-dev html-webpack-plugin

파일 이름에 해시값이 추가되면, HTML 파일에서 자동으로 이 파일을 참조하도록 설정

 

webpack.config.js에 아래 내용 추가

const HtmlWebpackPlugin = require("html-webpack-plugin");

plugins: [
    new HtmlWebpackPlugin({
	      template: "index.html",
        filename: 'index.html',
    })
]

 

// 현재 webpack.config.js 상태
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");

module.exports = {
  entry: "./src/app.js",
  output: {
    path: path.resolve(__dirname, "dist"),
    filename: "bundle.[contenthash].js",
  },
  module: {
    rules: [
      //.css .js 등 서로 다른 확장자를 가진 파일을 처리할 때 어떤 규칙을 적용할지 정의
      {
        test: /\.js$/, // 어떤 파일을 대상으로 할지 정규표현식으로 작성
        exclude: /node_modules/, // node_modules 폴더는 제외
        use: {
          loader: "babel-loader", // babel-loader를 사용
        },
      },
      // 이미지 파일 로더
      {
        test: /\.(png|jpe?g|gif|svg|webp)$/i,
        use: {
          loader: "file-loader",
          options: {
            name: "[name].[contenthash].[ext]",
          },
        },
      },
    ],
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: "index.html",
      filename: "index.html",
    }),
  ],
  mode: "development", // 없으면 warning 이 남
};

 

3. dist 폴더 확인

npm run build 했을 때 다음과 같이 bundle에 hash 값이 잘 들어간 모습을 볼 수 있음

html 파일에도 업데이트 될 때마다 새로 생성된 번들이 자동으로 연결되고 있음

 

 

+ Clean Webpack Plugin

npm install --save-dev clean-webpack-plugin
const { CleanWebpackPlugin } = require("clean-webpack-plugin");

 plugins: [
    new CleanWebpackPlugin(),
    new HtmlWebpackPlugin({
      template: "index.html",
      filename: "index.html",
    }),
  ],

이 설정을 통해 빌드 시마다 HTML 파일이 업데이트 되며 파일을 삭제할 필요가 없어짐

플러그인은 순서에따라 동기적으로 동작하므로 꼭 순서를 잘 지켜줘야 함

 

다시 npm run build 시 마지막으로 생성된 파일 제외하고 생성됨

 

 

개발 서버 설정

webpack-dev-server 설치

npm install --save-dev webpack-dev-server

 

서버 설정 추가

devServer: {
    static: {
      directory: path.join(__dirname, "dist"),
    },
    port: 9000,
    open: true,
    hot: true,
  },
  • por: 개발 서버가 실행될 포트 번호입니다.
  • open: 서버가 실행되면 자동으로 브라우저를 엽니다.
  • hot: 코드 변경 사항을 실시간으로 반영합니다(핫 모듈 리플레이스먼트).

 

명령어 설정

package.json의 script 항목에 개발 서버 명령어 추가

 "scripts": {
    "build": "webpack",
    "start": "webpack serve"
 },

 

이제 npm start해서 실행하고, 변경사항이 브라우저에 반영

환경 변수 관리

실제 프로젝트에서 개발, 스테이징, 프로덕션 환경에 맞게 다른 설정을 적용해야 함

Webpack과 함께 dotenv-webpack 파일을 사용해 환경 변수를 관리

 

1. 환경 변수 파일 생성

프로젝트 루트에 .env.development, .env.production 파일을 생성해 각 환경에 맞는 변수를 설정

# .env.development
APP_API_URL=https://dev-api.example.com
# .env.production
APP_API_URL=https://api.example.com

 

2. dotenv-webpack 플러그인 설정

npm install --save-dev dotenv-webpack

 

webpack 설정에 플러그인 추가

const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
const DotenvWebpack = require("dotenv-webpack");

const mode = process.env.NODE_ENV || "development";

module.exports = {
	mode,
  plugins: [
    new CleanWebpackPlugin(),
    new HtmlWebpackPlugin({
      template: "index.html",
      filename: "index.html",
    }),
    new DotenvWebpack({
      path: `./.env.${process.env.NODE_ENV || "development"}`,
    }),
  ],
};

 

3. script 변경

  "scripts": {
    "build": "webpack",
    "start": "NODE_ENV=production webpack serve"
  },

 

4. 환경변수 사용

JS 파일에서 환경 변수를 다음과 같이 사용할 수 있음

const apiUrl = process.env.APP_API_URL;

 

5. 크로스 개발환경 추가

윈도우 환경에서 set NODE_ENV = ~ && 같은 형태로 사용하는데, 각 환경에서 오류가 나지 않도록 cross-env 패키지를 설치

npm install --save-dev cross-env
    "start": "cross-env NODE_ENV=development webpack serve"