💡 이번에 배운 내용
- Section4. 사람과 기계가 모두 쉽고 빠르게 접근 가능한 Web App을 만들 수 있다.
- Unit3. 번들링과 webpack : 프론트엔드 개발에서 번들링은 사용자가 더 쉽고 빠르게 프론트엔드 애플리케이션에 접근할 수 있도록 용량을 줄이거나 파일을 최소화하여 유저에게 전달하는 과정이다. 이 개념과 이를 도와주는 툴인 webpack에 대해 학습한다.
이번에는 직접 HTML,CSS,JS로 된 프로젝트와 react로 된 프로젝트를 번들링해보는 실습도 같이 진행하였다. 직접 해보니 어떤 방법으로 해야할지, 어떤 작업이 필요한지 잘 파악할 수 있었고 깃헙 페이지에 직접 배포할 수도 있었다. 평소 리액트로 된 작업물들은 어떻게 깃헙 페이지로 배포할지 몰랐는데 이번 기회에 잘 알 수 있었다. 재밌다!
이참에 지난번 유닛에서 작업했던 결과물고 배포해야겠다. 😁
번들링, 웹팩 webpack, 빌드, entry, output, loader, plugins, mode, optimization, babel, css-loader, style-loader, webpack-cli
프론트엔드 개발에서 번들이란 이름 그대로 웹 애플리케이션을 제공하기 위한 파일 묶음을 의미한다. 사용자가 브라우저를 열고 주소를 입력하면 프론트엔드 개발자가 번들링한 여러 파일을 다운 받는다. 이 파일을 브라우저가 실행하여 웹 애플리케이션이 실행된다.
번들링이 필요한 이유는?
아래와 같은 상황을 해결하기 위해선 번들링이 필요하다.
위의 상황을 해결하고, 용량을 줄이면서 파일을 통합하기 위해 번들링이 필요하다. 이는 파일의 용량이 줄어들어 퍼포먼스에도 영향을 미치기 때문에 사용자에게도 더 나은 UX를 제공할 수 있다.
Webpack은 프론트엔드 웹 애플리케이션 배포를 위해 사용하는 번들링 툴 중 하나다. 2022년 7월 기준으로 가장 많이 사용하는 번들러이기도 하다.
이 Webpack은 여러 개의 파일을 하나의 파일로 합쳐주는 모듈 번들러이다. 모듈 번들러란 HTML, CSS, JavaScript 등의 자원(모두 모듈이라 한다)을 조합해 하나의 묶음으로 번들링(빌드)하는 도구를 의미한다.
Webpack에서의 모듈이란 JS뿐만 아니라 HTML, CSS, 이미지도 전부 포함하는 개념이다. Webpack은 주요 구성 요소인 로더(loader)를 통해 이런 다양한 모듈들을 번들링한다.
기술이 발전하며 JavaScript 코드량이 많이 증가했고, 대규모의 의존성 트리를 가진 대형 웹 앱의 등장으로 세분화된 모듈 파일이 증가했다. 이 모듈 단위의 파일들을 브라우저에 띄우려면 JS특성상 각 변수들의 스코프 문제, 네트워크 비용도 신경써야 한다.
때문에 이런 문제에를 해결하기 위해 하나의 시작점(Ex. React App의 index.js 등)으로부터 의존성을 가지는 모듈(자원)을 모두 추적하여 하나의 결과물을 만들어내는 모듈 번들러가 등장하게 되었다.
cf. Webpack4 버전 이상부터는 Develoment, Production 두 가지의 모드를 지원한다. Production 모드로 번들링을 진행할 경우, 코드 난독화, 압축, 최적화(Tree Shaking) 작업을 지원한다.
다음은 webpack.config.js 파일의 예시로, 이 코드 내의 속성을 확인하면 웹팩의 핵심 요소를 쉽게 알 수 있다.
module.exports = {
target: ["web", "es5"],
entry: "./src/script.js",
output: {
path: path.resolve(__dirname, "dist"),
filename: "app.bundle.js",
clean: true
},
module: {
rules: [
{
test: /\.css$/,
use: ["style-loader","css-loader"],
exclude: /node_modules/,
},
],
},
plugins: [
new HtmlWebpackPlugin({
template: path.resolve(__dirname, "src", "index.html"),
}),
new MiniCssExtractPlugin(),
],
optimization: {
minimizer: [
new CssMinimizerPlugin(),
]
}
};
웹팩 공식문서에 따르면 위에서 언급했던 요소들은 웹팩의 핵심 개념이다.
이 개념을 이해하면 웹팩의 작동 원리에 대해 좀 더 쉽게 이해할 수 있다.
Webpack이 번들링할 대상을 명시한다. target의 기본값은 web이며(없을 경우 기본값 적용), web 외에도 다양한 환경을 컴파일 할 수 있으며 아래와 같이 지정된 ECMAScript 버전으로 컴파일할 수 있다.
module.exports = {
target: ["web", "es5"],
};
webpack에서의 entry는 코드의 “시작점"이다. React의 index.js서 컴포넌트를 넣어 전체 코드가 시작되는 것을 생각하면 편하다.
Entry 속성은 Entry point라고도 하며, 웹팩이 내부의 디펜던시 그래프를 생성하기 위해 사용해야 하는 모듈입이다. 웹팩은 이 Entry point를 기반으로 직간접적으로 의존하는 다른 모듈과 라이브러리를 찾아낼 수 있다.
//기본 값
module.exports = {
...
entry: "./src/index.js", //index.js 대신 기본 시작점이 되는 코드를 입력
};
Output 속성은 생성된 번들을 내보낼 위치와 파일의 이름을 지정한다.
const path = require('path');
module.exports = {
...
output: {
path: path.resolve(__dirname, "dist"), // 절대 경로로 설정을 해야 합니다.
filename: "app.bundle.js",
clean: true
},
};
위 예제에서는 dist 폴더에서 app.bundle.js라는 파일에 번들링한다고 되어있다.
path는 절대 경로를 나타낼 때 쓸 수 있으며 사용할 때는 path 모듈을 사용하도록 한다.
Webpack은 기본적으로 JavaScript와 JSON 파일만 이해하지만, loader를 사용하면 다른 유형의 파일도 변환이 가능하다.
module.exports = {
...
module: {
rules: [
{
test: /\.css$/, //css로 끝나는 모든 파일
use: ["style-loader", "css-loader"],
exclude: /node_modules/,
},
],
},
};
loader에는 다음과 같은 속성이 있으며 module.rules안에 정의해야 한다.
여기서 test와 use는 필수 속성이다.
Plugins를 사용하면 번들을 최적화하거나 여러 작업(HTML 컴파일 및 생성, 에셋 관리, 환경변수 주입)이 가능하다.
플러그인을 사용하려면 해당 플러그인을 설치하고 requie()를 사용한다.
실제 사용시에는 new 키워드를 사용하여 인스턴스를 생성한다.
const webpack = require('webpack');
//모든 번들을 자동으로 삽입해 웹 앱용 HTML 파일 생성
const HtmlWebpackPlugin = require("html-webpack-plugin");
//CSS를 별도의 파일로 추출, CSS를 포함하는 JS파일 당 CSS파일을 작성
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
...
plugins: [
new HtmlWebpackPlugin({
template: path.resolve(__dirname, "src", "index.html"),
}),
new MiniCssExtractPlugin(),
],
};
Webpack은 버전 4부터 선택한 항목에 따라 최적화가 가능하다.
대표적인 옵션으로 minimize와 minimizer가 있다.
module.exports = {
...
optimization: {
minimizer: [
new CssMinimizerPlugin(), //mini-css-extract-plugin 에 관련된 번들을 최소화
]
}
};
리액트도 번들링이 필요하며, 필요한 라이브러리를 골라서 설치한 후 번들링할 수 있다.
리액트 개발에 꼭 필요한 라이브러리는 다음과 같다.
이외에 필수는 아니지만 리액트 개발에 도움이 되는 라이브러리는 다음과 같다.
1. webpack 공식문서
공식문서 링크: 🔗 https://webpack.kr/concepts/
2. 리액트에서 babel 설치하기
리액트 결과물을 webpack으로 번들링하기 위해 babel-loader가 필요했다.
아래는 직접 과제하면서 중요하다 싶은 점을 메모했다.
1) babel-loader 설치: preset-react를 꼭 설치해야 한다.
npm install -D @babel/core @babel/preset-env @babel/preset-react babel-loader
2) webpack.config.js 작성
아래처럼 작성하되, {runtime: 'automatic'} 이 항목이 들어가야 에러없이 잘 빌드된다.
runtime 옵션은 바벨의 옵션으로 기본값은 classic이며, automatic으로 설정하면 JSX가 변환하는 함수를 가져온다.
//...
module: {
rule:[
{
test: /\.(js|jsx)$/,
use:{
loader: "babel-loader",
options: {
presets: [
"@babel/preset-env",
["@babel/preset-react", {runtime:"automatic"}],
],
}
},
exclude: /node_modules/,
}
]
}
//...
3) 빌드하기
그 다음 npx webpack 명령어나 npm run build 명령어를 설정하여 빌드한다.
만약 깃헙 페이지로 배포할 예정이라면 output.path설정에서 폴더명을 'docs'로 해야 한다.