나는 오늘도 멋있다

React-webpack 시리즈 - 1 (개발 서버열기) 본문

Web/WebPack

React-webpack 시리즈 - 1 (개발 서버열기)

나는 오늘도 멋있다 2023. 11. 7. 00:19

 

SSR을 구현하기위해 Next.Js를 공부하게 되었고, SSR을 React로만으로도 구현하고싶어서 express를 이용하여 구현하였다.

이후에는 SSR, CSR의 차이점을 보게되었고, SSR은 webpack을 이용하여 설정했기때문에 CSR도 webpack으로 구현해야하는 상황이다. 그래서 여기까지 와버렸다. 하나를 시작하려했더니 갑자기 해봐야 할 것 들이 늘어났다...

 

 

Webpack이란?

JS 애플리케이션을 번들링하기 위한 JS모듈 번들러이다. 프로젝트에서 사용되는 여러 모듈과 종속성을 효율적으로 관리하고,

번들로 묶어 하나의 파일로 만드는 것 이다.

 

 

나는 기본적으로 React를 시작할때 CRA명령어를 통해 프로젝트를 시작하거나, 테스할때도 해당 명령어를 사용해서 빠르게 사용한다.  webpack은 초반에 공부할때 잠깐 만지작 했었다. 그때는 너무 이해하기 힘들었고, 봐도 몰랐다. 그래도 지금은 학습을 좀더한 상태고, CRA도 webpack을 내부적으로 사용하고 있기때문에 다시한번 보려한다. 

 

1. Webpack 테스를 위한 디렉토리 구조

CRA와 비슷한 구조로 만들어보려한다.

CRA와 비슷한 구조로 만들어보려한다.  

 

2. package 설치

npm i react react-dom
npm i -D @types/react @types/react-dom typescript

 

처음부터 패키지를 다설치하지 않을거다. 어떤 패키지가 어디에 쓰이는지 알고싶다. 하나씩 설치하면서 비교해 볼 예정이다.

 

3. tsconfig 생성

npx tsc --init

 

 

해당명령어를 사용하면 많은 주석들과 함께 활성화 되어있는 코드가 있는데. 주석달린 설정은 지웠다.(패키지를 설치하지 않고 해당명령어는 실행되지않는다.) 하지만 이후에 몇가지는 다시 추가해야한다.

 

4. 간단한 코드작성

//public/index.html

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>React-webpack</title>
</head>
<body>
    <div id="root"></div>
</body>
</html>

 

//src/index.tsx

import React from "react";
import ReactDOM, { createRoot } from "react-dom/client";
import App from "./App";

const root = ReactDOM.createRoot(document.getElementById('root') as HTMLElement)

root.render(
    <React.StrictMode>
        <App/>
    </React.StrictMode>
)

 

//src/App.tsx

import React, {useState} from "react";

function App(){
    const [count, setCount] = useState<number>(0);
    return(
        <div>
            <span>Count: {count}</span>
            <button onClick={()=> setCount( count + 1)}> + </button>
            <button onClick={()=> setCount( count - 1)}> - </button>
        </div>
    );
}

export default App;

 

각각의 파일에 적어주면 App.tsx 와 index.tsx에서는 JSX문법을 사용하기 위해 --jsx플래그를 사용하라는 문구가 뜬다.

여기서 tsconfig.json에 설정을 추가해주면 된다.

//tsconfig.json

{
  "compilerOptions": {
    "target": "es2016",
    "module": "commonjs",
    "esModuleInterop": true,
    "forceConsistentCasingInFileNames": true,
    "strict": true,
    "skipLibCheck": true,
    "jsx": "react-jsx", -- 추가
  }
}

 

5. webpack 설정하기

다른 사람들것도 참고해보고, 공식문서도 보고했는데 공통,개발,배포 이런식으로 나누는 것 같았다. 개발,배포,공통 순서대로 만들어 볼예정이며 개발,배포 설정을 만든후에 코드의 반복적인것을 공통적인 파일로 분류하려한다.

 

Concepts | 웹팩

웹팩은 모듈 번들러입니다. 주요 목적은 브라우저에서 사용할 수 있도록 JavaScript 파일을 번들로 묶는 것이지만, 리소스나 애셋을 변환하고 번들링 또는 패키징할 수도 있습니다.

webpack.kr

 

기본적인 webpack설정을 입력해준다.

//webpack.dev.js

const path = require('path');


