์น์ฑ๋ฅ ๊ฐ์ ์ ์ํ ์ด๊ฒ์ ๊ฒ/์ฌ๋ฌ๊ฐ์ง ๋ฐฉ๋ฒ์ ์์ฑํด๋ณด๋ ค๊ณ ํ๋ค. ๊ฐ์ธ์ ์ผ๋ก ๊ณต๋ถํ๋ ๋ด์ฉ์ด๋ผ ๋์๊ฐ ์์ ์ ์์ผ๋ ์ฃผ์!
Bundle analyzer
bundle
๋ JS
ํ์ผ์ด ์ด๋ค ์ฝ๋๋ค๋ก ์ด๋์ ๋์ ํฌ๊ธฐ๋ฅผ ๊ฐ์ง๊ณ ์๋์ง ๊ฐ์ํ ํ์ฌ ๋ณด์ฌ์ฃผ๋๊ฒ์ด ๋ฐ๋ก bundle-analyzer
์ด๋ค. NEXTJS
๋ฅผ ์ฌ์ฉํ ๊ฒฝ์ฐ @next/bundle-analyzer๋ฅผ, CRA
(create-react-app
)์ ์ฌ์ฉํ ๊ฒฝ์ฐ์๋ cra-bundle-analyzer๋ฅผ ์ธํ
ํ๋ฉด ๋๋ค. bundle analyzer๋ฅผ ์คํํ๋ฉด ์๋ ์ฌ์ง์ฒ๋ผ JS ์ฝ๋๊ฐ ์ด๋ป๊ฒ ๊ตฌ์ฑ๋์ด ์๋์ง ๋ณด์ฌ์ค๋ค. ๊ทธ ํฌ๊ธฐ๊ฐ ํด์๋ก ํฐ ์ฉ๋์ ์ฐจ์งํ๋ค.

Image size optimization with CDN

