์นํฉ์ ํ์ฉํ ์๋ฐ์คํฌ๋ฆฝํธ ๋ฒ๋ค ์ต์ ํ๋ฅผ ๋ง์คํฐํ์ธ์. ๋ ๋น ๋ฅธ ๋ก๋ฉ ์๊ฐ๊ณผ ๊ธ๋ก๋ฒ ์น์ฌ์ดํธ ์ฑ๋ฅ ํฅ์์ ์ํ ์ค์ ๋ชจ๋ฒ ์ฌ๋ก๋ฅผ ์์๋ด ๋๋ค.
์๋ฐ์คํฌ๋ฆฝํธ ๋ฒ๋ค ์ต์ ํ: ์นํฉ(Webpack) ์ค์ ๋ชจ๋ฒ ์ฌ๋ก
์ค๋๋ ์ ์น ๊ฐ๋ฐ ํ๊ฒฝ์์ ์ฑ๋ฅ์ ๊ฐ์ฅ ์ค์ํฉ๋๋ค. ์ฌ์ฉ์๋ค์ ๋น ๋ฅด๊ฒ ๋ก๋ฉ๋๋ ์น์ฌ์ดํธ์ ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ธฐ๋ํฉ๋๋ค. ์ฑ๋ฅ์ ์ํฅ์ ๋ฏธ์น๋ ์ค์ํ ์์๋ ์๋ฐ์คํฌ๋ฆฝํธ ๋ฒ๋ค์ ํฌ๊ธฐ์ ํจ์จ์ฑ์ ๋๋ค. ๊ฐ๋ ฅํ ๋ชจ๋ ๋ฒ๋ค๋ฌ์ธ ์นํฉ(Webpack)์ ์ด๋ฌํ ๋ฒ๋ค์ ์ต์ ํํ๊ธฐ ์ํ ๋ค์ํ ๋๊ตฌ์ ๊ธฐ์ ์ ์ ๊ณตํฉ๋๋ค. ์ด ๊ฐ์ด๋์์๋ ์ต์ ์ ์๋ฐ์คํฌ๋ฆฝํธ ๋ฒ๋ค ํฌ๊ธฐ๋ฅผ ๋ฌ์ฑํ๊ณ ์ ์ธ๊ณ ์ฌ์ฉ์๋ฅผ ์ํ ์น์ฌ์ดํธ ์ฑ๋ฅ์ ๊ฐ์ ํ๊ธฐ ์ํ ์นํฉ ์ค์ ๋ชจ๋ฒ ์ฌ๋ก๋ฅผ ์์ธํ ๋ค๋ฃน๋๋ค.
๋ฒ๋ค ์ต์ ํ์ ์ค์์ฑ ์ดํดํ๊ธฐ
์ค์ ์ธ๋ถ ์ ๋ณด๋ฅผ ์ดํด๋ณด๊ธฐ ์ ์ ๋ฒ๋ค ์ต์ ํ๊ฐ ์ ๊ทธํ ๋ก ์ค์ํ์ง ์ดํดํ๋ ๊ฒ์ด ํ์์ ์ ๋๋ค. ํฐ ์๋ฐ์คํฌ๋ฆฝํธ ๋ฒ๋ค์ ๋ค์๊ณผ ๊ฐ์ ๋ฌธ์ ๋ฅผ ์ ๋ฐํ ์ ์์ต๋๋ค:
- ํ์ด์ง ๋ก๋ฉ ์๊ฐ ์ฆ๊ฐ: ๋ธ๋ผ์ฐ์ ๋ ๋์ฉ๋ ์๋ฐ์คํฌ๋ฆฝํธ ํ์ผ์ ๋ค์ด๋ก๋ํ๊ณ ํ์ฑํด์ผ ํ๋ฏ๋ก ์น์ฌ์ดํธ ๋ ๋๋ง์ด ์ง์ฐ๋ฉ๋๋ค. ์ด๋ ์ธํฐ๋ท ์ฐ๊ฒฐ์ด ๋๋ฆฐ ์ง์ญ์์ ํนํ ํฐ ์ํฅ์ ๋ฏธ์นฉ๋๋ค.
- ์ ํ๋ ์ฌ์ฉ์ ๊ฒฝํ: ๋๋ฆฐ ๋ก๋ฉ ์๊ฐ์ ์ฌ์ฉ์๋ฅผ ์ข์ ์ํค๊ณ , ์ดํ๋ฅ ์ ๋์ด๋ฉฐ ์ฐธ์ฌ๋๋ฅผ ๋ฎ์ถฅ๋๋ค.
- ๊ฒ์ ์์ง ์์ ํ๋ฝ: ๊ฒ์ ์์ง์ ํ์ด์ง ๋ก๋ฉ ์๋๋ฅผ ์์ ๊ฒฐ์ ์์ธ์ผ๋ก ๊ณ ๋ คํฉ๋๋ค.
- ๋์ ๋์ญํญ ๋น์ฉ: ํฐ ๋ฒ๋ค์ ์ ๊ณตํ๋ฉด ๋ ๋ง์ ๋์ญํญ์ ์๋นํ๊ฒ ๋์ด ๊ฐ๋ฐ์์ ์ฌ์ฉ์ ๋ชจ๋์๊ฒ ๋น์ฉ ์ฆ๊ฐ๋ฅผ ์ ๋ฐํ ์ ์์ต๋๋ค.
- ๋ฉ๋ชจ๋ฆฌ ์๋น ์ฆ๊ฐ: ํฐ ๋ฒ๋ค์ ํนํ ๋ชจ๋ฐ์ผ ๊ธฐ๊ธฐ์์ ๋ธ๋ผ์ฐ์ ๋ฉ๋ชจ๋ฆฌ์ ๋ถ๋ด์ ์ค ์ ์์ต๋๋ค.
๋ฐ๋ผ์ ์๋ฐ์คํฌ๋ฆฝํธ ๋ฒ๋ค์ ์ต์ ํํ๋ ๊ฒ์ ๋จ์ํ ์์ผ๋ฉด ์ข์ ๊ฒ์ด ์๋๋ผ, ๋ค์ํ ๋คํธ์ํฌ ์กฐ๊ฑด๊ณผ ๊ธฐ๊ธฐ ์ฑ๋ฅ์ ๊ฐ์ง ์ ์ธ๊ณ ์ฌ์ฉ์๋ฅผ ๋ง์กฑ์ํค๋ ๊ณ ์ฑ๋ฅ ์น์ฌ์ดํธ์ ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ตฌ์ถํ๊ธฐ ์ํ ํ์ ์์์ ๋๋ค. ์ฌ๊ธฐ์๋ ๋ฐ์ดํฐ ์ฌ์ฉ๋์ ์ ํ์ด ์๊ฑฐ๋ ์ฌ์ฉํ ๋งํผ ์๊ธ์ ์ง๋ถํ๋ ์ฌ์ฉ์๋ค์ ๋ฐฐ๋ คํ๋ ๊ฒ๋ ํฌํจ๋ฉ๋๋ค.
์ต์ ํ๋ฅผ ์ํ ์นํฉ ๊ธฐ์ด
์นํฉ์ ํ๋ก์ ํธ์ ์์กด์ฑ์ ํ์ํ๊ณ ์ด๋ฅผ ์ ์ ์์ฐ์ผ๋ก ๋ฒ๋ค๋งํ๋ ๋ฐฉ์์ผ๋ก ์๋ํฉ๋๋ค. ์ผ๋ฐ์ ์ผ๋ก webpack.config.js
๋ผ๋ ์ด๋ฆ์ ์ค์ ํ์ผ์ ์ด ํ๋ก์ธ์ค๊ฐ ์ด๋ป๊ฒ ์ํ๋์ด์ผ ํ๋์ง๋ฅผ ์ ์ํฉ๋๋ค. ์ต์ ํ์ ๊ด๋ จ๋ ์ฃผ์ ๊ฐ๋
์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค:
- ์ํธ๋ฆฌ ํฌ์ธํธ(Entry points): ์นํฉ์ ์์กด์ฑ ๊ทธ๋ํ์ ์์์ ์ ๋๋ค. ์ข ์ข ๋ฉ์ธ ์๋ฐ์คํฌ๋ฆฝํธ ํ์ผ์ด ๋ฉ๋๋ค.
- ๋ก๋(Loaders): CSS, ์ด๋ฏธ์ง ๋ฑ ์๋ฐ์คํฌ๋ฆฝํธ๊ฐ ์๋ ํ์ผ์ ๋ฒ๋ค์ ํฌํจ๋ ์ ์๋ ๋ชจ๋๋ก ๋ณํํฉ๋๋ค.
- ํ๋ฌ๊ทธ์ธ(Plugins): ์ต์ํ, ์ฝ๋ ๋ถํ , ์์ฐ ๊ด๋ฆฌ์ ๊ฐ์ ์์ ์ผ๋ก ์นํฉ์ ๊ธฐ๋ฅ์ ํ์ฅํฉ๋๋ค.
- ์์ํ(Output): ์นํฉ์ด ๋ฒ๋ค๋ ํ์ผ์ ์ด๋์ ์ด๋ป๊ฒ ์ถ๋ ฅํ ์ง ์ง์ ํฉ๋๋ค.
์ด๋ฌํ ํต์ฌ ๊ฐ๋ ์ ์ดํดํ๋ ๊ฒ์ ์๋์์ ์ค๋ช ํ ์ต์ ํ ๊ธฐ์ ์ ํจ๊ณผ์ ์ผ๋ก ๊ตฌํํ๋ ๋ฐ ํ์์ ์ ๋๋ค.
๋ฒ๋ค ์ต์ ํ๋ฅผ ์ํ ์นํฉ ์ค์ ๋ชจ๋ฒ ์ฌ๋ก
1. ์ฝ๋ ์คํ๋ฆฌํ (Code Splitting)
์ฝ๋ ์คํ๋ฆฌํ ์ ์ ํ๋ฆฌ์ผ์ด์ ์ฝ๋๋ฅผ ๋ ์๊ณ ๊ด๋ฆฌํ๊ธฐ ์ฌ์ด ์ฒญํฌ(chunk)๋ก ๋๋๋ ๋ฐฉ๋ฒ์ ๋๋ค. ์ด๋ฅผ ํตํด ์ฌ์ฉ์๋ ์ ์ฒด ๋ฒ๋ค์ ํ ๋ฒ์ ๋ค์ด๋ก๋ํ๋ ๋์ , ์ ํ๋ฆฌ์ผ์ด์ ์ ํน์ ๋ถ๋ถ์ ํ์ํ ์ฝ๋๋ง ๋ค์ด๋ก๋ํ ์ ์์ต๋๋ค. ์นํฉ์ ์ฝ๋ ์คํ๋ฆฌํ ์ ๊ตฌํํ๋ ์ฌ๋ฌ ๊ฐ์ง ๋ฐฉ๋ฒ์ ์ ๊ณตํฉ๋๋ค:
- ์ํธ๋ฆฌ ํฌ์ธํธ:
webpack.config.js
์ ์ฌ๋ฌ ์ํธ๋ฆฌ ํฌ์ธํธ๋ฅผ ์ ์ํฉ๋๋ค. ๊ฐ ์ํธ๋ฆฌ ํฌ์ธํธ๋ ๋ณ๋์ ๋ฒ๋ค์ ์์ฑํฉ๋๋ค.module.exports = { entry: { main: './src/index.js', vendor: './src/vendor.js' // ์: React, Angular, Vue์ ๊ฐ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ }, output: { filename: '[name].bundle.js', path: path.resolve(__dirname, 'dist') } };
์ด ์์ ๋ ์ ํ๋ฆฌ์ผ์ด์ ์ฝ๋๋ฅผ ์ํ
main.bundle.js
์ ์๋ํํฐ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ํvendor.bundle.js
๋ ๊ฐ์ ๋ฒ๋ค์ ์์ฑํฉ๋๋ค. ๋ฒค๋ ์ฝ๋๋ ์์ฃผ ๋ณ๊ฒฝ๋์ง ์์ผ๋ฏ๋ก ๋ธ๋ผ์ฐ์ ๊ฐ ๋ณ๋๋ก ์บ์ํ ์ ์์ด ์ ๋ฆฌํฉ๋๋ค. - ๋์ ์ํฌํธ(Dynamic imports):
import()
๊ตฌ๋ฌธ์ ์ฌ์ฉํ์ฌ ํ์ํ ๋ ๋ชจ๋์ ๋ก๋ํฉ๋๋ค. ์ด๋ ๋ผ์ฐํธ๋ ์ปดํฌ๋ํธ๋ฅผ ์ง์ฐ ๋ก๋ฉ(lazy-loading)ํ๋ ๋ฐ ํนํ ์ ์ฉํฉ๋๋ค.async function loadComponent() { const module = await import('./my-component'); const MyComponent = module.default; // ... MyComponent ๋ ๋๋ง }
- SplitChunksPlugin: ๊ณต์ ๋ชจ๋์ด๋ ์ต์ ์ฒญํฌ ํฌ๊ธฐ์ ๊ฐ์ ๋ค์ํ ๊ธฐ์ค์ ๋ฐ๋ผ ์ฝ๋๋ฅผ ์๋์ผ๋ก ๋ถํ ํ๋ ์นํฉ์ ๋ด์ฅ ํ๋ฌ๊ทธ์ธ์ ๋๋ค. ์ด๊ฒ์ด ๊ฐ์ฅ ์ ์ฐํ๊ณ ๊ฐ๋ ฅํ ์ต์ ์ธ ๊ฒฝ์ฐ๊ฐ ๋ง์ต๋๋ค.
SplitChunksPlugin ์ฌ์ฉ ์์:
module.exports = {
// ... ๊ธฐํ ์ค์
optimization: {
splitChunks: {
chunks: 'all',
cacheGroups: {
vendor: {
test: /[\\/]node_modules[\\/]/,
name: 'vendors',
chunks: 'all'
}
}
}
}
};
์ด ์ค์ ์ node_modules
๋๋ ํ ๋ฆฌ์ ์ฝ๋๋ฅผ ํฌํจํ๋ vendors
์ฒญํฌ๋ฅผ ์์ฑํฉ๋๋ค. `chunks: 'all'` ์ต์
์ ์ด๊ธฐ ์ฒญํฌ์ ๋น๋๊ธฐ ์ฒญํฌ ๋ชจ๋ ๊ณ ๋ ค๋๋๋ก ๋ณด์ฅํฉ๋๋ค. ์ฒญํฌ๊ฐ ์์ฑ๋๋ ๋ฐฉ์์ ๋ง์ถค ์ค์ ํ๋ ค๋ฉด `cacheGroups`๋ฅผ ์กฐ์ ํ์ธ์. ์๋ฅผ ๋ค์ด, ๋ค๋ฅธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ ์์ฃผ ์ฌ์ฉ๋๋ ์ ํธ๋ฆฌํฐ ํจ์๋ฅผ ์ํด ๋ณ๋์ ์ฒญํฌ๋ฅผ ์์ฑํ ์ ์์ต๋๋ค.
2. ํธ๋ฆฌ ์์ดํน(Tree Shaking)
ํธ๋ฆฌ ์์ดํน(๋๋ ๋ฐ๋ ์ฝ๋ ์ ๊ฑฐ)์ ์ฌ์ฉํ์ง ์๋ ์ฝ๋๋ฅผ ์๋ฐ์คํฌ๋ฆฝํธ ๋ฒ๋ค์์ ์ ๊ฑฐํ๋ ๊ธฐ์ ์
๋๋ค. ์ด๋ ๋ฒ๋ค ํฌ๊ธฐ๋ฅผ ํฌ๊ฒ ์ค์ด๊ณ ์ฑ๋ฅ์ ํฅ์์ํต๋๋ค. ์นํฉ์ ํธ๋ฆฌ ์์ดํน์ ํจ๊ณผ์ ์ผ๋ก ์ํํ๊ธฐ ์ํด ES ๋ชจ๋(import
๋ฐ export
๊ตฌ๋ฌธ)์ ์์กดํฉ๋๋ค. ํ๋ก์ ํธ ์ ์ฒด์์ ES ๋ชจ๋์ ์ฌ์ฉํ๋๋ก ํ์ธ์.
ํธ๋ฆฌ ์์ดํน ํ์ฑํํ๊ธฐ:
package.json
ํ์ผ์ "sideEffects": false
๊ฐ ์๋์ง ํ์ธํ์ธ์. ์ด๋ ์นํฉ์๊ฒ ํ๋ก์ ํธ์ ๋ชจ๋ ํ์ผ์ ์ฌ์ด๋ ์ดํํธ(side effect)๊ฐ ์๋ค๊ณ ์๋ ค์ฃผ์ด, ์ฌ์ฉ๋์ง ์๋ ์ฝ๋๋ฅผ ์์ ํ๊ฒ ์ ๊ฑฐํ ์ ์๊ฒ ํฉ๋๋ค. ๋ง์ฝ ํ๋ก์ ํธ์ ์ฌ์ด๋ ์ดํํธ๊ฐ ์๋ ํ์ผ(์: ์ ์ญ ๋ณ์ ์์ )์ด ํฌํจ๋์ด ์๋ค๋ฉด, ํด๋น ํ์ผ์ด๋ ํจํด์ sideEffects
๋ฐฐ์ด์ ๋์ดํ์ธ์. ์์๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค:
{
"name": "my-project",
"version": "1.0.0",
"sideEffects": ["./src/analytics.js", "./src/styles.css"]
}
ํ๋ก๋์ ๋ชจ๋์์ ์นํฉ์ ์๋์ผ๋ก ํธ๋ฆฌ ์์ดํน์ ์ํํฉ๋๋ค. ํธ๋ฆฌ ์์ดํน์ด ์๋ํ๋์ง ํ์ธํ๋ ค๋ฉด, ๋ฒ๋ค๋ ์ฝ๋๋ฅผ ๊ฒ์ฌํ์ฌ ์ ๊ฑฐ๋ ๋ฏธ์ฌ์ฉ ํจ์๋ ๋ณ์๊ฐ ์๋์ง ์ฐพ์๋ณด์ธ์.
์์ ์๋๋ฆฌ์ค: 10๊ฐ์ ํจ์๋ฅผ ๋ด๋ณด๋ด๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ์์ง๋ง ์ ํ๋ฆฌ์ผ์ด์ ์์๋ ๊ทธ์ค 2๊ฐ๋ง ์ฌ์ฉํ๋ค๊ณ ์์ํด ๋ณด์ธ์. ํธ๋ฆฌ ์์ดํน์ด ์์ผ๋ฉด 10๊ฐ์ ํจ์ ๋ชจ๋ ๋ฒ๋ค์ ํฌํจ๋ฉ๋๋ค. ํธ๋ฆฌ ์์ดํน์ ์ฌ์ฉํ๋ฉด ์ฌ์ฉํ๋ 2๊ฐ์ ํจ์๋ง ํฌํจ๋์ด ๋ฒ๋ค ํฌ๊ธฐ๊ฐ ์์์ง๋๋ค.
3. ์ต์ํ(Minification) ๋ฐ ์์ถ(Compression)
์ต์ํ๋ ์ฝ๋์์ ๋ถํ์ํ ๋ฌธ์(์: ๊ณต๋ฐฑ, ์ฃผ์)๋ฅผ ์ ๊ฑฐํ์ฌ ํฌ๊ธฐ๋ฅผ ์ค์ ๋๋ค. ์์ถ ์๊ณ ๋ฆฌ์ฆ(์: Gzip, Brotli)์ ๋คํธ์ํฌ๋ฅผ ํตํด ์ ์ก๋๋ ๋์ ๋ฒ๋ค๋ ํ์ผ์ ํฌ๊ธฐ๋ฅผ ๋์ฑ ์ค์ ๋๋ค.
TerserPlugin์ ์ด์ฉํ ์ต์ํ:
์นํฉ์ ๋ด์ฅ TerserPlugin
(๋๋ ๋ ๋น ๋ฅธ ๋น๋์ ์ต์ ๊ตฌ๋ฌธ ํธํ์ฑ์ ์ํ ESBuildPlugin
)์ ํ๋ก๋์
๋ชจ๋์์ ์๋ฐ์คํฌ๋ฆฝํธ ์ฝ๋๋ฅผ ์๋์ผ๋ก ์ต์ํํฉ๋๋ค. terserOptions
์ค์ ์ต์
์ ์ฌ์ฉํ์ฌ ๋์์ ์ฌ์ฉ์ ์ ์ํ ์ ์์ต๋๋ค.
const TerserPlugin = require('terser-webpack-plugin');
module.exports = {
// ... ๊ธฐํ ์ค์
optimization: {
minimize: true,
minimizer: [new TerserPlugin({
terserOptions: {
compress: {
drop_console: true, // console.log ๊ตฌ๋ฌธ ์ ๊ฑฐ
},
mangle: true,
},
})],
},
};
์ด ์ค์ ์ console.log
๊ตฌ๋ฌธ์ ์ ๊ฑฐํ๊ณ , ๋ณ์ ์ด๋ฆ์ ์งง๊ฒ ๋ง๋๋ ๋๋
ํ(mangling)๋ฅผ ํ์ฑํํ์ฌ ํฌ๊ธฐ๋ฅผ ๋์ฑ ์ค์
๋๋ค. ๊ณต๊ฒฉ์ ์ธ ์ต์ํ๋ ๋๋๋ก ์ฝ๋๋ฅผ ์์์ํฌ ์ ์์ผ๋ฏ๋ก ์ต์ํ ์ต์
์ ์ ์คํ๊ฒ ๊ณ ๋ คํ์ธ์.
Gzip ๋ฐ Brotli๋ฅผ ์ด์ฉํ ์์ถ:
compression-webpack-plugin
๊ณผ ๊ฐ์ ํ๋ฌ๊ทธ์ธ์ ์ฌ์ฉํ์ฌ ๋ฒ๋ค์ Gzip ๋๋ Brotli ์์ถ ๋ฒ์ ์ ๋ง๋์ธ์. ์ด ์์ถ ํ์ผ์ ์ง์ํ๋ ๋ธ๋ผ์ฐ์ ์ ์ ๊ณตํ์ธ์. ๋ธ๋ผ์ฐ์ ๊ฐ ๋ณด๋ธ Accept-Encoding
ํค๋๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ์์ถ ํ์ผ์ ์ ๊ณตํ๋๋ก ์น ์๋ฒ(์: Nginx, Apache)๋ฅผ ์ค์ ํ์ธ์.
const CompressionPlugin = require('compression-webpack-plugin');
module.exports = {
// ... ๊ธฐํ ์ค์
plugins: [
new CompressionPlugin({
algorithm: 'gzip',
test: /.js$|.css$/,
threshold: 10240,
minRatio: 0.8
})
]
};
์ด ์์ ๋ ์๋ฐ์คํฌ๋ฆฝํธ ๋ฐ CSS ํ์ผ์ Gzip ์์ถ ๋ฒ์ ์ ์์ฑํฉ๋๋ค. threshold
์ต์
์ ์์ถํ ์ต์ ํ์ผ ํฌ๊ธฐ(๋ฐ์ดํธ ๋จ์)๋ฅผ ์ง์ ํฉ๋๋ค. minRatio
์ต์
์ ํ์ผ์ด ์์ถ๋๊ธฐ ์ํด ํ์ํ ์ต์ ์์ถ ๋น์จ์ ์ค์ ํฉ๋๋ค.
4. ์ง์ฐ ๋ก๋ฉ(Lazy Loading)
์ง์ฐ ๋ก๋ฉ์ ๋ฆฌ์์ค(์: ์ด๋ฏธ์ง, ์ปดํฌ๋ํธ, ๋ชจ๋)๊ฐ ํ์ํ ๋๋ง ๋ก๋๋๋ ๊ธฐ์ ์ ๋๋ค. ์ด๋ ์ ํ๋ฆฌ์ผ์ด์ ์ ์ด๊ธฐ ๋ก๋ฉ ์๊ฐ์ ์ค์ฌ์ค๋๋ค. ์นํฉ์ ๋์ ์ํฌํธ๋ฅผ ์ฌ์ฉํ์ฌ ์ง์ฐ ๋ก๋ฉ์ ์ง์ํฉ๋๋ค.
์ปดํฌ๋ํธ ์ง์ฐ ๋ก๋ฉ ์์:
async function loadComponent() {
const module = await import('./MyComponent');
const MyComponent = module.default;
// ... MyComponent ๋ ๋๋ง
}
// ์ฌ์ฉ์๊ฐ ํ์ด์ง์ ์ํธ์์ฉํ ๋(์: ๋ฒํผ ํด๋ฆญ) loadComponent๋ฅผ ํธ๋ฆฌ๊ฑฐํฉ๋๋ค
์ด ์์ ๋ loadComponent
ํจ์๊ฐ ํธ์ถ๋ ๋๋ง MyComponent
๋ชจ๋์ ๋ก๋ํฉ๋๋ค. ์ด๋ ํนํ ์ฌ์ฉ์์๊ฒ ์ฆ์ ๋ณด์ด์ง ์๋ ๋ณต์กํ ์ปดํฌ๋ํธ์ ๊ฒฝ์ฐ ์ด๊ธฐ ๋ก๋ฉ ์๊ฐ์ ํฌ๊ฒ ํฅ์์ํฌ ์ ์์ต๋๋ค.
5. ์บ์ฑ(Caching)
์บ์ฑ์ ์ฌ์ฉํ๋ฉด ๋ธ๋ผ์ฐ์ ๊ฐ ์ด์ ์ ๋ค์ด๋ก๋ํ ๋ฆฌ์์ค๋ฅผ ๋ก์ปฌ์ ์ ์ฅํ์ฌ ํ์ ๋ฐฉ๋ฌธ ์ ๋ค์ ๋ค์ด๋ก๋ํ ํ์์ฑ์ ์ค์ผ ์ ์์ต๋๋ค. ์นํฉ์ ์บ์ฑ์ ํ์ฑํํ๋ ์ฌ๋ฌ ๊ฐ์ง ๋ฐฉ๋ฒ์ ์ ๊ณตํฉ๋๋ค:
- ํ์ผ๋ช
ํด์ฑ: ๋ฒ๋ค๋ ํ์ผ์ ์ด๋ฆ์ ํด์๋ฅผ ํฌํจ์ํต๋๋ค. ์ด๋ ๊ฒ ํ๋ฉด ํ์ผ ๋ด์ฉ์ด ๋ณ๊ฒฝ๋ ๋๋ง ๋ธ๋ผ์ฐ์ ๊ฐ ์ ๋ฒ์ ์ ํ์ผ์ ๋ค์ด๋ก๋ํ๋๋ก ๋ณด์ฅํ ์ ์์ต๋๋ค.
module.exports = { output: { filename: '[name].[contenthash].bundle.js', path: path.resolve(__dirname, 'dist') } };
์ด ์์ ๋ ํ์ผ๋ช ์
[contenthash]
ํ๋ ์ด์คํ๋๋ฅผ ์ฌ์ฉํฉ๋๋ค. ์นํฉ์ ๊ฐ ํ์ผ์ ๋ด์ฉ์ ๊ธฐ๋ฐ์ผ๋ก ๊ณ ์ ํ ํด์๋ฅผ ์์ฑํฉ๋๋ค. ๋ด์ฉ์ด ๋ณ๊ฒฝ๋๋ฉด ํด์๋ ๋ณ๊ฒฝ๋์ด ๋ธ๋ผ์ฐ์ ๊ฐ ์ ๋ฒ์ ์ ๋ค์ด๋ก๋ํ๋๋ก ๊ฐ์ ํฉ๋๋ค. - ์บ์ ๋ฒ์คํ
: ์น ์๋ฒ๊ฐ ๋ฒ๋ค๋ ํ์ผ์ ๋ํด ์ ์ ํ ์บ์ ํค๋๋ฅผ ์ค์ ํ๋๋ก ๊ตฌ์ฑํ์ธ์. ์ด๋ ๋ธ๋ผ์ฐ์ ์ ํ์ผ์ ์ผ๋ง ๋์ ์บ์ํ ์ง ์๋ ค์ค๋๋ค.
Cache-Control: max-age=31536000 // 1๋ ๋์ ์บ์
์ ์ ํ ์บ์ฑ์ ํนํ ์น์ฌ์ดํธ๋ฅผ ์์ฃผ ๋ฐฉ๋ฌธํ๋ ์ฌ์ฉ์์ ์ฑ๋ฅ์ ํฅ์์ํค๋ ๋ฐ ํ์์ ์ ๋๋ค.
6. ์ด๋ฏธ์ง ์ต์ ํ
์ด๋ฏธ์ง๋ ์ข ์ข ์น ํ์ด์ง์ ์ ์ฒด ํฌ๊ธฐ์ ์๋นํ ๋น์ค์ ์ฐจ์งํฉ๋๋ค. ์ด๋ฏธ์ง๋ฅผ ์ต์ ํํ๋ฉด ๋ก๋ฉ ์๊ฐ์ ํฌ๊ฒ ์ค์ผ ์ ์์ต๋๋ค.
- ์ด๋ฏธ์ง ์์ถ: ImageOptim, TinyPNG ๋๋
imagemin-webpack-plugin
๊ณผ ๊ฐ์ ๋๊ตฌ๋ฅผ ์ฌ์ฉํ์ฌ ํ์ง ์ ํ ์์ด ์ด๋ฏธ์ง๋ฅผ ์์ถํ์ธ์. - ๋ฐ์ํ ์ด๋ฏธ์ง: ์ฌ์ฉ์์ ๊ธฐ๊ธฐ์ ๋ฐ๋ผ ๋ค๋ฅธ ํฌ๊ธฐ์ ์ด๋ฏธ์ง๋ฅผ ์ ๊ณตํ์ธ์.
<picture>
์์๋<img>
์์์srcset
์์ฑ์ ์ฌ์ฉํ์ฌ ์ฌ๋ฌ ์ด๋ฏธ์ง ์์ค๋ฅผ ์ ๊ณตํ์ธ์.<img srcset="image-small.jpg 320w, image-medium.jpg 768w, image-large.jpg 1200w" src="image-default.jpg" alt="My Image">
- ์ด๋ฏธ์ง ์ง์ฐ ๋ก๋ฉ: ๋ทฐํฌํธ์ ๋ณด์ผ ๋๋ง ์ด๋ฏธ์ง๋ฅผ ๋ก๋ํ์ธ์.
<img>
์์์loading="lazy"
์์ฑ์ ์ฌ์ฉํ์ธ์.<img src="my-image.jpg" alt="My Image" loading="lazy">
- WebP ํ์: ์ผ๋ฐ์ ์ผ๋ก JPEG๋ PNG ์ด๋ฏธ์ง๋ณด๋ค ์์ WebP ์ด๋ฏธ์ง๋ฅผ ์ฌ์ฉํ์ธ์. WebP๋ฅผ ์ง์ํ์ง ์๋ ๋ธ๋ผ์ฐ์ ๋ฅผ ์ํด ๋์ฒด ์ด๋ฏธ์ง๋ฅผ ์ ๊ณตํ์ธ์.
7. ๋ฒ๋ค ๋ถ์ํ๊ธฐ
๊ฐ์ ํ ๋ถ๋ถ์ ์ฐพ๊ธฐ ์ํด ๋ฒ๋ค์ ๋ถ์ํ๋ ๊ฒ์ด ์ค์ํฉ๋๋ค. ์นํฉ์ ๋ฒ๋ค ๋ถ์์ ์ํ ์ฌ๋ฌ ๋๊ตฌ๋ฅผ ์ ๊ณตํฉ๋๋ค:
- Webpack Bundle Analyzer: ๋ฒ๋ค์ ํฌ๊ธฐ์ ๊ตฌ์ฑ์ ๋ณด์ฌ์ฃผ๋ ์๊ฐ์ ๋๊ตฌ์
๋๋ค. ์ด๋ฅผ ํตํด ์ต์ ํํ ์ ์๋ ํฐ ๋ชจ๋๊ณผ ์์กด์ฑ์ ์๋ณํ ์ ์์ต๋๋ค.
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin; module.exports = { // ... ๊ธฐํ ์ค์ plugins: [ new BundleAnalyzerPlugin() ] };
- Webpack Stats: ๋ฒ๋ค์ ๋ํ ์์ธ ์ ๋ณด๊ฐ ํฌํจ๋ JSON ํ์ผ์ ์์ฑํฉ๋๋ค. ์ด ํ์ผ์ ๋ค๋ฅธ ๋ถ์ ๋๊ตฌ์ ํจ๊ป ์ฌ์ฉํ ์ ์์ต๋๋ค.
์ต์ ํ ๋ ธ๋ ฅ์ด ํจ๊ณผ์ ์ธ์ง ํ์ธํ๊ธฐ ์ํด ์ ๊ธฐ์ ์ผ๋ก ๋ฒ๋ค์ ๋ถ์ํ์ธ์.
8. ํ๊ฒฝ๋ณ ์ค์
๊ฐ๋ฐ ํ๊ฒฝ๊ณผ ํ๋ก๋์ ํ๊ฒฝ์ ๋ํด ๋ค๋ฅธ ์นํฉ ์ค์ ์ ์ฌ์ฉํ์ธ์. ๊ฐ๋ฐ ์ค์ ์ ๋น ๋ฅธ ๋น๋ ์๊ฐ๊ณผ ๋๋ฒ๊น ๊ธฐ๋ฅ์ ์ค์ ์ ๋์ด์ผ ํ๋ฉฐ, ํ๋ก๋์ ์ค์ ์ ๋ฒ๋ค ํฌ๊ธฐ์ ์ฑ๋ฅ์ ์ฐ์ ์ํด์ผ ํฉ๋๋ค.
ํ๊ฒฝ๋ณ ์ค์ ์์:
const path = require('path');
const TerserPlugin = require('terser-webpack-plugin');
module.exports = (env, argv) => {
const isProduction = argv.mode === 'production';
return {
mode: isProduction ? 'production' : 'development',
devtool: isProduction ? false : 'source-map',
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist')
},
optimization: {
minimize: isProduction,
minimizer: isProduction ? [new TerserPlugin()] : [],
},
};
};
์ด ์ค์ ์ ํ๊ฒฝ์ ๋ฐ๋ผ mode
์ devtool
์ต์
์ ์ค์ ํฉ๋๋ค. ํ๋ก๋์
๋ชจ๋์์๋ TerserPlugin
์ ์ฌ์ฉํ์ฌ ์ต์ํ๋ฅผ ํ์ฑํํฉ๋๋ค. ๊ฐ๋ฐ ๋ชจ๋์์๋ ๋ ์ฌ์ด ๋๋ฒ๊น
์ ์ํด ์์ค ๋งต์ ์์ฑํฉ๋๋ค.
9. ๋ชจ๋ ํ๋๋ ์ด์ (Module Federation)
๋ ํฌ๊ณ ๋ง์ดํฌ๋ก ํ๋ก ํธ์๋ ๊ธฐ๋ฐ ์ ํ๋ฆฌ์ผ์ด์ ์ํคํ ์ฒ์ ๊ฒฝ์ฐ ๋ชจ๋ ํ๋๋ ์ด์ (์นํฉ 5๋ถํฐ ์ฌ์ฉ ๊ฐ๋ฅ) ์ฌ์ฉ์ ๊ณ ๋ คํ์ธ์. ์ด๋ฅผ ํตํด ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ค๋ฅธ ๋ถ๋ถ์ด๋ ์ฌ์ง์ด ๋ค๋ฅธ ์ ํ๋ฆฌ์ผ์ด์ ์ด ๋ฐํ์์ ์ฝ๋์ ์์กด์ฑ์ ๊ณต์ ํ ์ ์์ด ๋ฒ๋ค ์ค๋ณต์ ์ค์ด๊ณ ์ ๋ฐ์ ์ธ ์ฑ๋ฅ์ ํฅ์์ํฌ ์ ์์ต๋๋ค. ์ด๋ ํนํ ๋๊ท๋ชจ์ ๋ถ์ฐ๋ ํ์ด๋ ์ฌ๋ฌ ๋ ๋ฆฝ์ ์ธ ๋ฐฐํฌ๊ฐ ์๋ ํ๋ก์ ํธ์ ์ ์ฉํฉ๋๋ค.
๋ง์ดํฌ๋ก ํ๋ก ํธ์๋ ์ ํ๋ฆฌ์ผ์ด์ ์ ์ํ ์ค์ ์์:
// ๋ง์ดํฌ๋ก ํ๋ก ํธ์๋ A
module.exports = {
//...
plugins: [
new ModuleFederationPlugin({
name: 'MicrofrontendA',
exposes: {
'./ComponentA': './src/ComponentA',
},
shared: ['react', 'react-dom'], // ํธ์คํธ ๋ฐ ๋ค๋ฅธ ๋ง์ดํฌ๋ก ํ๋ก ํธ์๋์ ๊ณต์ ๋๋ ์์กด์ฑ
}),
],
};
// ํธ์คํธ ์ ํ๋ฆฌ์ผ์ด์
module.exports = {
//...
plugins: [
new ModuleFederationPlugin({
name: 'Host',
remotes: {
'MicrofrontendA': 'MicrofrontendA@http://localhost:3001/remoteEntry.js', // ์๊ฒฉ ์ํธ๋ฆฌ ํ์ผ์ ์์น
},
shared: ['react', 'react-dom'],
}),
],
};
10. ๊ตญ์ ํ(Internationalization) ๊ณ ๋ ค์ฌํญ
๊ธ๋ก๋ฒ ์ฌ์ฉ์๋ฅผ ์ํ ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ตฌ์ถํ ๋, ๊ตญ์ ํ(i18n)๊ฐ ๋ฒ๋ค ํฌ๊ธฐ์ ๋ฏธ์น๋ ์ํฅ์ ๊ณ ๋ คํด์ผ ํฉ๋๋ค. ํฐ ์ธ์ด ํ์ผ์ด๋ ์ฌ๋ฌ ๋ก์ผ์ผ๋ณ ๋ฒ๋ค์ ๋ก๋ฉ ์๊ฐ์ ํฌ๊ฒ ์ฆ๊ฐ์ํฌ ์ ์์ต๋๋ค. ๋ค์๊ณผ ๊ฐ์ ๋ฐฉ๋ฒ์ผ๋ก ์ด๋ฌํ ๊ณ ๋ ค์ฌํญ์ ํด๊ฒฐํ์ธ์:
- ๋ก์ผ์ผ๋ณ ์ฝ๋ ์คํ๋ฆฌํ : ๊ฐ ์ธ์ด์ ๋ํด ๋ณ๋์ ๋ฒ๋ค์ ์์ฑํ์ฌ ์ฌ์ฉ์์ ๋ก์ผ์ผ์ ํ์ํ ์ธ์ด ํ์ผ๋ง ๋ก๋ํฉ๋๋ค.
- ๋ฒ์ญ์ ์ํ ๋์ ์ํฌํธ: ๋ชจ๋ ๋ฒ์ญ์ ์ด๊ธฐ ๋ฒ๋ค์ ํฌํจํ๋ ๋์ ํ์์ ๋ฐ๋ผ ๋ฒ์ญ ํ์ผ์ ๋ก๋ํฉ๋๋ค.
- ๊ฒฝ๋ i18n ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ฌ์ฉ: ํฌ๊ธฐ์ ์ฑ๋ฅ์ ์ต์ ํ๋ i18n ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ ํํ์ธ์.
๋ฒ์ญ ํ์ผ์ ๋์ ์ผ๋ก ๋ก๋ํ๋ ์์:
async function loadTranslations(locale) {
const module = await import(`./translations/${locale}.json`);
return module.default;
}
// ์ฌ์ฉ์ ๋ก์ผ์ผ์ ๋ฐ๋ผ ๋ฒ์ญ ๋ก๋
loadTranslations(userLocale).then(translations => {
// ... ๋ฒ์ญ ์ฌ์ฉ
});
๊ธ๋ก๋ฒ ๊ด์ ๊ณผ ํ์งํ
๊ธ๋ก๋ฒ ์ ํ๋ฆฌ์ผ์ด์ ์ ์ํด ์นํฉ ์ค์ ์ ์ต์ ํํ ๋ ๋ค์ ์ฌํญ์ ๊ณ ๋ คํ๋ ๊ฒ์ด ์ค์ํฉ๋๋ค:
- ๋ค์ํ ๋คํธ์ํฌ ์กฐ๊ฑด: ํนํ ๊ฐ๋ฐ๋์๊ตญ์ ๋๋ฆฐ ์ธํฐ๋ท ์ฐ๊ฒฐ์ ๊ฐ์ง ์ฌ์ฉ์๋ฅผ ์ํด ์ต์ ํํ์ธ์.
- ๊ธฐ๊ธฐ ๋ค์์ฑ: ์ ์ฌ์ ํด๋ํฐ์ ํฌํจํ ๋ค์ํ ๊ธฐ๊ธฐ์์ ์ ํ๋ฆฌ์ผ์ด์ ์ด ์ ์๋ํ๋์ง ํ์ธํ์ธ์.
- ํ์งํ(Localization): ๋ค๋ฅธ ์ธ์ด์ ๋ฌธํ์ ๋ง๊ฒ ์ ํ๋ฆฌ์ผ์ด์ ์ ์กฐ์ ํ์ธ์.
- ์ ๊ทผ์ฑ: ์ฅ์ ๊ฐ ์๋ ์ฌ์ฉ์๋ ์ ํ๋ฆฌ์ผ์ด์ ์ ์ ๊ทผํ ์ ์๋๋ก ๋ง๋์ธ์.
๊ฒฐ๋ก
์๋ฐ์คํฌ๋ฆฝํธ ๋ฒ๋ค ์ต์ ํ๋ ์ ์คํ ๊ณํ, ์ค์ ๋ฐ ๋ถ์์ด ํ์ํ ์ง์์ ์ธ ํ๋ก์ธ์ค์ ๋๋ค. ์ด ๊ฐ์ด๋์ ์ค๋ช ๋ ๋ชจ๋ฒ ์ฌ๋ก๋ฅผ ๊ตฌํํจ์ผ๋ก์จ ๋ฒ๋ค ํฌ๊ธฐ๋ฅผ ํฌ๊ฒ ์ค์ด๊ณ ์น์ฌ์ดํธ ์ฑ๋ฅ์ ๊ฐ์ ํ๋ฉฐ ์ ์ธ๊ณ ์ฌ์ฉ์์๊ฒ ๋ ๋์ ์ฌ์ฉ์ ๊ฒฝํ์ ์ ๊ณตํ ์ ์์ต๋๋ค. ์ ๊ธฐ์ ์ผ๋ก ๋ฒ๋ค์ ๋ถ์ํ๊ณ , ๋ณํํ๋ ํ๋ก์ ํธ ์๊ตฌ์ฌํญ์ ๋ง๊ฒ ์ค์ ์ ์กฐ์ ํ๋ฉฐ, ์ต์ ์นํฉ ๊ธฐ๋ฅ๊ณผ ๊ธฐ์ ์ ๋ํ ์ ๋ณด๋ฅผ ๊ณ์ ์ ๋ฐ์ดํธํ๋ ๊ฒ์ ์์ง ๋ง์ธ์. ํจ๊ณผ์ ์ธ ๋ฒ๋ค ์ต์ ํ๋ฅผ ํตํด ๋ฌ์ฑ๋ ์ฑ๋ฅ ํฅ์์ ์ฌ์ฉ์์ ์์น๋ ๊ธฐ๊ธฐ์ ๊ด๊ณ์์ด ๋ชจ๋ ์ฌ์ฉ์์๊ฒ ํํ์ ์ค ๊ฒ์ ๋๋ค.
์ด๋ฌํ ์ ๋ต์ ์ฑํํ๊ณ ์ง์์ ์ผ๋ก ๋ฒ๋ค ํฌ๊ธฐ๋ฅผ ๋ชจ๋ํฐ๋งํจ์ผ๋ก์จ ์น ์ ํ๋ฆฌ์ผ์ด์ ์ ์ฑ๋ฅ์ ์ ์งํ๊ณ ์ ์ธ๊ณ ์ฌ์ฉ์์๊ฒ ํ๋ฅญํ ์ฌ์ฉ์ ๊ฒฝํ์ ์ ๊ณตํ ์ ์์ต๋๋ค. ํน์ ํ๋ก์ ํธ์ ๊ฐ์ฅ ์ ํฉํ ์ค์ ์ ์ฐพ๊ธฐ ์ํด ์นํฉ ์ค์ ์ ์คํํ๊ณ ๋ฐ๋ณตํ๋ ๊ฒ์ ๋๋ ค์ํ์ง ๋ง์ธ์.