webpack과 React

leekoby·2023년 3월 21일
0

webpack

목록 보기
2/2
post-thumbnail

🔧변경내용🔨

제목날짜내용
발행일23.03.21

📌들어가기에 앞서

해당 포스트는 WEBPACK에 대해 학습한 내용을 정리하며 기록한 내용입니다.




📖 리액트가 번들링이 필요한 이유

프론트엔드 개발에서 번들링은 사용자가 더 쉽고 빠르게 프론트엔드 애플리케이션에 접근할 수 있도록 용량을 줄이거나 파일을 최소화하여 유저에게 전달하는 과정

리액트는 당시 앵귤러의 단점을 보완할 수 있는 대체재로서 뷰와 함께 거론되기 시작

리액트가 주목받던 이유 중 하나가 “프레임워크가 아니고 라이브러리"라는 점 때문

프론트엔드 개발에 꼭 필요한 점 말고는 코드를 추가하지 말고, 더 필요한 것이 있으면 개발자가 설치하라는 의견을 제시

Learn Once, Write Anywhere
We don’t make assumptions about the rest of your technology stack, so you can develop new features in React without rewriting existing code.

리액트 개발진은 개발자가 어떤 기술 스택을 사용할지 미리 가정하지 않는다.

그래서 개발자가 새로운 코드를 다시 작성할 필요 없이 기능을 추가할 수 있다.

당시에 앵귤러의 갑작스러운 버전 변경과 논란과 겹쳐서 리액트의 이런 자유도는 많은 프론트엔드 개발자들의 관심을 받게 되었다.

반대로 이런 특성 때문에 생기는 문제도 많다.

“리액트"만 알아서는 개발하기가 어렵다는 점이다.

react, react-dom, react-scripts, create-react-app, react-router-dom, storybook, styled-component등 많은 부가 라이브러리를 설치하고 활용하는 법을 배웠다.

이렇게 알아야 하는 점이 많아지다 보니, 리액트 개발진은 이런 문제를 한 번에 해결할 수 있는 create-react-app이라는 툴 체인을 개발하여 초급 리액트 개발자가 쉽게 리액트에 접근할 수 있도록 했다.

리액트를 “간단하게" 시작하기 위해 create-react-app에서 사용되는 툴 목록은 어마어마하다.

create-react-app의 큰 부분인 react-scripts에 사용되는 라이브러리 목록만 봐도 알 수 있다. (여기서도 웹팩이 사용)

반대로, 사용자에게 최적의 번들을 제공하기 위한 전문 프론트엔드 개발자들은 이런 create-react-app의 거대한 라이브러리 목록을 줄이고자 직접 웹팩을 설치하여 하나씩 리액트와 그에 필요한 라이브러리 설정을 하기 시작했다.

리액트는 프론트엔드 라이브러리로서 최소한의 기능을 제공하고자 가볍게 만들어졌지만, 시간이 지나면서 아이러니하게도 개발자의 다양한 니즈를 충족시키기 위해 더 많은 라이브러리를 필수적으로 사용해야만 했고, 개발자가 필요한 이런저런 라이브러리를 골라서 번들링 할 수 있는 웹팩이 필요하게 되었다.




📖 리액트 개발에 꼭 필요한 라이브러리

react, react-dom

너무나 당연한 이야기지만, 리액트 컴포넌트와 Hooks, 라이프 사이클에 대한 정보가 모두 들어있는 리액트와 이 리액트 코드를 브라우저에 보여줄 수 있는 react-dom은 꼭 필요


babel

React를 학습하기 전, JSX부터 배워야 했었다. 그런데, 브라우저에서 JavaScript는 읽을 수 있지만 JSX는 읽을 수 없다.

그렇다면 지금까지 React를 JSX로 작성해왔는데 어떻게 브라우저에서 내가 만든 React 애플리케이션을 볼 수 있었을까?

create-react-app에 포함되어 있는 babeljsxjs로 변경해주어 번들링을 해줬기 때문이다.

참고로 babelJSX를 JavaScript로 변경하여 entry에서 불러올 수 있게 만들어줬기 때문에 로더의 일종으로 볼 수 있겠다.


css-loader

create-react-app으로 만들어진 애플리케이션을 보면 import 'aaa.css' 와 같이 입력해도 CSS가 적용되던 것을 알 수 있다. 우리가 배웠던 css-loader가 필요하다는 것을 쉽게 알 수 있다.




📖 리액트 개발에 꼭 필요한 라이브러리


react-hot-loader

react-hot-loaderwebpack-dev-server처럼 저장할 때 마다 변경사항을 개발 환경에 적용해주는 라이브러리
추가적인 특징이 있다면 react-hot-loader는 리액트 상태를 유지시켜준다.


