Javascript를 배우고 있습니다. 매일 배운 것을 이해한만큼 정리해봅니다.
오늘은 Webpack에 대해 정리해봅니다.
얼마 전 어떤 CTO 분을 만나 개발자로서 앞으로 익혀야 할 것들을 자세히 들을 수 있는 시간이 있었다. 이 때 cra - eject 방식 말고 webpack 설정 경험에 대한 질문을 받았는데, 일전에 튜토리얼만 쓱쓱 따라해본 경험 뿐이라 자세히 이야기를 나눌 수 없었다. 이참에 한 번 더 webpack 기본 설정에 대해서 정리해보려고 한다.
<script>
태그를 이용해 불러오고 실행하는데, 렌더시켜야 하는 코드가 여러 개가 있을 경우 곧이 곧대로 script를 붙여서 렌더시킨다고 하면 로딩 과정에서 무리가 있고(병목현상), 또 어마어마한 양의 script를 복붙해야 한다.react는 jsx라는 문법을 사용한다. 마치 js 코드에 html 태그를 섞어 쓴 듯한 모양을 하고 있기 때문에 이를 빌드할 때에는 바벨과 웹팩을 통해 jsx와 같은 실험적인 문법 구조를 js로 변환시키고 html dom에 띄우기 위해 번들링하는 작업이 필요하다. babel과 webpack이 모두 필요하다는 말.
물론 이 과정은 create react app
이라는 과정을 통해 자동으로 설정할 수 있다. 보통 react 코드들은 cra를 통해 빌드를 하고, eject한 후부터는 자체 설정에 의해 관리하는 경우가 많다고 한다. 이럴 때 cra 과정에서 어떤 작업을 대체하는지 알고 있어야 설정에 변화를 주거나 잘 운영할 수 있다.
웹팩 공식문서와 ZeroCho님의 유튜브 강좌를 번갈아 가면서 확인하고 파일을 만들어봤다.
예제 코드 전체 보기 : https://github.com/naseriansuzie/react-webpack-test
과정은 크게 npm 설정 후 > 웹팩을 설정하고 > 마지막으로 변경 감지 시 자동 빌드 설정을 하는 것으로 나누어 보았다.
가장 먼저 폴더를 생성하고, 해당 폴더에서 npm init
을 하고 package.json을 설정한다.
mkdir react-webpack-test
cd react-webpack-test
npm init
그런 다음 react와 react-dom을 dependency로 설치한다.
npm i react react-dom
webpack과 webpack-cli를 devdependency로 설치한다.
npm i -D webpack webpack-cli
Webpack으로 번들링하기 위해서는 터미널 창에 webpack을 쳐줘야 하는데 cli가 global로 되어 있지 않은 이상 command not found가 나올 것이다. 대신에 1) script를 직접 짜서 해당 script를 돌리거나 2) npx의 도움을 받아야 한다.
"script" : {
"dev" : "webpack"
}
npx webpack
이렇게 하면 기본적인 패키지는 설정한 셈이다.
번들링 후 렌더시킬 html 파일을 하나 만들고 <div id="root></div>
를 body 태그 안에 넣어둔다. 나중에 여기에 전체 번들 파일을 넣을 것이므로...
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Test</title>
</head>
<body>
<div id="root"></div>
<script src="../dist/bundle.js"></script>
</body>
</html>
루트 컴포넌트 준비: 나는 app.jsx에 Hello라는 컴포넌트를 담는 초간단 구조를 준비했다.
//Hello.jsx
import React from "react";
const Hello = () => <div>hello</div>;
export default Hello;
//app.jsx
import React from "react";
import { render } from "react-dom";
import Hello from "./Hello";
render(<Hello />, document.querySelector("#root"));
이제 webpack의 설정을 해 줄 차례이다. 가장 중요+복잡+신기한 부분 :)
폴더의 루트에서 webpack.config.js 파일을 만든다.
node의 common js 모듈에 따라서 module.exports를 설정하면서 객체 선언을 한다.
const path = require('path');
module.exports = {
name: 'react with webpack setting',
//어떤 것에 대한 웹팩 설정인지 제목 작성
mode: 'development',
// 개발모드 때는 development, 실제는 production
devtool: 'eval',
// production에서는 'hidden-source-map'을 많이 씀
reslove: {
extensions: ['.js', '.jsx'],
// 번들링 할 파일들의 확장자 종류를 배열에 나열
},
entry : {
app: ["./app", "./Hello"],
// 번들링 할 파일들을 지정. 루트 파일 하나만 지정해도 문제 없음
},
output : {
path: path.resolve(__dirname + 'dist'),
//번들링 한 파일을 위치할 곳 명시
publicPath: '/dist',
//가상 주소처럼 지정, webpack-dev-server 사용 시 필요
filename: "bundle.js",
//번들한 파일 이름 지정
}
};
기본적인 구조는 entry가 번들되어 output이 되는 구조인 것을 볼 수 있다. 여기에 일부 설정들을 추가해주는데 module
과 plugins
에 추가해주면 된다.
이 때 사용할 babel을 먼저 설치해야 한다.
npm i -D @babel/core @babel-preset-env @babel-preset-react babel-loader
다시 webpack.config.js로 가서 module 설정을 완료해준다.
const path = require('path');
module.exports = {
name: 'react with webpack setting',
//어떤 것에 대한 웹팩 설정인지 제목 작성
mode: 'development',
// 개발모드 때는 development, 실제는 production
devtool: 'eval',
// production에서는 'hidden-source-map'을 많이 씀
reslove: {
extensions: ['.js', '.jsx'],
// 번들링 할 파일들의 확장자 종류를 배열에 나열
},
entry : {
app: ["./app", "./Hello"],
// 번들링 할 파일들을 지정. 루트 파일 하나만 지정해도 문제 없음
},
module : {
rules : [{
test: /\.jsx?/,
// 규칙을 적용할 파일 종류를 설정
loader: "babel-loader",
options: {
// babel 설정
presets: [
// preset(plugin들의 모임)을 나열
["@babel/preset-env", {
// 특정 preset에 대해 설정을 지정할 수 있음
targets : {
browsers: ["> 5% in KR"]
// 어떤 브라우저에 대응할지를 명시
},
debug: true
}], "@babel/preset-react"
]
}
}]
},
output : {
path: path.resolve(__dirname + 'dist'),
//번들링 한 파일을 위치할 곳 명시
publicPath: '/dist',
//가상 주소처럼 지정, webpack-dev-server 사용 시 필요
filename: "bundle.js",
//번들한 파일 이름 지정
}
};
이렇게 복잡하지만 babel과 webpack을 이용해 설정을 완료할 수 있다.
그런 다음 초기에 설정해두었던 npx webpack
이나 npm run dev
script를 통해 리액트를 빌드할 수 있다.
이렇게 cra 과정을 대신해서 webpack으로 react를 build해서 사용할 수 있다. 사용하다가 여러 수정사항이나 업데이트가 나올 때마다 해당하는 내용을 webpack.config.js에 반영하면 된다.
node에서 nodemon 없이 서버 수정 작업을 하다 보면 수시로 서버에 오류는 없는지, 변경 사항이 반영되었는지 확인을 하는 것이 어려운 것처럼 현재 빌드한 react에서도 변경사항이 있을 때마다 계속 webpack을 통해 번들링을하고 빌드를 해야 한다.
무척 귀찮은 작업이므로 nodemon처럼 webpack-dev-server와 react-hot-loader를 설정하면 빌드한 내용을 개발 서버에서 수행하며 변경을 감지할 때마다 바로 view에서 확인할 수 있다.
이를 위해서 2개 패키지를 설치해야 한다.
npm i -D webpack-dev-server react-hot-loader
packagejson 파일에서 script를 수정한다. 나는 dev server & hot loader를 지정했을 때와 그렇지 않을 때 비교를 해보기 위해 다른 script를 추가했다.
"script" : {
"dev" : "webpack",
"dev-hot" : "webpack-dev-server --hot"
}
Reactdom에 렌더시킬 루트 컴포넌트 파일에서 react-hot-loader/root에서 hot을 꺼내 컴포넌트에 씌운다.
import React from "react";
import { render } from "react-dom";
import { hot } from "react-hot-loader/root";
import Hello from "./Hello";
const Hot = hot(Hello);
render(<Hot />, document.querySelector("#root"));
npm run dev-hot
를 치면 https://localhost:8080에서 빌드된 리액트 뷰를 볼 수 있고, 변경사항이 발생할 때마다 계속 터미널 창에서 감지하는 것을 볼 수 있다. 나는 html을 public 폴더 아래에 위치해서 https://localhost:8080/public에서 아래와 같은 화면을 볼 수 있었다.