์ด๋ฏธ์ง ์ต์ ํ
์ค๋ช
์ด๋ฏธ์ง๋ ์น ํ์ด์ง์์ ํฐ ๋ถ๋ถ์ ์ฐจ์งํ๋ฉฐ, ์ต์ ํ๋์ง ์์ ์ด๋ฏธ์ง๋ ๋ก๋ฉ ์๊ฐ์ ์ง์ฐ์ํฌ ์ ์์ต๋๋ค.
์ต์ ํ ๋ฐฉ๋ฒ
- ์ ์ ํ ํ์ ์ ํ: JPEG๋ ์ฌ์ง์, PNG๋ ํฌ๋ช ๋๊ฐ ํ์ํ ์ด๋ฏธ์ง์ ์ฌ์ฉ.
- ์ด๋ฏธ์ง ์์ถ: TinyPNG, ImageOptim๊ณผ ๊ฐ์ ๋๊ตฌ๋ฅผ ์ฌ์ฉํด ์ด๋ฏธ์ง ํ์ผ ํฌ๊ธฐ ์ถ์.
- ๋ฐ์ํ ์ด๋ฏธ์ง ์ฌ์ฉ: srcset ์์ฑ์ ์ฌ์ฉํด ๋ค์ํ ํด์๋์ ๋ง๋ ์ด๋ฏธ์ง๋ฅผ ์ ๊ณต.
<img src="image-320w.jpg" srcset="image-320w.jpg 320w, image-640w.jpg 640w, image-1280w.jpg 1280w" alt="Example Image">
์ฝ๋ ์คํ๋ฆฌํ
์ค๋ช
์ฝ๋ ์คํ๋ฆฌํ ์ ์ ํ๋ฆฌ์ผ์ด์ ์ ์ฝ๋๋ฅผ ์ฌ๋ฌ ๊ฐ์ ์์ ๋ฒ๋ค๋ก ๋ถํ ํ์ฌ ํ์ํ ๋ถ๋ถ๋ง ๋ก๋ํ๋๋ก ํ๋ ๊ธฐ๋ฒ์ ๋๋ค.
์ต์ ํ ๋ฐฉ๋ฒ
- Webpack ์ฌ์ฉ: Webpack์ Dynamic Imports๋ฅผ ํ์ฉํด ์ฝ๋ ์คํ๋ฆฌํ ๊ตฌํ.
- React.lazy์ Suspense ์ฌ์ฉ: React ์ ํ๋ฆฌ์ผ์ด์ ์์ ์ปดํฌ๋ํธ ๋จ์๋ก ์ฝ๋ ์คํ๋ฆฌํ .
const OtherComponent = React.lazy(() => import('./OtherComponent'));
function MyComponent() {
return (
<React.Suspense fallback={<div>Loading...</div>}>
<OtherComponent />
</React.Suspense>
);
}
Lazy Loading
์ค๋ช
Lazy Loading์ ์ฌ์ฉ์๊ฐ ์คํฌ๋กคํ ๋ ์ฝํ ์ธ ๋ฅผ ๋ก๋ํ์ฌ ์ด๊ธฐ ๋ก๋ฉ ์๊ฐ์ ๋จ์ถ์ํค๋ ๊ธฐ๋ฒ์ ๋๋ค.
์ต์ ํ ๋ฐฉ๋ฒ
- ์ด๋ฏธ์ง Lazy Loading: HTML5์ loading ์์ฑ์ ์ฌ์ฉํด ์ด๋ฏธ์ง์ Lazy Loading ๊ตฌํ.
<img src="image.jpg" loading="lazy" alt="Example Image">
- Intersection Observer API ์ฌ์ฉ: ๋น๋๊ธฐ์ ์ผ๋ก ์์๋ฅผ ๊ด์ฐฐํ๊ณ ๋ก๋.
const imgObserver = new IntersectionObserver((entries, observer) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const img = entry.target;
img.src = img.dataset.src;
observer.unobserve(img);
}
});
});
document.querySelectorAll('img[data-src]').forEach(img => {
imgObserver.observe(img);
});
์ฝํ ์ธ ์ ์ก ๋คํธ์ํฌ(CDN) ์ฌ์ฉ
์ค๋ช
CDN์ ์ ์ธ๊ณ์ ๋ถ์ฐ๋ ์๋ฒ๋ฅผ ํตํด ์ฌ์ฉ์๊ฐ ๋ ๋น ๋ฅด๊ฒ ์ฝํ ์ธ ๋ฅผ ๋ฐ์๋ณผ ์ ์๊ฒ ํด์ค๋๋ค.
์ต์ ํ ๋ฐฉ๋ฒ
- CDN ์ ๊ณต ์ ์ฒด ์ ํ: Cloudflare, Akamai, Amazon CloudFront ๋ฑ์ ์๋น์ค๋ฅผ ํ์ฉ.
- ์ ์ ์์ฐ ๋ฐฐํฌ: ์ด๋ฏธ์ง, CSS, JavaScript ํ์ผ์ CDN์ ํธ์คํ .
<link rel="stylesheet" href="https://cdn.example.com/style.css">
<script src="https://cdn.example.com/script.js"></script>
๋ธ๋ผ์ฐ์ ์บ์ฑ
์ค๋ช
๋ธ๋ผ์ฐ์ ์บ์ฑ์ ๋ฐฉ๋ฌธ์๊ฐ ๋์ผํ ๋ฆฌ์์ค๋ฅผ ์ฌ๋ฐฉ๋ฌธํ ๋ ์๋ฒ ์์ฒญ ์์ด ์บ์๋ ๋ฆฌ์์ค๋ฅผ ์ฌ์ฉํ๋๋ก ํฉ๋๋ค.
์ต์ ํ ๋ฐฉ๋ฒ
- ์บ์ ์ ์ด ํค๋ ์ค์ : ์๋ฒ์์ Cache-Control ํค๋๋ฅผ ์ค์ ํด ์บ์ฑ ๋์ ์ ์ด.
Cache-Control: public, max-age=31536000
- ETag ์ฌ์ฉ: ๋ฆฌ์์ค๊ฐ ๋ณ๊ฒฝ๋์๋์ง ํ์ธํ๋ ํ๊ทธ๋ฅผ ์ค์ .
ETag: "12345"
JavaScript ๋ฐ CSS ์ถ์
์ค๋ช
JavaScript์ CSS ํ์ผ์ ์ถ์ํ๋ฉด ํ์ผ ํฌ๊ธฐ๋ฅผ ์ค์ด๊ณ ๋ก๋ฉ ์๋๋ฅผ ํฅ์์ํฌ ์ ์์ต๋๋ค.
์ต์ ํ ๋ฐฉ๋ฒ
- ๋๊ตฌ ์ฌ์ฉ: Terser, UglifyJS, CSSNano์ ๊ฐ์ ๋๊ตฌ๋ฅผ ์ฌ์ฉํด ์ฝ๋ ์ถ์.
npx terser script.js -o script.min.js
npx cssnano style.css -o style.min.css
- Webpack ์ค์ : Webpack์ mode๋ฅผ production์ผ๋ก ์ค์ ํด ์๋์ผ๋ก ์ถ์.
module.exports = {
mode: 'production',
// other configurations
};
๋น๋๊ธฐ์ ์๋ฐ์คํฌ๋ฆฝํธ ๋ก๋ฉ
์ค๋ช
๋น๋๊ธฐ์ ์๋ฐ์คํฌ๋ฆฝํธ ๋ก๋ฉ์ ํตํด HTML ํ์ฑ์ ๋ง์ง ์๊ณ ์๋ฐ์คํฌ๋ฆฝํธ๋ฅผ ๋ก๋ํ ์ ์์ต๋๋ค.
์ต์ ํ ๋ฐฉ๋ฒ
- async ์์ฑ ์ฌ์ฉ: ์ธ๋ถ ์คํฌ๋ฆฝํธ๋ฅผ ๋น๋๊ธฐ์ ์ผ๋ก ๋ก๋.
<script src="script.js" async></script>
- defer ์์ฑ ์ฌ์ฉ: HTML ํ์ฑ์ด ์๋ฃ๋ ํ์ ์คํฌ๋ฆฝํธ๋ฅผ ์คํ.
<script src="script.js" defer></script>
HTTP/2 ์ฌ์ฉ
์ค๋ช
HTTP/2๋ ์ฌ๋ฌ ๊ฐ์ ์์ฒญ์ ๋์์ ์ฒ๋ฆฌํ ์ ์์ด ์น ํ์ด์ง ๋ก๋ฉ ์๋๋ฅผ ๊ฐ์ ํฉ๋๋ค.
์ต์ ํ ๋ฐฉ๋ฒ
- ์๋ฒ ์ค์ : ์๋ฒ๊ฐ HTTP/2๋ฅผ ์ง์ํ๋๋ก ์ค์ .
- SSL ์ธ์ฆ์ ์ ์ฉ: HTTP/2๋ SSL์ ํ์๋ก ํ๋ฏ๋ก, SSL ์ธ์ฆ์๋ฅผ ์ ์ฉ.
ํฌ๋ฆฌํฐ์ปฌ ๋ ๋๋ง ํจ์ค ์ต์ ํ
์ค๋ช
ํฌ๋ฆฌํฐ์ปฌ ๋ ๋๋ง ํจ์ค๋ ๋ธ๋ผ์ฐ์ ๊ฐ ์น ํ์ด์ง๋ฅผ ๋ ๋๋งํ๋ ๋ฐ ํ์ํ ๋ฆฌ์์ค๋ฅผ ์ต์ ํํ๋ ๊ธฐ๋ฒ์ ๋๋ค.
์ต์ ํ ๋ฐฉ๋ฒ
- CSS ์ธ๋ผ์ธ: ํฌ๋ฆฌํฐ์ปฌ CSS๋ฅผ ์ธ๋ผ์ธ์ผ๋ก ํฌํจํด ์ฒซ ๋ฒ์งธ ํ์ธํธ ์๊ฐ์ ๋จ์ถ.
<style>
/* Critical CSS */
body { margin: 0; padding: 0; }
</style>
- ๋นํฌ๋ฆฌํฐ์ปฌ CSS ์ง์ฐ ๋ก๋: ๋นํฌ๋ฆฌํฐ์ปฌ CSS๋ฅผ ๋น๋๊ธฐ์ ์ผ๋ก ๋ก๋.
<link rel="stylesheet" href="styles.css" media="print" onload="this.media='all'">
์๋ฒ ๋ฐ์ ์๊ฐ ์ต์ ํ
์ค๋ช
์๋ฒ ๋ฐ์ ์๊ฐ(TTFB, Time to First Byte)์ ์ฌ์ฉ์๊ฐ ์์ฒญ์ ๋ณด๋ด๊ณ ์ฒซ ๋ฒ์งธ ๋ฐ์ดํธ๋ฅผ ๋ฐ์ ๋๊น์ง์ ์๊ฐ์ ๋ํ๋ ๋๋ค.
์ต์ ํ ๋ฐฉ๋ฒ
- ์๋ฒ ์ต์ ํ: ์๋ฒ์ ํ๋์จ์ด์ ์ํํธ์จ์ด ์ฑ๋ฅ์ ์ต์ ํ.
- ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ต์ ํ: ์ฟผ๋ฆฌ ์ต์ ํ์ ์ธ๋ฑ์ฑ์ ํตํด ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ฑ๋ฅ ํฅ์.
- ์บ์ฑ: ์๋ฒ ์ธก ์บ์ฑ์ ํตํด ์์ฃผ ์์ฒญ๋๋ ๋ฐ์ดํฐ๋ฅผ ์บ์.
๋๊ธ