image CDN
์ ์ฌ์ฉํ๋ค. CDN
(Content Delivery Network
)์ ์ปจํ
์ธ ๋ฅผ ๋น ๋ฅด๊ณ , ์ ๋ ดํ๊ณ , ์์ ํ๊ฒ ์ ์กํ๊ธฐ ์ํด ์ฐ๊ฒฐ๋ ์๋ฒ ๋คํธ์ํฌ์ด๋ค. ์ง๋ฆฌ์ ์ผ๋ก ๋ถ์ฐ์์ผ ์น ์ปจํ
์ธ ๋ฅผ ์ฌ์ฉ์์ ๊ฐ๊น์ด ๊ณณ์์ ์ ์กํจ์ผ๋ก์จ ์ ์ก ์๋๋ฅผ ๋์ธ๋ค.
CDN
์ image ๋ฟ๋ง ์๋๋ผ web page
, image
, video
๋ฑ์ ์ปจํ
์ธ ๋ฅผ ์ฌ์ฉ์์ ๋ฌผ๋ฆฌ์ ์์น์ ๊ฐ๊น์ด server์ caching
ํ๋ค. ๋ํ์ ์ธ image CDN
service๋ cloudinary, imagekit.io ๋ฑ์ด ์๋ค.
Code splitting & Lazy loading
bundler
๋ฅผ ์ฌ์ฉํ๋ฉด ํ๋์ bundle๋ก ์ฝ๋๋ฅผ ๋ณํํด์ฃผ์ด ์ฑ์ ๋ก๋ํ ๋ ํธ๋ฆฌํ์ง๋ง, ๋ณ๋์ ํฐ third-party library๋ฅผ ํฌํจํ๋ ๊ฒฝ์ฐ ์ด ๋ํ bundle์ ํฌํจ๋๊ธฐ ๋๋ฌธ์ ๋ก๋์๊ฐ์ด ์ค๋ ๊ฑธ๋ฆฌ๋ ๋ฌธ์ ๊ฐ ๋ฐ์ํ๋ค. ์ด๋ code splitting
๊ณผ lazy loading
์ ์ฌ์ฉํ๋ฉด ์ฑ๋ฅ์ ํฅ์ ์ํฌ ์ ์๋ค.
lazy component
๋ Suspense
ํ์์์ rendering๋์ด์ผ ํ๋ฉฐ, suspense
๋ lazy component
๊ฐ ๋ก๋๋๊ธธ ๊ธฐ๋ค๋ฆฌ๋ ๋์ ๋ก๋ฉํ๋ฉด์ ๋ณด์ฌ์ค ์ ์๋ค.
import React, { Suspense } from 'react';
const OtherComponent = React.lazy(() => import('./OtherComponent'));
function MyComponent() {
return (
<div>
<Suspense fallback={<div>Loading...</div>}>
<OtherComponent />
</Suspense>
</div>
);
}
Don't use the INDEX as KEY
key
๋ React
๊ฐ ์ด๋ค ํญ๋ชฉ์ ๋ณ๊ฒฝ, ์ถ๊ฐ ๋๋ ์ญ์ ํ ์ง ์๋ณํ๋ ๊ฒ์ ๋๋๋ค. ์์ ์ ์ธ ๊ณ ์ ์ฑ์ ๋ถ์ฌํ๊ธฐ ์ํด ๋ด๋ถ์ element
์ ๋ช
์ํ๊ฒํ๋ค. ๋๋ถ๋ถ์ ๊ฒฝ์ฐ ๋ฐ๋ณต๋ฌธ์ ์ฌ์ฉํ๋ data set
์ unique
ํ id
๋ฅผ key
๋ก ์ฌ์ฉํ๋ค.
todos.map((todo, index) => (
<Todo {...todo} key={index} /> // don't
));
}
๋ง์ฝ ํญ๋ชฉ์ ์์๊ฐ ๋ฐ๋ ์ ์๋ ๊ฒฝ์ฐ, key
์ index
๋ฅผ ์ฌ์ฉํ๋๊ฒ์ ๊ถ์ฅํ์ง ์๋๋ค. ์ฑ๋ฅ์ด ์ ํ๋๊ฑฐ๋ component
์ state
์ ๊ด๋ จ๋ ๋ฌธ์ ๊ฐ ๋ฐ์ ํ ์ ์๊ธฐ ๋๋ฌธ์ด๋ค. ์ด ํฌ์คํ
์์ ์์ธํ ์ค๋ช
๋์ด ์๋ค. component
๋ key
๋ฅผ ๋ณด๊ณ ๊ฐฑ์ ๋๊ณ ์ฌ์ฌ์ฉ๋๋ค. index
๋ฅผ ์ฌ์ฉํ๋ค๋ฉด ํญ๋ชฉ์ ์์๊ฐ ๋ฐ๋์์ ๊ฒฝ์ฐ key
๋ํ ๋ฐ๋์์ ๊ฑฐ๊ณ ์ด๋ state
์ ์ํฅ์ ์ค ์ ์๋ค. ํ์ง๋ง ๋ฐฐ์ด์ ํญ๋ชฉ๋ค์ด static
ํ์ฌ ๋ณ๊ฒฝ๋์ง ์๋ ๋จ์ ๋ฐ๋ณต์ ๊ฒฝ์ฐ์๋ index
๋ฅผ key
๋ก ์ฌ์ฉํด๋ ๋ฌธ์ ๊ฐ ๋ฐ์ํ ํ๋ฅ ์ด ๋ฎ๋ค.
Animation optimization
will-change
์์ฑ์ ์์์ ์์๋๋ ๋ณํ์ ์ข
๋ฅ์ ๊ดํ ํํธ๋ฅผ ๋ธ๋ผ์ฐ์ ์ ์ ๊ณตํ๋ค. ๊ทธ๋์ ์์๊ฐ ๋ณํ๋๊ธฐ ์ ์ ๋ฏธ๋ฆฌ ๋ธ๋ผ์ฐ์ ๋ ์ ์ ํ๊ฒ ์ต์ ํํ ์ ์๋ค.
animation
์ ๊ตฌํํ ๋ javascript code๋ฅผ ์ด์ฉํ ์๋ ์์ง๋ง css
๋ฅผ ์ด์ฉํด์๋ ํ๋ฅญํ animation
์ ๊ตฌํํ ์ ์๋ค. ํ์ง๋ง animation ์ฒ๋ผ ์์ง์์ด ๋ฐ์ํ๋ ๊ฒฝ์ฐ ๊ทธ์ ๋ฐ๋ฅธ ์ฐ์ฐ๋์๋ ๊ฝค๋ ๋ง์ ๋ถํ๊ฐ ํ์ํ๊ณ ์ ์ ํ ํจ์จ์ ์ธ ์ฝ๋๋ก ์์ฑํ๋๊ฒ์ด ๋ฐ๋์ ํ์ํ๋ค.
์ผ๋ฐ์ ์ผ๋ก animation
์ ๊ตฌํํ๊ฒ ๋๋ฉด ๋ค์๊ณผ ๊ฐ์ ํ๋ฆ์ผ๋ก ๋์ํ๊ฒ ๋๋ค.
- Recalculate (
element
์style
์ด ์ ์ฉ๋ ๊ฒฝ์ฐ ๋ฐ์) - Reflow (์ ์ฉ๋
style
์ ์ํด ์์น๋ ํฌ๊ธฐ๊ฐ ๋ณ๊ฒฝ๋์ด ๊ณ์ฐ์ด ํ์ํ ๊ฒฝ์ฐ ๋ฐ์ : CPU๋ฅผ ์ด์ฉํ์ฌ ์ํ) - Repaint (
element
๊ฐ ํ๋ฉด์ ๋ค์ ๊ทธ๋ ค์ ธ์ผ ํ ๊ฒฝ์ฐ ๋ฐ์)
ํ์ง๋ง GPU๋ฅผ ์ฌ์ฉํ๋ option์ ์ฌ์ฉํ ๊ฒฝ์ฐ์๋ ๋ค์๊ณผ ๊ฐ์ ํ๋ฆ์ผ๋ก ๋์ํ๋ค.
- Recalculate
- Composite layer (Render layer๋ฅผ ๊ณ์ฐํ๊ณ ํฉ์ฑ : GPU๋ฅผ ์ด์ฉํ์ฌ ์ํ)
GPU๋ฅผ ํตํด animation
์ ์ํํ๋ค๋ ๊ฒ์ ๊ธฐํ๊ตฌ์กฐ๋ฅผ ๊ณ์ฐํ๊ณ ๊ทธ๋ ค์ฃผ๋ reflow
/repaint
๋์์ CPU์์ ๊ฑฐ์น ํ์๊ฐ ์๋ค๋ ๋ป์ด๋ค. ๋ํ์ ์ผ๋ก GPU๋ฅผ ์ฌ์ฉํ๋ css option์ transform
๊ณผ opacity
๊ฐ ์๋ค. ํจ์จ์ ์ธ animation
์ ๊ตฌํํ๊ธฐ ์ํด ์ด top
/left
, display
๋ฅผ ์ฌ์ฉํ๊ธฐ๋ณด๋ค ์ด ๋๊ฐ์ง๋ฅผ ์ ๊ทน์ ์ผ๋ก ํ์ฉํ๋๋ก ํ์.
- https://robinpokorny.medium.com/index-as-a-key-is-an-anti-pattern-e0349aece318
- https://developer.mozilla.org/en-US/docs/Web/Performance/CSS_JavaScript_animation_performance#running_the_performance_test
- https://www.smashingmagazine.com/2016/12/gpu-animation-doing-it-right/