eslint

eslint는 JavaScript로 개발 시 자주 접하는 에러를 방지하기 위한 린터.

eslint 역시 많은 configplugin이 있는데, 이를 잘 조합하면 리액트에서 자주 접하는 에러를 미리 발견하는데 도움이 된다.


prettier

prettier는 JavaScript로 개발 시 통일성 있게 코드 형식을 맞출 수 있게 도와주는 툴.

eslint와 조합해서 통일된 코드 형식까지 강요할 수도 있다.




🎯 실습

이번 과제에서는 create-react-app으로 만든 리액트 웹 애플리케이션의 src 디렉터리 코드만을 가지고 webpack으로 번들링하는 것이다.

나만의 아고라 스테이츠 서버 레퍼런스 코드를 이용해서 시도해봤다.

과제 내용


Bare Minimum Requirement

  • 리액트 웹 애플리케이션을 제작합니다.

  • babel-loader, style-loader, css-loader, html-webpack-plugin 등 필요한 로더나 플러그인을 스스로 학습하고 리액트 앱을 번들링합니다.


Advanced Challenge

  • github page 배포
  • 작동 모드 설정
  • Output 관리
  • Asset 관리
  • 개발용 서버
  • eslint, prettier
  • webpack-bundle-analyzer




Bare Minimum


1.개발환경 초기화

npm i -y


2. 리액트 라이브러리 설치

npm i react react-dom

  • react : 리액트 컴포넌트와 Hooks, 라이프 사이클에 대한 정보가 들어있는 코어 라이브러리

  • react-dom : React의 데이터를 실제 DOM으로 변경하기 위해 사용


3. 웹팩 설치

npm i -D webpack webpack-cli

  • webpack: 웹팩 코어

  • webpack-cli: 터미널에서 웹팩 사용


4. 바벨 설치

자바스크립트로 작성된 프로젝트는 번들링할때는 webpack.config.js에서 entryoutput만 설정하고 번들링할 수 있었다.

하지만 JSX로 작성된 리액트 코드는 바벨을 통해서 브라우저가 이해할 수 있는 자바스크립트로 변환해서 번들링해줘야 한다.

JSX를 자바스크립트로 변환 처리 해주는 것이 바벨 로더

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

preset이란 자주 사용하는 babel 플러그인들을 합쳐서 제공하는 것을 의미

  • @babel/core : 바벨 코어

  • @babel/preset-env: 구문 변환 및 폴리필 같은 다양한 처리를 해주는 preset

  • @babel/preset-react: jsx 구문을 js로 바꿔주는 등의 처리를 해주는 preset

  • babel-loader : 바벨과 웹팩을 연결

//webpack.config.js
const path = require('path');
module.exports = {
  entry: './src/index.js', // 빌드 시작 위치
  output: {
    // 빌드결과 저장 위치
    filename: 'app.bundle.js',
    path: path.resolve(__dirname, 'docs'),
    clean: true,
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: [
              ['@babel/preset-env'],
              ['@babel/preset-react', { runtime: 'automatic' }],
            ],
          },
        },
      },
    ],
  },
};
  • loader이기 때문에 module.rules 하단에 작성

5. CSS 번들링

  • style-loadercss-loader로 번들링하면 header태그 안에서 internal 방식으로 번들링 됨

  • external 방식으로 CSS 번들링하는 플러그인인 css-minimizer-webpack-plugin 를 설치했다.

npm i -D css-minimizer-webpack-plugin
npm i -D mini-css-extract-plugin

mini-css-extract-plugin은 css 파일을 한줄로 압축한다.

//webpack.config.js
const path = require('path');

const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');

module.exports = {
  entry: './src/index.js', // 빌드 시작 위치
  output: {
    // 빌드결과 저장 위치
    filename: 'app.bundle.js',
    path: path.resolve(__dirname, 'docs'),
    clean: true,
  },

  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: [
              ['@babel/preset-env'],
              ['@babel/preset-react', { runtime: 'automatic' }],
            ],
          },
        },
      },
      {
        test: /\.css$/,
        use: [MiniCssExtractPlugin.loader, 'css-loader'],
        exclude: /node_modules/,
      },
    ],
  },
  optimization: {
    minimizer: [
      new CssMinimizerPlugin(), // css를 줄여주는 플러그인
    ],
  },
  plugins: [
    new MiniCssExtractPlugin({
      filename: 'style.css',
    }),
  ],
};
//index.js
import style from './index.css'

index.js파일 안에 css파일이 import 되어 있어야함


6. HTML 번들링

npm install -D html-webpack-plugin

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');

