번들링(Bundling)
여러 제품이나 코드, 프로그램 등을 묶어서 패키지로 제공하는 행위.
프론트엔드에서 번들은 사용자에게 웹 애플리케이션을 제공하기 위한 파일 묶음을 말한다.
번들링을 하지 않았을 경우 발생할 수 있는 문제
- 여러개의 .js 파일에서 같은 변수 / 함수를 사용하고 있어서 변수 / 함수간 충돌 발생
- 파일 용량이 커서 인터넷 속도가 느릴경우 사용자의 불편함 유발
- 파일 용량을 줄이기 위해 공백을 모두 삭제했는데 가독성이 떨어짐
- 배포코드가 너무 읽기 쉬운 경우 사용자가 프론트엔드 애플리케이션을 임의로 조작하는 문제 발생
=> 파일의 용량을 줄이고 파일을 하나로 통일하는 툴링작업이 필요하다.
번들링을 했을 경우의 장점
- 여러개의 파일들을 하나로 묶어 제공함으로 사용자는 애플리케이션을 더 빨리 다운받을 수 있고 효율적으로 사용할 수 있다.
- 최적화와 압축을 동시에 할 수 있기 때문에 용량이 줄어들고 네트워크 리소스를 절약할 수 있다.
- 난독화가 가능함으로 배포코드의 가독성이 떨어지고 읽기 어려워짐으로 보안에도 도움이 된다.
웹팩(Webpack)
여러개의 파일을 하나로 합쳐주는 모듈 번들러. HTML, CSS, JavaScript 등의 자원을 각각 하나의 모듈로 인식하고 이를 조합해 하나의 묶음으로 번들링(빌드) 할 수 있다.
모듈 번들러(Module Bundler)
모던 웹으로 발전하면서 JavaScript 코드의 양이 절대적으로 증가하고, 대규모 의존성 트리를 가진 대형 웹 애플리케이션들이 등장하면서 세분화된 모듈 파일이 폭발적으로 증가했다. 이 모듈 단위의 파일들을 호출하여 브라우저에 띄울때 각 변수들의 스코프 문제를 해결해야했고, 호출할때 생겨나는 네트워크 코스트 또한 해결해야했다.
=> 하나의 시작점으로부터 의존성을 가지는 모듈을 모두 추적하여 하나의 결과물을 만들어내는 모듈 번들러 등장
🤔 웹팩에서 말하는 모듈이 뭔데?
JavaScript, HTML, CSS, .jpg, .png 등의 이미지까지도 전부 포함한 포괄적인 개념.
단 특정한 파일의 경우 특정한 플러그인이나 로더를 사용해야 번들링을 할 수 있다.
빌드(build) & 번들링(bundling)
빌드
개발이 완료된 앱을 배포하기 위해 하나의 폴더(directory)로 구성하여 준비하는 작업. 빌드 내에 번들링이 포함된다.
번들링
파일을 묶는 작업 자체. 더 정확하게는 모듈 간의 의존성 관계를 파악해 그룹화 하는 작업.
웹팩의 장점
- 같은 타입의 파일들을 묶어서 요청 및 응답을 받을 수 있음
=> 네트워크 코스트가 줄어듬. - 웹팩의 로더(loader)를 사용하면 일부 브라우저에서 지원하지 않는 문법들을 변환해주는 로더를 사용할 수 있다.
ex) babel-loader(JavaScript ES6을 ES5로 변환), vue-loader(Vue 문법 변환), scss-loader(scss를 css로 변환)...
=> 개발자가 원하는 최선의 방식을 선택해 개발할 수 있다. - Webpack4 버전 이상부터 지원되는 모드 - Development, Production
Production(배포모드)로 번들링할 경우 코드 난독화, 압축, 최적화(Tree Shaking)을 지원
=> 사용자의 환경 및 보안을 신경쓰면서도 코드를 노출시킬 수 있다.
=> 웹 애플리케이션의 빠른 속도와 높은 성능을 위해서는 웹팩이 필요하다.
웹팩의 핵심 개념
Target
웹팩은 다양한 환경과 target을 컴파일하고 특정 환경에 대한 런타임 코드를 생성하도록 한다.
browserslist 설정이 없다면 'browserlist' 혹은 기본값인 'web'으로 설정된다.
web 외에도 node 등 다양한 환경을 컴파일 할 수 있고, es_를 넣으면 지정된 ECMAScript 버전으로 컴파일 할 수 있다.
module.exports = {
target: ["web", "es5"],
// web : 브라우저와 동일한 환경에서 사용할것임
// es5 : 작성한 코드를 es5 버전으로 컴파일 할것임
};
Entry(엔트리)
개발자가 작성한 코드의 시작점. Entry point라고도 하고, 웹팩이 내부의 디펜던시 그래프를 생성하기 위해 사용해야 하는 모듈. 웹팩은 entry point를 기반으로 직간접적으로 의존하는 다른 모듈과 라이브러리를 찾아낼 수 있다.
기본값은 ./src/index.js 이지만 설정에서 다른 (또는 여러 엔트리 포인트)를 지정할 수 있다.
//기본 값
module.exports = {
...
entry: "./src/index.js",
};
//지정 값
module.exports = {
...
entry: "./src/script.js",
};
Output(출력)
생성된 번들을 내보낼 위치와 이 파일의 이름을 지정하는 방법을 웹팩에 알려주는 역할.
기본 출력파일의 경우 .dist/main.js로, 생성된 기타 파일의 경우 ./dist 폴더로 설정된다.
const path = require('path');
module.exports = {
...
output: {
path: path.resolve(__dirname, "docs"), // 절대 경로로 설정
filename: "app.bundle.js",
clean: true // 내보내기 전에 output 디렉터리(여기서는 docs)를 정리함
},
};
Node.js의 path 모듈을 가져와 파일 경로를 지정하는데 사용했다. 위의 예제를 보면 생성된 번들이 저장될 위치는 docs 폴더이고, 거기에 app.bundle.js 라는 이름으로 번들링된 파일이 저장될 것이다.
clean 옵션의 경우, 아래와 같이 사용할 수 있다.
내보내기 전에 디렉터리를 정리
module.exports = {
//...
output: {
clean: true, // 내보내기 전에 output 디렉터리를 정리합니다.
},
};
삭제하는 대신 제거해야 하는 애셋을 기록
module.exports = {
//...
output: {
clean: {
dry: true, // 삭제하는 대신 제거해야 하는 애셋을 기록합니다.
},
},
};
애셋을 특정한 경로 아래에 유지
module.exports = {
//...
output: {
clean: {
keep: /ignored\/dir\//, // 애셋을 'ignored/dir' 아래에 유지합니다.
},
},
};
// 또는
module.exports = {
//...
output: {
clean: {
keep(asset) {
return asset.includes('ignored/dir');
},
},
},
};
Loader(로더)
웹팩은 기본적으로 JavaScript와 JSON 파일만 이해한다. 그래서 다른 유형의 파일을 처리해야할때는 loader를 사용해야한다. 그래서 파일들을 유효한 모듈로 변환해 애플리케이션에 사용하거나 디펜던시 그래프에 추가할 수 있다.
module.rules 아래에 정의한다.
module.exports = {
...
module: {
rules: [
{
test: /\.css$/,
use: [MiniCssExtractPlugin.loader, "css-loader"],
exclude: /node_modules/,
},
],
},
};
- test : 변환이 필요한 파일들을 식별하기 위한 속성. 필수속성.
- use : 변환을 수행하는데 사용되는 로더를 가리키는 속성. 필수속성.
- exclude : 바벨로 컴파일하지 않을 파일이나 폴더를 지정
- include : 반드시 컴파일해야할 파일이나 폴더 지정
Plugins(플러그인)
번들을 최적화하거나 애셋을 관리하고 환경변수를 주입하는 등의 광범위한 작업을 수행할 수 있다.
const webpack = require('webpack');
const HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
...
plugins: [
new HtmlWebpackPlugin({
template: path.resolve(__dirname, "src", "index.html"),
}),
new MiniCssExtractPlugin(),
],
};
플러그인을 사용하는 방법
- require를 통해 플러그인 요청
- plugins 배열에 사용할 플러그인 추가
- 대부분의 플러그인은 사용자가 옵션을 지정할 수 있다.
- new 연산자를 호출해 플러그인의 인스턴스를 만들어 사용한다. 다른목적으로 플러그인을 여러번 사용할 수도 있기 때문.
Optimization(최적화)
Webpack4부터 선택한 항목에 대해 최적화를 실행할 수 있다.
module.exports = {
...
optimization: {
minimizer: [
new CssMinimizerPlugin(),
]
}
};
- minimize : TerserPlugin 또는 optimization.minimize에 명시된 plugins로 bundle 파일을 최소화(=압축)시키는 작업 여부를 결정
- minimizer : defualt minimizer을 커스텀된 TerserPlugin 인스턴스를 제공해서 재정의
웹팩과 리액트
리액트가 번들링이 필요한 이유
리액트는 프론트엔드 라이브러리로서 최소한의 기능을 제공하고자 가볍게 만들어졌지만, 시간이 지나면서 아이러니하게도 개발자의 다양한 니즈를 충족시키기 위해 더 많은 라이브러리를 필수적으로 사용해야만 했고, 개발자가 필요한 이런저런 라이브러리를 골라서 번들링 할 수 있는 웹팩이 필요하게 되었다.
리액트 개발에 꼭 필요한 라이브러리
react, react-dom
리액트 컴포넌트와 Hooks, 라이프 사이클에 대한 정보가 모두 들어있는 리액트와 리액트 코드를 브라우저에 보여줄 수 있는 react-dom은 가장 필수적이다.
babel
브라우저는 JavaScript는 읽을 수 있지만 JSX는 읽을 수 없다. 따라서 JSX를 JavaScript로 변경하여 번들링해주어야한다. 그래서 로더의 일종인 babel을 사용해야 한다.
css-loader
css를 번들링해주는 로더이다.
리액트 개발에 도움이 되는 라이브러리
react-hot-loader
webpack-dev-server처럼 저장할때마다 변경사항을 개발 환경에 적용해주는 라이브러리. 추가적인 특징으로는 리액트 상태를 유지시켜준다.
eslint
JavaScript로 개발 시 자주 접하는 에러를 방지하기 위한 린터
prettier
JavaScript로 개발 시 통일성 있게 코드 형식을 맞출 수 있게 도와주는 툴
'study > TIL' 카테고리의 다른 글
React Hooks(feat. useMemo, useCallback, Custom Hooks) (0) | 2023.03.22 |
---|---|
리액트의 동작 방식(feat. Virtual DOM, React Diffing Algorithm) (0) | 2023.03.22 |
23.03.15 - Tree, Graph (0) | 2023.03.15 |
23.03.14 - 자료구조, Stack, Queue (0) | 2023.03.14 |
23.03.13 - 기술면접 (0) | 2023.03.13 |