리액트 CRA없이 기본 설정 하기

rkdghwnd·2023년 5월 1일
0

CRA(Create-React-App)

CRA는 리액트 프로젝트를 쉽게 구축할수 있도록 도와주는 도구입니다. 기본적인 로드와 빌드, 초기에 복잡한 Webpack과 Babel등을 직접 설정 할 필요 없이 명령어 한번에 개발에 필요한 환경을 세팅해줍니다.

일반적으로는 CRA를 사용하면 손 쉽게 리액트 환경을 구축 할 수 있습니다. 하지만 프로젝트에 따라서 Webpack, Babel에 추가적인 설정을 해야 하는 경우 직접 리액트 세팅을 하는게 쉬울 수 있습니다.
이번 게시글에서는 CRA없이 리액트 환경을 구축하는 법을 알아보겠습니다.

개발환경 구축

(1) 리액트 및 타입스크립트 설정

$ npm init -y
$ npm i react react-dom

프로젝트 기본설정과 리액트를 설치 해 줍니다.

$node_modules/.bin/tsc --init
최상위 경로에 tsconfig.json 파일이 생성 되는데 프로젝트에 맞게 수정하도록 합니다.

tsconfig.json

{
  "compilerOptions": {
    "sourceMap": true,
    "target": "es5",
    "lib": ["dom", "ES2015", "ES2016", "ES2017", "ES2018", "ES2019", "ES2020"],
    "allowJs": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "esModuleInterop": true,
    "module": "commonjs",
    "isolatedModules": true,
    "jsx": "preserve",
    "allowSyntheticDefaultImports": true,
    "baseUrl": "./",
    "outDir": "./dist",
    "moduleResolution": "node"
  },
  "exclude": ["node_modules"],
  "include": ["**/*.ts", "**/*.tsx"]
}

(2) 바벨(Babel) 설정

$ npm i -D babel-loader @babel/core @babel/preset-env
$ npm i -D @babel/preset-react @babel/preset-typescript

타입스크립트를 Babel이 해석할 수 있도록 트랜스파일러를 설치해줘야 합니다.
이후 아래와 같이 Babel 설정파일을 생성 후 작성합니다.

babel.config.js

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

@babel/preset-react : JSX로 작성된 코드들을 createElement 함수를 이용한 코드로 변환해 주는 바벨 플러그인이 내장(리액트를 변환하기 위한 프리셋)
@babel/preset-typescript : 타입스크립트를 변환하기 위한 프리셋
@babel/preset-env : preset-env는 ECMAScript2015+를 변환할 때 사용합니다. IE 지원을 위한 프리셋

(3) 웹팩(Webpack) 설정

$ npm i -D webpack webpack-cli webpack-dev-server
$ npm i -D html-webpack-plugin ts-loader

webpack, webpack-cli : 웹팩 기본파일
html-webpack-plugin: html 파일에 필요한 플러그인
webpack-dev-server: 개발 도중 변경사항을 확인할 수 있음
ts-loader : 타입스크립트 코드를 자바스크립트 코드로 변환

이후 아래 Webpack 설정파일을 생성 후 작성합니다.

webpack.config.js

const HtmlWebpackPlugin = require('html-webpack-plugin');
const path = require('path');
const webpack = require('webpack');
const prod = process.env.NODE_ENV === 'production';

module.exports = {
  mode: prod ? 'production' : 'development',
  devtool: prod ? 'hidden-source-map' : 'eval',
  entry: './src/index.tsx',
  resolve: {
    extensions: ['.js', '.jsx', '.ts', '.tsx'],
  },
  
  module: {
    rules: [
      {
        test: /\.tsx?$/,
        use: ['babel-loader', 'ts-loader'],
      },
    ],
  },
  
  output: {
    path: path.join(__dirname, '/dist'),
    filename: 'bundle.js',
  },

  plugins: [
	new webpack.ProvidePlugin({
      React: 'react',
    }),
    new HtmlWebpackPlugin({
      template: './src/index.html',
    }),
  ],
};

mode : 프로덕션 모드인지 개발 모드인지 확인하는 옵션
devtool : 프로덕션 모드인 경우엔 hidden-source-map을 권장합니다. (외부에서 리액트 구조를 확인할 수 없게 해줍니다.)
resolve : 확장자나 경로를 알아서 처리할 수 있도록 설정하는 옵션입니다.
module : 이 옵션에 설치한 ts-loader와 babel-loader를 설정하면 됩니다. loader들은 오른쪽에서 왼쪽 방향으로 적용되기 때문에 ts-loader가 babel-loader보다 오른쪽에 위치해야 합니다.
output : 번들화 된 파일을 export할 경로와 파일명을 설정합니다.
plugins : 설치한 플러그인을 적용하는 옵션입니다.

(4) Webpack-dev-server 추가설정

webpack-dev-server는 핫리로딩 기능을 갖춘 개발 서버로 개발하는 과정에서 코드가 수정이 일어났는지 바로바로 확인할 수 있어서 유용합니다. 또한 프록시 설정기능을 제공하여 CORS문제 등 브라우저 및 서버에러를 처리할 수 있습니다.

const webpack = require('webpack');

...
module.exports = {...
  devServer: {
    historyApiFallback: true,
    inline: true,
    port: 3000,
    hot: true,
    publicPath: '/',
  },

  plugins: [
    ...,
    new webpack.HotModuleReplacementPlugin(),
    ...,
  ],
...
}

historyApiFallback : 히스토리 API를 사용하는 SPA 개발 시 설정하며 404에러가 발생하면 index.html로 리다이렉트 한다.
inline : inline모드를 활성화 해준다.
port : 접속 포트를 설정한다.
hot : webpack의 HMR기능을 활성화 한다. (리로드 기능)
publicPath : 브라우저를 통해 접근하는 기본 주소값을 설정한다.

(5) package.json 변경설정

...,
"scripts": {
    "dev": "webpack serve --mode development --open --hot",
    "build": "webpack --mode production",
    "prestart": "npm build",
    "start": "webpack --mode development"
  },
...

예전에는 webpack-dev-server 명령어로 실행했는데 webpack serve로 바뀌었습니다.(webpack-cli는 4버전이랑 같이 써야 오류가 안난다.)
dev 명령어는 webpack serve를 실행하는 명령어고 start는 리액트 프로젝트를 빌드해 dist폴더 안에 번들링 된 파일을 추출시켜 줍니다.

(6) react 기본파일 설정
src/index.tsx

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

const rootElement = document.getElementById('root');
ReactDOM.render(<App />, rootElement);
src/App.tsx

import React from 'react';

const App = () => <>Test</>;

export default App;
src/index.html

<!DOCTYPE html>
<html lang="ko">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <div id="root"></div>
  </body>
</html>
profile
rkdghwnd's dev story

0개의 댓글