module.exports = {
  entry: './src/index.js', // 빌드 시작 위치
  output: {
    // 빌드결과 저장 위치
    filename: 'app.bundle.js',
    path: path.resolve(__dirname, 'docs'),
    clean: true,
  },

  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: [
              ['@babel/preset-env'],
              ['@babel/preset-react', { runtime: 'automatic' }],
            ],
          },
        },
      },
      {
        test: /\.css$/,
        use: [MiniCssExtractPlugin.loader, 'css-loader'],
        exclude: /node_modules/,
      },
    ],
  },
  optimization: {
    minimizer: [
      new CssMinimizerPlugin(), // css를 줄여주는 플러그인
    ],
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: './public/index.html',
    }),
    new MiniCssExtractPlugin({
      filename: 'style.css',
    }),
  ],
};

여기까지 진행하면 docs 폴더에 최소한의 웹팩 설정으로 생성된 번들 결과가 JS, CSS, HTML 파일이 생성된다.




Advanced Challenge


개발환경과 배포환경 나누기

Mode |webpack 러닝 가이드
Mode | 공식문서

웹팩 설정 파일에 mode 속성을 추가해서 사용할 수 있다.

기본값은 production(배포 모드)이고, 웹팩 모듈 번들링 과정에서 코드를 최적화해서 용량을 줄인다.

반면에 development(개발 모드)는 안전한 로컬 환경에서 개발한다고 가정하고, 편리한 개발을 위해서 어느 파일에서 에러가 발생했는지도 알려주는 최적화되지 않은 번들 파일을 제공한다.

웹팩 설정파일을 두가지 모드로 설정하기 위해서 webpack-merge를 설치한다.

npm install -D webpack-merge

기본 설정 파일을 머지한 각각의 개발/배포 환경에 필요한 설정파일을 따로 만들어준다.

webpack-dev-server도 설치해서 변경된 코드를 개발 서버에 반영해서 보여줄 수 있도록 설정을 추가했다.

npm i -D webpack-dev-server

// webpack.config.dev.js
const { merge } = require('webpack-merge');
const baseConfig = require('./webpack.config.js');
const path = require('path');

module.exports = merge(baseConfig, {
  mode: 'development',
  devServer: {
    static: {
      directory: path.resolve(__dirname, 'docs'),
    },
    port: 3001,
    hot: true,
  },
});
// webpack.config.prod.js
const { merge } = require('webpack-merge');
const baseConfig = require('./webpack.config.js');

module.exports = merge(baseConfig, {
  mode: 'production',
});
//package.json scripts에 추가
 "scripts": {
    "build": "webpack --config webpack.config.prod.js",
    "dev": "webpack server --open --config webpack.config.dev.js",
  },

eslint 설치

코드에 문제가 없는지 검사하기 위해서 설치

npm install -D eslint eslint-plugin-react @babel/eslint-parser

//pacakge.json scripts에 추가 
 "lint": "eslink ./src",

웹 접근성에 대해서 지켜야하는 부분을 알려주는 eslint rule 설치해봄

npm install -D eslint-plugin-jsx-a11y

따로 설정파일을 작성해야 한다.

// .eslintrc.js
module.exports = {
  parser: "@babel/eslint-parser",
  env: {
    browser: true,
    commonjs: true,
    es6: true,
    node: true,
  },
  extends: [
    "eslint:recommended",
    "plugin:react/recommended",
    "plugin:jsx-a11y/recommended",
  ],
  parserOptions: {
    ecmaFeatures: {
      jsx: true,
    },
    ecmaVersion: 2020,
    sourceType: "module",
  },
  settings: {
    react: {
      version: "18.2.0",
    },
  },
  plugins: ["react"],
  rules: {
    "react/react-in-jsx-scope": 0,
    "react/jsx-uses-react": 0,
    "react/prop-types": 0,
  },
};


prettier 설치

코드 형식 통일(VSCode extension으로도 할 수 있지만 직접 작성할줄도 알아야한다.)

npm install -D prettier

//pacakge.json scripts에 추가 

"pretty": "prettier --write ./",

따로 설정파일을 만들어줘야 한다.

// .prettierrc.js
module.exports = {
  singleQuote: true,
  jsxSingleQuote: true,
};



📚 레퍼런스

코드스테이츠 수업자료

webpack 공식문서

웹팩 ( Webpack + TypeScript + React ) | 1-blue의 블로그

웹팩 핸드북 | 캡틴판교

[React] 리액트 webpack & babel 설정하기 | 꾸생의 DevLog

순수(?) 리액트 앱에 webpack 설정하기 (without CRA) | 365kim

Webpack 기초 | hih0327.log

[react] CRA없이 React환경 구축하기 (웹팩, 바벨) | phrygia devlog

jsx-ESlint

Mode | webpack 러닝 가이드

Babel | 공식문서

0개의 댓글