ํ๋ก ํธ์๋ ์ฑ๋ฅ ๋ฒ ์ด์ค์บ ํ
๋ ์ฐ์ํํ
ํฌ์ฝ์ค ๋ ๋ฒจ 4 ์น ์ฑ๋ฅ ๋ฏธ์
์ ๋ฐํ์ผ๋ก ๋ง์ฃผํ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ ๊ณผ์ ์ ๋ค๋ฃฌ๋ค. ๊ทธ์ค ์ฒซ ๋ฒ์งธ๋ ์์ฒญ ํฌ๊ธฐ ์ค์ด๊ธฐ
์ด๋ค.
์์ฒญ ํฌ๊ธฐ๋ผ๊ณ ํ๋ฉด ๋ค์๊ณผ ๊ฐ์ ๊ฒ๋ค์ ์๊ฐํ ์ ์๋ค.
- ์์ค์ฝ๋
- ์ด๋ฏธ์ง์ ๊ฐ์ assets ํ์ผ
- ํฐํธ
์ด ์ค ์์ค์ฝ๋
์ ์ด๋ฏธ์ง์ ๊ฐ์ assets ํ์ผ
์ ํฌ๊ธฐ๋ฅผ ์ค์ฌ๋ณด๋๋ก ํ๋ค.
์ฑ๋ฅ ํ ์คํธ์ ์ฌ์ฉ๋๊ณ ๊ฐ์ ๋๋ ์ฝ๋๋ ์ฌ๊ธฐ์์ ํ์ธํ ์ ์๋ค. ๋ํ ํด๋น ์๋ฆฌ์ฆ์์๋ ํน๋ณํ ์ธ๊ธ์ ํ์ง ์๋ ์ด์ ์ฑ๋ฅ ์ธก์ ํ๊ฒฝ์ dev ํ๊ฒฝ์ด๋ค.
1. ์์ค์ฝ๋ ํฌ๊ธฐ ์ค์ด๊ธฐ
1-1. ๊ธฐ์กด ์์ค์ฝ๋ ํฌ๊ธฐ
์๋น์ค๋ฅผ ์คํํ๊ฒ ๋๋ฉด bundle.js
๊ฐ ๋ถ๋ฌ์์ง๋ค. bundle.js
ํฌ๊ธฐ๋ฅผ ๋น๊ตํ๊ธฐ ์ package.json
์ scripts๋ฅผ ๋ค์๊ณผ ๊ฐ์ด ์์ ํ์.
{
"scripts": {
// ...
"serve:dev": "webpack serve --mode=development", // ์์ ํ ์คํฌ๋ฆฝํธ, `dev` ํ๊ฒฝ
"serve:prod": "webpack serve --mode=production", // ์ถ๊ฐํ ์คํฌ๋ฆฝํธ, `prod` ํ๊ฒฝ
// ...
"deploy": "npm run build:prod && npx gh-pages -d dist" // ๊ธฐ์กด ์คํฌ๋ฆฝํธ, `github-pages` ๋ฐฐํฌ ํ๊ฒฝ
}
}
์ฌ๋ฌ ํ๊ฒฝ์์์ bundle.js
์ ํฌ๊ธฐ๋ฅผ ํ์ธํ๋ฉด ๋ค์๊ณผ ๊ฐ๋ค.
1. dev ํ๊ฒฝ์์์ bundle.js
ํฌ๊ธฐ - 2.8MB
2. prod ํ๊ฒฝ์์์ bundle.js ํฌ๊ธฐ - 1.6MB
3. github-pages ํ๊ฒฝ์์์ bundle.js ํฌ๊ธฐ - 284kB
๊ฐ๊ฐ์ ํ๊ฒฝ์ ์ bundle.js
ํฌ๊ธฐ์ ์ฐจ์ด๊ฐ ์์๊น? ๊ทธ ์ด์ ๋ webpack์ v4 ์ด์๋ถํฐ๋ ๊ฐ๊ฐ์ ํ๊ฒฝ(dev, prod)์ ๋ฐ๋ผ ์ต์ ํ๊ฐ ์งํ๋๋ค. ์ฆ, prod
ํ๊ฒฝ์ผ๋ก ๋น๋๋ฅผ ํ๊ฒ ๋๋ฉด ๋ณ๋ค๋ฅธ webpack ์ค์ ์์ด ์๋์ผ๋ก ์ต์ ํ๊ฐ ์งํ๋๋ค.
๋ค์์ ์นํฉ๋ฌธ์์์ ์ค๋ช
ํ๊ณ ์๋ mode ์ต์
(dev, prod, none)์ ๋ํ ์ค๋ช
์ด๋ค.
์ต์ | ์ค๋ช |
development | DefinePlugin์ process.env.NODE_ENV๋ฅผ development๋ก ์ค์ ํฉ๋๋ค. ๋ชจ๋๊ณผ ์ฒญํฌ์ ์ ์ฉํ ์ด๋ฆ์ ์ฌ์ฉํ ์ ์์ต๋๋ค. |
production | DefinePlugin์ process.env.NODE_ENV๋ฅผ production์ผ๋ก ์ค์ ํฉ๋๋ค. ๋ชจ๋๊ณผ ์ฒญํฌ, FlagDependencyUsagePlugin, FlagIncludedChunksPlugin, ModuleConcatenationPlugin, NoEmitOnErrorsPlugin, TerserPlugin ๋ฑ์ ๋ํด ๊ฒฐ์ ์ ๋ง๊ธ์ด๋ฆ(mangled name)์ ์ฌ์ฉํ ์ ์์ต๋๋ค. |
none | ๊ธฐ๋ณธ ์ต์ ํ ์ต์ ์์ ์ ์ธ |
๊ทธ๋ฆฌ๊ณ github-pages
์ ๋ฐฐํฌ๋ฅผ ํ๊ฒ ๋๋ค๋ฉด bundle.js
์ gzip
ํํ๋ก ์ธ์ฝ๋ฉ๋์ด ๋ถ๋ฌ์์ง๊ธฐ ๋๋ฌธ์ ์์ค ํฌ๊ธฐ๋ ๋์ฑ ์์์ง๊ฒ ๋๋ค.
1-2. optimization.minimize ์ ์ฉํ๊ธฐ
optimization
์ minimize
์์ฑ์ TerserPlugin
๋๋ optimization.minimizer
์ ์ง์ ๋ ํ๋ก๊ทธ์ธ์ ์ฌ์ฉํ์ฌ ๋ฒ๋ค์ ์ต์ํํ๋ค.
webpack์ optimization
์ค์ ์ ๋ณด๋ฉด ๋ค์๊ณผ ๊ฐ๋ค.
module.exports = {
// ...
optimization: {
minimize: false,
},
};
minimize
์์ฑ์ true
๋ก ์์ ํ ํ ๋ค์ ๋น๋๋ฅผ ํด๋ณด์.
module.exports = {
// ...
optimization: {
minimize: true,
},
};
๊ฒฐ๊ณผ๋ ๋ค์๊ณผ ๊ฐ๋ค.
- dev ํ๊ฒฝ: 2.8MB -> 1.3MB
- prod ํ๊ฒฝ: 1.6MB -> 446kB
๋ณ๋ค๋ฅธ ์ค์ ์ ํ์ง ์์๋ bundle.js
ํฌ๊ธฐ๊ฐ ํฌ๊ฒ ์ค์ด๋ ๊ฒ์ ํ์ธํ ์ ์๋ค. ์ฆ, ๋จ์ํ minimize
์์ฑ์ true
๋ง ํด์ฃผ์ด๋ ๊ธฐ๋ณธ์ ์ธ ์ต์ ํ๊ฐ ์ผ์ด๋๋ค.
์ฌ๊ธฐ์ ์๋ฌธ์ ์ด ๋ค์๋ค. ์์ optimization
์ค์ ์ ์ง์ฐ๊ฒ ๋๋ค๋ฉด ์ด๋ป๊ฒ ๋ ๊น? ๊ฒฐ๊ณผ๋ ๋ค์๊ณผ ๊ฐ๋ค.
- dev ํ๊ฒฝ: 2.8MB
- prod ํ๊ฒฝ: 446kB
์ฌ๊ธฐ๊น์ง์ ๋ด์ฉ์ ์ ๋ฆฌํ์๋ฉด prod
ํ๊ฒฝ์์๋ optimization
์ค์ ์ ๊ตณ์ด ํ์ง ์์๋ ๊ธฐ๋ณธ์ ์ธ ์ต์ ํ๊ฐ ์ด๋ฃจ์ด์ง๊ณ dev
ํ๊ฒฝ์์๋ optimization
์ minimize
์์ฑ์ true
๋ก ํด์ฃผ์ด์ผ ์ต์ ํ๊ฐ ์ด๋ฃจ์ด์ง๋ค. ์ฆ, optimization
์ค์ ์ ํตํด ์ถ๊ฐ ์ต์ ํ๋ฅผ ์ค์ ํ์ง ์๋๋ค๋ฉด optimization
์ค์ ์ ํ์ง ์์๋ ๋๋ค.(dev
ํ๊ฒฝ์์์ ์ต์ ํ๋ ๊ตณ์ด ํ์ ์์ผ๋๊น)
1-3. CSS ์ต์ ํ์ optimization.minimizer์ ๊ธฐ๋ณธ๊ฐ ์ ์ง
๋ง์ฝ CssMinimizerPlugin
์ ์ฌ์ฉํ์ฌ css๋ฅผ ์ต์ ํ๋ฅผ ์ถ๊ฐ ์งํํ๋ค๋ฉด optimization
์ minimizer
์์ฑ์ ๋ค์๊ณผ ๊ฐ์ด ํ ์ ์์ ๊ฒ์ด๋ค.
module.exports = {
// ...
optimization: {
minimize: true, // ์ ๊ฑฐ ๊ฐ๋ฅ. ๋จ, false๋ก ํ ๊ฒฝ์ฐ ์ต์ ํ๋ ์งํ๋์ง ์์.
minimizer: [new CssMinimizerPlugin()],
},
};
์์ ๊ฐ์ ๊ฒฝ์ฐ๋ minimizer
์ ์ฌ์ฉํ๋ฏ๋ก minimize
๊ฐ true
๊ฐ ๋๋ค. ์ฆ minimize
์์ฑ์ ์ ๊ฑฐํด๋๋๋ค. ๋จ, ์์์๋ ์ค๋ช
ํ๋ฏ์ด dev
ํ๊ฒฝ์๋ ๋ค๋ฅด๊ฒ ์ ์ฉ๋๋ค. minimize
๊ฐ true
์ด์ด์ผ๋ง ์ต์ ํ๊ฐ ์ด๋ฃจ์ด์ง๋ค.
์ด์จ๋ ์ ์ค์ ์ ๋ฐ๋ฅธ ๊ฒฐ๊ณผ๋ ์ด๋จ๊น? ๋ค์๊ณผ ๊ฐ๋ค.
- dev ํ๊ฒฝ: 2.8MB
- prod ํ๊ฒฝ: 1.6MB
๋ค์ bundle.js
์ ํฌ๊ธฐ๊ฐ ์ด์ ์ผ๋ก ๋์๊ฐ ์ด์ ๋ ๋ฌด์์ผ๊น? ์ด๋ minimizer
์์ฑ์์ ๊ธฐ๋ณธ ๊ฐ์ ์ ๊ฑฐํ๊ธฐ ๋๋ฌธ์ด๋ค. ๋ง์ฝ ์ถ๊ฐ์ ์ธ ์ต์ ํ๋ฅผ ํ๊ธฐ ์ํด ํ๋ฌ๊ทธ์ธ์ ์ฌ์ฉํ๋ค๋ฉด ๊ธฐ๋ณธ ๊ฐ์ ์ ์งํ๋ ๊ตฌ๋ฌธ์ด ํ์ํ๋ค. ๋ค์์ minimizer
์์ฑ์ ๊ธฐ๋ณธ ๊ฐ์ ์ ์งํ๋ ์ฝ๋์ minimizer
์์ฑ์ ๊ธฐ๋ณธ ๊ฐ์ด๋ค.
// `minimizer` ์์ฑ์ ๊ธฐ๋ณธ ๊ฐ
[
{
apply: (compiler) => {
// Lazy load the Terser plugin
const TerserPlugin = require("terser-webpack-plugin");
new TerserPlugin({
terserOptions: {
compress: {
passes: 2,
},
},
}).apply(compiler);
},
},
];
// `minimizer` ์์ฑ์ ๊ธฐ๋ณธ ๊ฐ์ ์ ์งํ๊ธฐ ์ํ ์ฝ๋
module.exports = {
// ...
optimization: {
minimize: true,
minimizer: ["...", new CssMinimizerPlugin()],
},
};
'...'
์ ์ถ๊ฐํด์ผ ๊ธฐ๋ณธ ๊ฐ์ ์ ์งํ๋ค.
๊ฒฐ๊ณผ๋ ๋ค์๊ณผ ๊ฐ๋ค.
- dev ํ๊ฒฝ: 1.3MB
- prod ํ๊ฒฝ: 446kB
1-4. ๊ฒฐ๋ก ๋ฐ ์ต์ข ๊ฒฐ๊ณผ
ํ์ฌ CssMinimizerPlugin
์ ์ฌ์ฉํ์ฌ css ์ต์ ํ๋ฅผ ์งํ์ ํด๋ ๋ณํ๊ฐ ์๊ธฐ ๋๋ฌธ์ ์ค์ ํ์ง ์์๋ค. ๋ํ optimization
์ค์ ์ ์ถ๊ฐํ์ง ์์๋ ์ถฉ๋ถํ bundle.js
์ ํฌ๊ธฐ๊ฐ ์ค์ด๋ค๊ธฐ ๋๋ฌธ์ optimization
์ค์ ์์ฒด๋ฅผ ์ ๊ฑฐํ์๋ค.
๋ง์ฝ ์ต์ ํ์ ๋ํ ์ถ๊ฐ์ ์ธ ์ค์ ์ด ํ์ํ๋ค๋ฉด ์๋์ ๋งํฌ๋ฅผ ์ฐธ๊ณ ํ๋ฉด ๋๋ค.
๋ค์์ github-pages
์์์ bundle.js
์์ค ํฌ๊ธฐ์ด๋ค. ์ด์ ๋ณด๋ค ํ ์ค์ด๋ ๊ฒ์ ํ์ธํ ์ ์๋ค.
284kB -> 84.8kB
๋ค์์ ์์ค์ฝ๋ ํฌ๊ธฐ ์ค์ด๊ธฐ
์์
์ ์งํํ ์ปค๋ฐ์ด๋ค.
2. ์ด๋ฏธ์ง ํฌ๊ธฐ ์ค์ด๊ธฐ
์ด๋ฏธ์ง ํฌ๊ธฐ๋ฅผ ์ค์ด๋ ๋ฐฉ๋ฒ์ ๋ค์ํ๋ค. ์ธ๋ถ ์ฌ์ดํธ๋ฅผ ์ด์ฉํ์ฌ ์ง์ ์ด๋ฏธ์ง ํฌ๊ธฐ๋ฅผ ์ค์ผ ์ ์๊ณ ๋ช ๋ น์ด๋ฅผ ํตํด ์ด๋ฏธ์ง ํฌ๊ธฐ์ ๋๋ถ์ด ํ์ฅ์๋ ๋ณํ์ํฌ ์ ์๋ค. ๋ํ ์นํฉ ํ๋ฌ๊ทธ์ธ์ ํ์ฉํ ์๋ ์๋ค. ์๋์์๋ ๋ด๊ฐ ๋ฏธ์ ์์ ์ ์ฉํ๋ ๋ฐฉ๋ฒ์ ๋ํ ์ค๋ช ์ด๋ค.
2-1. ๊ธฐ์กด ์ด๋ฏธ์ง ํฌ๊ธฐ
๊ธฐ์กด ์ด๋ฏธ์ง ํฌ๊ธฐ๋ฅผ ์ดํด๋ณด๋ฉด hero.png
์ Size๋ 10.7MB๋ก ๊ต์ฅํ ํฌ๋ค. ๋๋ถ์ด gif
์ Size๋ ์ค์ฌ์ผ ํ ํ์๊ฐ ๋๊ปด์ง๋ค.
2-2. ๋๋ฌด๋ ํฐ ์๋ณธ ์ฌ์ด์ฆ
Intrinsic size
์ ์ดํด๋ณด๋ฉด hero ์ด๋ฏธ์ง์ ์๋ณธ ์ฌ์ด์ฆ(ํด์๋)๋ฅผ ํ์ธํ ์ ์๋ค. ํ์ง๋ง 4100 x 2735 px
๋งํผ ํ์ํ์ง ์๋ค.
๋๋ฌธ์ ํด์๋๋ฅผ ์ค์ด๊ธฐ ์ํด ๋ค์์ ์ฌ์ดํธ๋ฅผ ์ด์ฉํ์๋ค.
์ด๋ฏธ์ง ๋น์จ์ ๊ทธ๋๋ก ๋๊ณ ์ฌ์ด์ฆ๋ฅผ 2000 x 1333px
์ผ๋ก ์ค์๋ค. ๊ฒฐ๊ณผ๋ ๋ค์๊ณผ ๊ฐ๋ค.
๋ฒ์จ ์ด๋ฏธ์ง ์ฌ์ด์ฆ๊ฐ ํ ์ค์ด๋ ๊ฒ์ ํ์ธํ ์ ์๋ค.
2-3. png๋ณด๋จ jpg
format์ ๋ณ๊ฒฝํ์ฌ ์ด๋ฏธ์ง ์ฌ์ด์ฆ๋ฅผ ๋ ์ค์ฌ๋ณด์. jpg์ด png์ ๋น๊ตํ์ ๋ ์ฉ๋์ด ํจ์ฌ ์๊ณ ์ฌ์ง๊ณผ ๊ฐ์ ์์์ด ๋ง์ ์ด๋ฏธ์ง์ ์ด์ธ๋ฆฐ๋ค.
์ด๋ฒ์๋ ์ ์ฉํ ์ฌ์ดํธ์ ๋์์ ๋ฐ์ ์ฝ๊ฒ ๋ณ๊ฒฝํ ์ ์๋ค.
๊ฒฐ๊ณผ๋ ๋ค์๊ณผ ๊ฐ๋ค.
์ด์ฒ๋ผ ์ด๋ฏธ์ง์ ์๋ณธ ์ฌ์ด์ฆ๋ฅผ ์ค์ด๊ณ format๋ง ๋ณ๊ฒฝํ์ฌ๋ ์ด๋ฏธ์ง ํฌ๊ธฐ๋ ๋ง์ด ์ค์ด๋ ๋ค.
๊ธฐ์ค | ์ด๋ฏธ์ฆ ํฌ๊ธฐ |
์๋ณธ | 10.7MB |
ํด์๋ ๋ฎ์ถ ํ | 2.4MB |
format ๋ณ๊ฒฝ ํ | 219kM |
2-4. ์ด๋ฏธ์ง๋ฅผ webp๋ก ๋ณํ ํ๊ธฐ
์์ ๊ณผ์ ์ ํตํด ์ด๋ฏธ์งํฌ๊ธฐ๊ฐ ๋ง์ด ์ค์ด๋ค์๋ค. ํ์ง๋ง ์๊ตฌ์ฌํญ(120kB ๋ฏธ๋ง)์ ์์ง ์ถฉ์กฑ์ํค์ง ๋ชปํ์๋ค. ์ด๋ฅผ webp๋ฅผ ํ์ฉํ์ฌ ํด๊ฒฐํด ๋ณด์.
web
์ด๋ฏธ์ง๋ฅผ ์ฌ์ฉํ๋ค๋ฉด ์ผ๋ฐ์ ์ผ๋ก ํ์ผ ํฌ๊ธฐ๊ฐ 25~35% ๊ฐ์ํ๋ค. ๋ช
๋ น์ด๋ฅผ ํ์ฉํ์ฌ jpgํํ์ ์ด๋ฏธ์ง๋ฅผ webp์ด๋ฏธ์ง๋ก ๋ณ๊ฒฝํด ๋ณด์.
๋จผ์ ๊ธฐ๋ณธ์ ์ธ ๋ช ๋ น์ด ์ฌ์ฉ๋ฐฉ๋ฒ์ ๋ค์๊ณผ ๊ฐ๋ค.
$ cwebp -q {ํ์ง(0~100)} {์๋ณธ ํ์ผ ๊ฒฝ๋ก} -o {๋ณ๊ฒฝ๋ webp ํ์ผ ๊ฒฝ๋ก}
๋ค์์ ์ค์ ๋ก ํ๋ก์ ํธ์์ ์ฌ์ฉํ ๋ช ๋ น์ด์ด๋ค.
$ cwebp -q 40 src/assets/images/hero.jpg -o src/assets/images/hero.webp
webp๋ก ๋ณํํ์ฌ ์ด๋ฏธ์ง ํฌ๊ธฐ๋ฅผ ํ์ธํ ๊ฒฐ๊ณผ 109kB๋ก ์ค์ด๋ ๊ฒ์ ํ์ธํ ์ ์๋ค.
๋ค์์ผ๋ก webp๋กค ์ฌ์ฉํ์ฌ ์ด๋ฏธ์ง๋ฅผ ํ๋ฉด์ ๋์ด๋ณด์. ์ด๋ฅผ ์ํด picture
ํ๊ทธ๋ฅผ ํ์ฉํด์ผ ํ๋ค.
// ...
const MyComponents = () => {
return (
<picture>
<source
className={styles.heroImage}
type="image/webp"
srcSet={heroImageWebp}
/>
<img className={styles.heroImage} src={heroImage} alt="hero image" />
</picture>
);
// ...
};
webp
๋ฅผ ์ง์ํ๋ ๋ธ๋ผ์ฐ์ ์ธ ๊ฒฝ์ฐ webp
์ด๋ฏธ์ง๋ฅผ ๋ณด์ฌ์ฃผ๊ณ ๊ทธ๋ ์ง ์์ ๋ธ๋ผ์ฐ์ ์ธ ๊ฒฝ์ฐ์ jpg
์ด๋ฏธ์ง๋ฅผ ๋ณด์ฌ์ค๋ค. ๋ค์์ด webp๋ฅผ ์ ์ฉํ ๊ฒฐ๊ณผ์ด๋ค.
๋ํ ๋ค์๊ณผ ๊ฐ์ด ํ๋ฉด ๋๋น์ ๋ฐ๋ผ ํฌ๊ธฐ๊ฐ ๋ค๋ฅธ ์ด๋ฏธ์ง๋ฅผ ๊ฐ๊ฐ ๋ถ๋ฌ์ฌ ์๋ ์๋ค.
const MyComponents = () => {
return (
<picture>
<source
src={heroImage}
className={styles.heroImage}
type="image/webp"
srcSet={`${heroImageSmallWebp} 700w, ${heroImageLargeWebp} 2000w`}
/>
<img className={styles.heroImage} src={heroImage}></img>
</picture>
);
// ...
};
2-5. ๊ฒฐ๋ก ๋ฐ ์ต์ข ๊ฒฐ๊ณผ
์ด๋ฏธ์ง ์ต์ ํ๋ฅผ ํ๊ธฐ ์ํด ์ฝ๋์ ์ผ๋ก ๋ง์ ๋ถ๋ถ์ ์์ ํ๊ธฐ๋ณด๋ค๋ ์ด๋ฏธ์ง ํฌ๋งท, ํ์์ ๋ฐ๊พธ์ด ์ด๋ฏธ์ง์ ํฌ๊ธฐ(์ฉ๋) ์์ฒด๋ฅผ ์ค์๋ค. ์ง๊ธ๊น์ง ๊ฑฐ์ณ์จ ๊ณผ์ ๊ณผ ์ด์ ๋ฐ๋ฅธ ๊ฒฐ๊ณผ๋ฅผ ํ๋ก ๋ํ๋ด๋ฉด ๋ค์๊ณผ ๊ฐ๋ค.
๊ธฐ์ค | ์ด๋ฏธ์ฆ ํฌ๊ธฐ |
์๋ณธ | 10.7MB |
ํด์๋ ๋ฎ์ถ ํ | 2.4MB |
format ๋ณ๊ฒฝ ํ | 219kM |
webp๋ก ๋ณ๊ฒฝ ํ | 109kM |
์ด๋ฏธ ํด์๋ ๋ณ๊ฒฝ, format ๋ณ๊ฒฝ์ ๊ฐ๋ฅํ๊ฒ ํด์ฃผ๋ ์ฌ์ดํธ๋ ๊ฒ์๋ง ํด๋ ๋ง์ด ์๋ค. ๋๋ฌธ์ ์ด๋ ต์ง ์์๊ณ webp๋ ์ฌ์ดํธ์์ ๋ณ๊ฒฝ์ ํ ์ ์์ง๋ง ๋ช
๋ น์ค์ ์ฌ์ฉํ์ฌ WebP ์ด๋ฏธ์ง ๋ง๋ค๊ธฐ ์์ ์๊ฐํ๋ cwebp
๋ช
๋ น์ด๋ฅผ ์ฌ์ฉํ์๋ค. picture
ํ๊ทธ์ ๋ํ ์ค๋ช
๋ ํจ๊ป ์์ด ํฐ ์ด๋ ค์์ด ์์ด ์ด๋ฏธ์ง ์ต์ ํ๋ฅผ ๋ง๋ฌด๋ฆฌํ ์ ์์๋ค.
๋ค์์ ์ด๋ฏธ์ง ํฌ๊ธฐ ์ค์ด๊ธฐ
์์
์ ์งํํ ์ปค๋ฐ์ด๋ค.
3. ์ ๋๋ฉ์ด์ GIF๋ฅผ ๋น๋์ค๋ก ๋์ฒดํ๊ธฐ
์ ๋๋ฉ์ด์ GIF๋ ์ฉ๋์ด ํฌ๋ค. ๋๋ฌธ์ mp4, webm๊ณผ ๊ฐ์ ํ์ผ ํ์์ ๋น๋์ค๋ก ๋ณํํ์ฌ ํ์ด์ง๋ฅผ ๋ ๋น ๋ฅด๊ฒ ๋ก๋ํ๋ค๋ฉด ์ฑ๋ฅ์ ๋์ฑ ์ข์์ง ๊ฒ์ด๋ค.
3-1. ffempeg ์ค์น
๋ฏธ์
์์ ์ ๋๋ฉ์ด์
GIF๋ฅผ ๋น๋์ค(mp4, webm)๋ก ๋ณํํ๊ธฐ ์ํด ffempeg
๋ช
๋ น์ด๋ฅผ ์ฌ์ฉํ๋ค. ffempeg
๋ช
๋ น์ด๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํด์ ์ด๋ฅผ ์ค์นํด์ผ ํ๋๋ฐ, ์ค์น๋ถํฐ ์ฝ์ง ์์ ๊ณผ์ ์ด์๋ค. ์ค์น๋ง ๋งค๋๋ฝ๊ฒ ๋์๋ค๋ฉด ํจ์ฌ ๊ฐํธํ๊ณ ๋น ๋ฅด๊ฒ ์์
์ ๋ง๋ฌด๋ฆฌํ์์ ๊ฒ์ด๋ค.
๊ธฐ๋ณธ์ ์ธ ์ค์น ๋ช ๋ น์ด๋ ๋ค์๊ณผ ๊ฐ๋ค.
$ brew install ffmpeg
ํ์ง๋ง ์ด ๊ณผ์ ์์ ์ค์น ์ค๋ฅ๊ฐ ๋ฌ๋ค๋ฉด ์ต์ ๋ฆด๋ฆฌ์ฆ ๋ฒ์ ์ผ๋ก ์ค์น๋ฅผ ํด์ผ ํ๋๋ฐ, ์ด๋์๋ ๋ค์๊ณผ ๊ฐ์ ๋ช ๋ น์ด๋ฅผ ์ ๋ ฅํด์ผ ํ๋ค.
$ brew install ffmpeg --HEAD
3-2. mp4 ๋น๋์ค๋ก ๋ณํํ๊ธฐ
์ฐ์ mp4
๋ก ๋ณํ์ ํด๋ณด์. ffempeg
๋ช
๋ น์ด๋ฅผ ์ฌ์ฉํ์ฌ gif
์ mp4
๋ก ๋ณํํ๊ธฐ ์ํด์ ๋ค์๊ณผ ๊ฐ์ด ๋ช
๋ น์ด๋ฅผ ์คํํด์ผ ํ๋ค.
$ ffmpeg -i {์๋ณธ gifํ์ผ ๊ฒฝ๋ก} -b:v 0 -crf 25 -f mp4 -vcodec libx264 -pix_fmt yuv420p {๋ณํ๋ mp4 ํ์ผ ๊ฒฝ๋ก}
์ ๋ช
๋ น์ด์์๋ libx264
์ธ์ฝ๋๋ฅผ ์ฌ์ฉํ๋๋ฐ ์ด๋ 320x240ํฝ์
๊ณผ ๊ฐ์ด ํฌ๊ธฐ๊ฐ ์ง์์ธ ํ์ผ์์๋ง ์๋ํ๋ค. ๋๋ฌธ์ gif
์ ํฌ๊ธฐ๊ฐ ํ์์ธ ๊ฒฝ์ฐ์ ๋ค์๊ณผ ๊ฐ์ด "crop=trunc(iw/2)2:trunc(ih/2)2"์ ๋ช
๋ น์ด์ ์ถ๊ฐํด์ผ ํ๋ค.
$ ffmpeg -i {์๋ณธ gifํ์ผ ๊ฒฝ๋ก} -vf "crop=trunc(iw/2)*2:trunc(ih/2)*2" -b:v 0 -crf 25 -f mp4 -vcodec libx264 -pix_fmt yuv420p {๋ณํ๋ mp4 ํ์ผ ๊ฒฝ๋ก}
์ด๋ฅผ ๋ฐํ์ผ๋ก ์ค์ ํ๋ก์ ํธ์ ์ฌ์ฉํด ๋ณด์.
$ ffmpeg -i src/assets/images/find.gif -vf "crop=trunc(iw/2)*2:trunc(ih/2)*2" -b:v 0 -crf 25 -f mp4 -vcodec libx264 -pix_fmt yuv420p src/assets/images/find.mp4
$ ffmpeg -i src/assets/images/free.gif -vf "crop=trunc(iw/2)*2:trunc(ih/2)*2" -b:v 0 -crf 25 -f mp4 -vcodec libx264 -pix_fmt yuv420p src/assets/images/free.mp4
$ ffmpeg -i src/assets/images/trending.gif -vf "crop=trunc(iw/2)*2:trunc(ih/2)*2" -b:v 0 -crf 25 -f mp4 -vcodec libx264 -pix_fmt yuv420p src/assets/images/trending.mp4
์ฑ๊ณต์ ์ผ๋ก ๋ณํ๋ ๊ฒ์ ํ์ธํ ์ ์๋ค.
๋ค์ ํ๋ gif
์ mp4
์ ํ์ผ ํฌ๊ธฐ๋ฅผ ๋น๊ตํ ๊ฒ์ด๋ค.
์ด๋ฆ\ํ์ผํ์ | gif | mp4 |
find | 2MB | 218kB |
free | 1.7MB | 126kB |
trending | 1.3MB | 111kB |
3-3. webm ๋น๋์ค๋ก ๋ณํํ๊ธฐ
์ด๋ฒ์๋ webm ๋น๋์ค๋ก ๋ณํ๋ฅผ ํด๋ณด์. mp4
๋ 1999๋
๋ถํฐ ์ฌ์ฉ๋์์ง๋ง webm
์ ๋น๊ต์ ์ต๊ทผ์ธ 2010๋
์ ์ถ์๋ ์๋ก์ด ํ์ผ ํ์์ด๋ค. webm
์ด mp4
์ ๋น๊ตํ์ ๋ ํ์ผ ํฌ๊ธฐ๊ฐ ์์ง๋ง ๋ชจ๋ ๋ธ๋ผ์ฐ์ ๊ฐ ์ง์์ ํ๋ ๊ฒ์ด ์๋๋ฏ๋ก ๋ ๊ฐ์ ํ์์ ๋น๋์ค๋ฅผ ๋ชจ๋ ๋ง๋ค์ด ์ฌ์ฉํ๋ ๊ฒ์ด ์ข๋ค.
๋ค์์ ffempeg
๋ช
๋ น์ด๋ฅผ ์ฌ์ฉํ์ฌ webm
์ผ๋ก ๋ณํํ๋ ๋ช
๋ น์ด์ด๋ค.
$ ffmpeg -i {์๋ณธ gifํ์ผ ๊ฒฝ๋ก} -c vp9 -b:v 0 -crf 41 {๋ณํ๋ webm ํ์ผ ๊ฒฝ๋ก}
๋ฐ๋ก ํ๋ก์ ํธ์ ์ ์ฉํด ๋ณด์.
$ ffmpeg -i src/assets/images/find.gif -c vp9 -b:v 0 -crf 41 src/assets/images/find.webm
$ ffmpeg -i src/assets/images/free.gif -c vp9 -b:v 0 -crf 41 src/assets/images/trending.webm
$ ffmpeg -i src/assets/images/trending.gif -c vp9 -b:v 0 -crf 41 src/assets/images/trending.webm
webm
์ผ๋ก ์ฑ๊ณต์ ์ผ๋ก ๋ณํ๋์๊ณ mp4
๋ณด๋ค ๋ ์์์ง ํ์ผ ํฌ๊ธฐ๋ฅผ ํ์ธํ ์ ์๋ค.
์ด๋ฆ\ํ์ผํ์ | gif | mp4 | webm |
find | 2MB | 218kB | 159kB |
free | 1.7MB | 126kB | 105kB |
trending | 1.3MB | 111kB | 84kB |
3-4. ์ฝ๋์ ์ ์ฉํ๊ธฐ
๋ค์์ gif
ํ์ผ์ ๋ฐํ์ผ๋ก ๋ ๋๋ง์ ํ๋ ๊ธฐ์กด์ฝ๋์ด๋ค.
const FeatureItem = ({ title, imageSrc }: FeatureItemProps) => {
return (
<div className={styles.featureItem}>
<img className={styles.featureImage} src={imageSrc} />
<div className={styles.featureTitleBg}></div>
<h4 className={styles.featureTitle}>{title}</h4>
</div>
);
};
์ฐ์ img
ํ๊ทธ๋ฅผ video
ํ๊ทธ๋ก ๋ฐ๊พธ์ด๋ณด์. ์ด๋ video
ํ๊ทธ์๋ ๋ค์๊ณผ ๊ฐ์ ์์ฑ์ ์ถ๊ฐํ์ฌ gif
์ฒ๋ผ ๋ณด์ด๊ฒ ํ ์ ์๋ค.
- autoPlay: ์๋ ์ฌ์
- loop: ๋ฌดํ ๋ฐ๋ณต
- muted: ์์๊ฑฐ
- playsInline: ์ธ๋ผ์ธ์ผ๋ก ์ฌ์(์ ์ฒด ํ๋ฉด์ด ์๋)
const FeatureItem = ({ title, imageSrc }: FeatureItemProps) => {
return (
<div className={styles.featureItem}>
<video className={styles.featureImage} autoPlay loop muted playsInline>
<h4 className={styles.featureTitle}>{title}</h4>
</video>
</div>
);
};
๋ค์ ์์
์ source
ํ๊ทธ๋ฅผ ํตํด ๋ธ๋ผ์ฐ์ ๊ฐ ์ง์ํ ์ ์๋ ๋น๋์ค ํ์ผ์ ์ถ๊ฐํ๋ค. ๋จผ์ webm
๊ทธ๋ค์์ mp4
์ด๋ค.
const FeatureItem = ({ title, webmSrc, mp4Src }: FeatureItemProps) => {
return (
<div className={styles.featureItem}>
<video className={styles.featureImage} autoPlay loop muted playsInline>
<source src={webmSrc} type="video/webm" />
<source src={mp4Src} type="video/mp4" />
<h4 className={styles.featureTitle}>{title}</h4>
</video>
</div>
);
};
3-5. ๊ฒฐ๋ก ๋ฐ ์ต์ข ๊ฒฐ๊ณผ
์ฑ๊ณต์ ์ผ๋ก gif
์ webm
์ผ๋ก ๋ณํํ์ฌ ํ์ผ ํฌ๊ธฐ๋ฅผ ์ค์๋ค. ๋ค์์ ์ต์ข
๊ฒฐ๊ณผ๋ก dev
ํ๊ฒฝ์์์ webm
ํ์ผ์ ํฌ๊ธฐ์ด๋ค.
์ ๋๋ฉ์ด์
GIF๋ฅผ ๋น๋์ค๋ก ๋์ฒดํ๊ธฐ
์์
์ ์ํด ์ฐธ๊ณ ํ ๊ธ์ด๋ค.
๋ค์์ ์ ๋๋ฉ์ด์
GIF๋ฅผ ๋น๋์ค๋ก ๋์ฒดํ๊ธฐ
์์
์ ์งํํ ์ปค๋ฐ์ด๋ค.
4. ๋ง๋ฌด๋ฆฌ
lighthouse
์ ๋ฐํ์ผ๋ก ์ผ๋ง๋ ์ฑ๋ฅ์ด ๊ฐ์ ๋์๋์ง ํ์ธํ๋ฉฐ ๋ง๋ฌด๋ฆฌํด ๋ณด์.
๊ฐ์ ์
๊ฐ์ ํ
'๐ ์ฐ์ํํ ํฌ์ฝ์ค > Level4' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
๋ ๋ฒจ4 ํ๋ก ํธ์๋ ์ฑ๋ฅ ๋ฒ ์ด์ค์บ ํ 2 - ํ์ํ ๊ฒ๋ง ์์ฒญํ๊ธฐ (2) | 2023.10.08 |
---|