module.exports = {
    // 개발환경 최적화: 개발모드
    mode: "development",
    // 웹팩의 출발지점 설정
    entry: path.resolve(__dirname,'./src/index.tsx'),
    devServer: {
        // 개발서버 실행후 브라우저를 open여부
        open: true,
        // 애플리케이션의 상태를 유지하고 변경된 부분만 업데이트
        hot: true,
        // 개발서버가 열릴 Port번호
        port: 3000,
        /*
        SPA에서 브라우저 히스토리와 라우팅을 관리하는데 유용하며,
        사용자가 잘못된 경로로 이동하였을경우 클라이언트측에서 라우팅을 처리하고
        적절한 화면을 표시하기 위함
        */
        historyApiFallback: true,
        // 파일 변경이 감지되면 페이지를 다시 로드하고 새로고침
        liveReload: false,
    },
    /*
    module-rules: webpack은 기본적으로 JS, JSON만 해석할수있다.
    1. test: 어떤파일을 변환할지 지정하는 속성
    2. use: 파일을 변환할때 어떤 로더를 사용해야하는지
    3. exclude: 외부모듈을 제외한다. 번들파일의 크기를줄이고, 빌드성능을 향상
    */
    module: {
    rules: [
      {
        test: /\.(ts|tsx|js|jsx)$/,
        use: "babel-loader",
        exclude: /node_modules/,
      },
    ],
  },
    /*
        resolve: 파일 확장자를 어떤 순서로 찾을것인지 webpack에게 알림
    */
    resolve:{
        extensions:[".js", ".ts", ".jsx", ".tsx", ".css", ".json"]
    }

}

 

package.json으로 이동하여 start명령어를 입력해준다

//package-json

{
  "name": "react-webpack",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "start": "webpack-dev-server --config webpack.dev.js", // 추가
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "react": "^18.2.0",
    "react-dom": "^18.2.0"
  },
  "devDependencies": {
    "@types/react": "^18.2.35",
    "@types/react-dom": "^18.2.14",
    "typescript": "^5.2.2",
  }
}

 

명령어를 입력해주고 명령어를 실행하면 (npm run start)

webpack-dev-server 필요

모듈을 찾을수 없다고 나온다. 설치해주자

npm i -D webpack-dev-server

 

이후에 다시 npm run start를 실행하면 아래처럼 다시한번물어본다. webpack-cli를 받을거냐고... Yes

 

webpack-cli가 필요

webpack-dev-server 와 webpack-cli를 다받은후에 다시 npm run start를 하면 아래처럼 babel-loader가 필요하다고 나온다

 

해당명령어로 다시 설치한다.

npm i -D babel-loader

 

다시 실행해본다 npm run start ....

babel.config.json필요

나는 이부분에서 3시간가량을 버렸다. babel도 webpack, tsconfig처럼 설정파일이 필요한건데... 그냥 패키지 설치만하면 적용되는줄 알았다. 그래서 다른사람코드를 보고, 공식문서를 보고, 나한테 없는파일이 있다는것을 알게 되었고 그제서야 공식문서를 봤다.

 

 

Presets · Babel

Babel presets can act as sharable set of Babel plugins and/or config options.

babeljs.io

[babel.config.json: 일반적으로 전체프로젝트에 대한 기본 설정을 정의할때 사용]

[babelrc: 특정 디렉토리나 파일에대한 babel 설정을 정의하기 위해 사용]

 

두파일은 차이가 있다. 확장자, 스코프, 우선순위, 환경변수등등...  간단하게 정리하자면 babel.config.json 전역으로 적용된다. 우선순위는 babel.config.json이 높으며 동적 설정을 하는데 더유연하다고 한다. babelrc는 해당디렉토리와 하위디렉토리에 적용되며, babel.config.json보다 우선순위가 낮다. 특정 디렉토리에서 사용하면 오버라이드가 가능하다. 상위디렉토리에 babelrc가 있고 하위 디렉토리에 babelrc가 있으면 하위 디렉토리의 babelr가 우선순위가 더높다. 이러한 특징들이 있다~

 

ps:  babel에 대한 내용을 적으려 했지만 내용이 너무많아서 따로 다뤄야겠다...

 

위에 에러를 해결하기 위해서는 아래 명령어를 입력해주고

npm i -D @babel/preset-typescript @babel/preset-react

 

root에 babel.config.json을 생성하고 아래처럼 입력해준다.

//babel.config.json

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

 

이렇게 까지 작성한후에 다시 npm run start 를 하면 localhost://3000 으로 열릴것이다. 하지만 빈페이지 일텐데 이때 webpack에서

plugin을 추가해줘야한다.

npm i -D html-webpack-plugin
//webpack.dev.js
.... code


plugins: [
        new HtmlWebpackPlugin({
            template: "public/index.html"
        })
    ]

 

추가까지 끝난후 npm run start을 다시 실행한다면 정상적으로 나오는 것을 확인할수 있다. 간단하게 내가 개발하는 웹을 실행하는 서버를 보기위해서는 이정도이다.  추가해야할 모듈은 더많이있다. babel, Polyfill, css loader 등등 말이다. 

 

다음편에서 이어서 써야겠다.

 

 

[이번글에서 설치한 패키지]

npm i react react-dom
npm i -D typescript @types/react @types/react-dom
npm i -D webpack webpack-cli webpack-dev-server 
npm i -D babel-loader @babel/preset-react @babel/preset-typescript
npm i -D html-webpack-plugin

[이번글의 구조]