사용자에게 있어서 모바일
속도 지연으로 인한 스트레스 반응
은 거의 공포영화를 보거나 수학 문제를 푸는 정도의 스트레스라고 합니다😱
여러분들도 웹 페이지를 접속할때 너무 느리다면 그 서비스를 사용하지 않을거예요.
즉, 속도 개선은 사용자 이탈을 방지하고 가입율을 증가시킵니다. 이는 곧 서비스의 수익과 직결
되는 문제죠.
이 포스팅은 React에 기반한 성능 개선입니다.
✨설치
npm install --save-dev html-webpack-plugin
✨HTMLWebpackPlugin
// webpack.config.js에서
plugins: [
new HtmlWebpackPlugin({
minify: {
collapseWhitespace: true, // 빈칸 제거
removeComments: true // 주석 제거
},
template: './index.html',
hash: true // 캐싱 방지: 매 빌드마다 다른 queryString과 함께 bundle.js를 불러와서 파일이 동일하지 않음을 알려줍니다.
}),
new CopyWebpackPlugin({
patterns: [{ from: './public', to: './public' }]
}),
new Dotenv()
],
✨설치
npm install --save-dev mini-css-extract-plugin
npm install --save-dev optimize-css-assets-webpack-plugin
✨mini-css-extract-plugin
module: {
rules:[
{
test: /\.css$/i,
use: [MiniCSSExtractionPlugin.loader, 'css-loader']
},
...
]
...
}
plugins: [
new MiniCSSExtractionPlugin({
filename: '[name].[contenthash].css' // contenthash를 통해 네이밍을 짓는다면 캐싱할때 유리해요. (파일이 변경되면 네이밍이 바뀜)
})
],
MiniCSSExtractionPlugin
을 사용하는 것이 좋아요.🤔 style-loader vs MiniCSSExtractionPlugin
style-loader
는 빌드 시 인라인으로 스타일을 주입해줍니다.
반면에 MiniCSSExtractionPlugin
은 JS파일에서 호출되는 style 코드들을 CSS 파일을 따로 분리하여 만들어주죠.
개발할 때
에는 CSS 파일 수정이 많아서 DOM에 <style>로 직접 주입하는 것이 빠르므로
style-loader를 사용하면 좋아요.
프로덕션 빌드
에는 병렬 로딩을 통해서 분리도니 CSS 코드들을 더 빠르게 가져올 수 있기 때문에 MiniCSSExtractionPlugin를 사용하는 것이 좋아요.
✨optimize-css-assets-webpack-plugin
HTML의 빈칸을 압축한 것처럼, css 파일도 빈칸을 없애는 압축을 할 수 있어요.
이를 이용한다면 css 코드를 하나로 묶은 파일이 생성되고, 빌드된 HTML 파일의 head tag안에서 불러오게 됩니다.
optimization: {
minimizer: mode === 'production' ? [new OptimizeCSSAssetsPlugin()] : []
}
하지만 2022-09-25 기준으로 npm 페이지에 들어가보니 optimize-css-assets-webpack-plugin
보다는 css-minimizer-webpack-plugin
을 사용하도록 권장하고 있더라구요! 참고하면 좋을 것 같아요.
https://yamoo9.gitbook.io/webpack/webpack/webpack-plugins/extract-css-files
웹팩 5 이전 버전이라면 아래처럼 해야해요.
✨설치
npm install -D terser-webpack-plugin
✨terser-webpack-plugin
optimization: {
minimizer: mode === 'production' ? [new OptimizeCSSAssetsPlugin(), new TerserPlugin()] : []
}
✨mode 설정
const PRODUCTION = 'production';
const DEVELOPMENT = 'development';
const mode = process.env.NODE_ENV || DEVELOPMENT;
module.exports = {
mode,
...
}
하지만 웹팩 5부터는 자동으로 적용해요! (웹팩은 신인가..?)
FlagDependencyUsagePlugin
FlagIncludedChunksPlugin
ModuleConcatenationPlugin
NoEmitOnErrorsPlugin
OccurrenceOrderPlugin
SideEffectsFlagPlugin
TerserPlugin
따라서 그저 아래와 같이 하면 된답니다.
minimizer: [
'...',
]
✨image-webpack-loader
module: {
rules: [
{
test: /\.(png|jpg|jpeg|gif|webp)$/i,
loader: 'image-webpack-loader',
enforce: 'pre',
},
]
}
✨직접 수정하기 -> 파일 형식을 webp로!
✨ImageMinimizerPlugin
optimization: {
minimize: true,
minimizer: [
'...',
new ImageMinimizerPlugin({
minimizer: {
implementation: ImageMinimizerPlugin.imageminGenerate,
options: {
plugins: [
['webp', { quality: 40, resize: { width: 1200, height: 0 } }]
]
}
}
})
]
}
✨img 태그의 srcset 속성
✨webp를 못 읽는 구형 브라우저라면?
SPA는 js 번들 파일에 모든 app에 대한 로직을 처음에 불러오기 때문에 로딩 속도가 지연될 수 있다는 단점이 있죠. 하지만 필요한 것만을 그때 그때 불러오면 어떨까요?
코드 스플리팅은 번들 파일을 여러 개의 파일로 분리하는 기법이예요.
React에서는 React.lazy와 Suspense
를 활용하여 코드 스플리팅을 구현할 수 있어요.
트리 쉐이킹이 "나무를 흔든다"는 뜻이죠.
즉, 사용하지 않는 코드들을 번들에 포함시키지 않고 나뭇잎처럼 떨어뜨리겠는 의미입니다.
// loadash의 모든 것을 가져올 거예요.
import { sortBy } from 'lodash'
// sortBy만 가져옵니다.
import sortBy from 'lodash-es/sortBy'
Side-Effect를 일으키지 않는 모듈은바깥의 변수를 변경하지 않고 인풋을 넣었을 때 아웃풋이 예측
할 수 있도록 되어 있어야 Tree-Shaking 하기에 안전한 모듈이라고 합니다.
// in package.json...
{
"name": "webpack-tree-shaking-example",
"version": "1.0.0",
"sideEffects": [
"./src/utils/utils.js"
]
}
이렇게 설정하면 특정 모듈이 sideEffects를 발생시키지 않는다고 명시할 수 있어요.
https://helloinyong.tistory.com/305
gzip은 파일 압축에 쓰이는 응용 소프트웨어예요.
현재 대부분의 모든 브라우저에서 Gzip압축을 지원하고 있어요.
브라우저가 Gzip을 지원한다면 서버에게 Accept-Encoding:gzip
헤더를 통해서 Gzip 지원 여부를 알려줘요.
웹 서버는 그에 답하여 Content-Encoding:gzip
응답헤더에 넣어주게 되죠!
보통 Nginx, CloudFront 등에서 Gzip을 설정해줄 수 있어요.
하지만 안 된다면 다음의 플러그인을 설치해봐요.
✨설치
npm install compression webpack plugin
Content-Encoding
헤더에 상응하도록 assets들의 압축을 도와주는 플러그인이예요.
compression webpack plugin - npm
plugins:[
...,
new CompressionPlugin(),
]
성능에 있어서 캐싱은 너무나 중요한 포인트죠.
데이터가 유효할 때까지 클라이언트와 가까운 곳에 데이터를 저장해두고
빠르게 꺼내 쓸 수 있도록 합니다.
Cloudfront에서는 캐시 정책을 생성할 수 있어요.
TTL, 최대 TTL, 기본 TTL을 설정할 수 있습니다.
브라우저에서도 캐시를 제공합니다.
👀 캐싱은 다른 포스팅에서 조금 더 자세하게 다루겠습니다.
https://parkadd.tistory.com/116
S3에서는 각 파일마다 메타데이터를 설정할 수 있어요.