๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
Develop

์›น ์„ฑ๋Šฅ ์ตœ์ ํ™”๋ฅผ ์œ„ํ•œ 10๊ฐ€์ง€ ํ•„์ˆ˜ ๊ธฐ๋ฒ•

by _mingle 2024. 7. 2.
728x90

์ด๋ฏธ์ง€ ์ตœ์ ํ™”

์„ค๋ช…

์ด๋ฏธ์ง€๋Š” ์›น ํŽ˜์ด์ง€์—์„œ ํฐ ๋ถ€๋ถ„์„ ์ฐจ์ง€ํ•˜๋ฉฐ, ์ตœ์ ํ™”๋˜์ง€ ์•Š์€ ์ด๋ฏธ์ง€๋Š” ๋กœ๋”ฉ ์‹œ๊ฐ„์„ ์ง€์—ฐ์‹œํ‚ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ตœ์ ํ™” ๋ฐฉ๋ฒ•

  • ์ ์ ˆํ•œ ํ˜•์‹ ์„ ํƒ: 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)์€ ์‚ฌ์šฉ์ž๊ฐ€ ์š”์ฒญ์„ ๋ณด๋‚ด๊ณ  ์ฒซ ๋ฒˆ์งธ ๋ฐ”์ดํŠธ๋ฅผ ๋ฐ›์„ ๋•Œ๊นŒ์ง€์˜ ์‹œ๊ฐ„์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.

์ตœ์ ํ™” ๋ฐฉ๋ฒ•

  • ์„œ๋ฒ„ ์ตœ์ ํ™”: ์„œ๋ฒ„์˜ ํ•˜๋“œ์›จ์–ด์™€ ์†Œํ”„ํŠธ์›จ์–ด ์„ฑ๋Šฅ์„ ์ตœ์ ํ™”.
  • ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ตœ์ ํ™”: ์ฟผ๋ฆฌ ์ตœ์ ํ™”์™€ ์ธ๋ฑ์‹ฑ์„ ํ†ตํ•ด ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์„ฑ๋Šฅ ํ–ฅ์ƒ.
  • ์บ์‹ฑ: ์„œ๋ฒ„ ์ธก ์บ์‹ฑ์„ ํ†ตํ•ด ์ž์ฃผ ์š”์ฒญ๋˜๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ์บ์‹œ.

 

 

 

728x90
๋ฐ˜์‘ํ˜•

๋Œ“๊ธ€