๐Ÿ“ FE ์„ฑ๋Šฅ ์ตœ์ ํ™” ์ •๋ฆฌ

๊ถŒ๊ทœ๋ฆฌยท2024๋…„ 1์›” 22์ผ
1

๐Ÿ‘ฉ๐Ÿปโ€๐Ÿ’ปFrontEnd

๋ชฉ๋ก ๋ณด๊ธฐ
3/29
post-thumbnail

๐Ÿ“Œ์—ฌ๋Š” ๋ง

๊ตฌ๊ธ€์˜ ์กฐ์‚ฌ์— ์˜ํ•˜๋ฉด ํŽ˜์ด์ง€๊ฐ€ 3์ดˆ ์•ˆ์— ๋กœ๋”ฉ๋˜์ง€ ์•Š๋Š”๋‹ค๋ฉด 53% ์‚ฌ์šฉ์ž๊ฐ€ ๋– ๋‚˜๊ณ , ๋กœ๋”ฉ ์‹œ๊ฐ„์ด ๊ธธ์–ด์งˆ์ˆ˜๋ก ์ดํƒˆ๋ฅ ์ด ๋Š˜์–ด๋‚œ๋‹ค๊ณ  ํ•˜๋ฉฐ ์ด๋ฅผ 3์ดˆ ๋ฒ•์น™์ด๋ผ๊ณ  ํ•œ๋‹ค. ์ด๋ ‡๊ฒŒ ์ฒซ ์ธ์ƒ(?)์ด ์ค‘์š”ํ•œ ๊ฒƒ ๊ฐ™๋‹ค. ์›นํŽ˜์ด์ง€์˜ ์ฒซ ์ธ์ƒ์ด ์ข‹์œผ๋ ค๋ฉด ์„ฑ๋Šฅ์„ ์ข‹๊ฒŒ ์œ ์ง€ํ•˜๋Š” ์ˆ˜ ๋ฐ–์— ๐Ÿ”ฅ

1์žฅ. ์›น ์„ฑ๋Šฅ ์ตœ์ ํ™” ์ข…๋ฅ˜

์›น์˜ ์„ฑ๋Šฅ์„ ์ตœ์ ํ™”ํ•  ์ˆ˜ ์žˆ๋Š” ๋ถ€๋ถ„์€ ํฌ๊ฒŒ 2๊ฐ€์ง€๋กœ ๋‚˜๋ˆŒ ์ˆ˜ ์žˆ๋‹ค.

๐Ÿ“ ๋กœ๋”ฉ ์„ฑ๋Šฅ ์ตœ์ ํ™”

  • ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ๋ฆฌ์†Œ์Šค๋ฅผ ๋ถˆ๋Ÿฌ์˜ค๋Š” ์„ฑ๋Šฅ์„ ๋†’์ด๋Š” ๋ฐฉ๋ฒ•

๐Ÿ“ ๋ Œ๋”๋ง ์„ฑ๋Šฅ ์ตœ์ ํ™”

  • ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ํ™”๋ฉด์— ๊ทธ๋ ค์ฃผ๋Š” ์„ฑ๋Šฅ์„ ๋†’์ด๋Š” ๋ฐฉ๋ฒ•

์ด๋ ‡๊ฒŒ ์„ค๋ช…์œผ๋กœ๋งŒ ๋ด์„œ๋Š” ๋กœ๋”ฉ ์„ฑ๋Šฅ ์ตœ์ ํ™”๊ฐ€ ๋ฌด์—‡์ธ์ง€, ๋ Œ๋”๋ง ์„ฑ๋Šฅ ์ตœ์ ํ™”๊ฐ€ ๋ฌด์—‡์ธ์ง€ ์ž˜ ๊ฐ์ด ์•ˆ ์˜จ๋‹ค. ๊ฐ๊ฐ ์ตœ์ ํ™”๋ฅผ ํ•˜๋Š” ๋ฐ์— ์–ด๋–ค ๋ฐฉ๋ฒ•์ด ์žˆ๋Š”์ง€ ์•Œ์•„๋ณด์ž๊ตฌ์š” ~๐Ÿ’ก


2์žฅ. ๋กœ๋”ฉ ์„ฑ๋Šฅ ์ตœ์ ํ™” ๐Ÿƒ๐Ÿป

(1) ๐Ÿงฉ Block Resource ์ตœ์ ํ™”

๋ธŒ๋ผ์šฐ์ €๊ฐ€ ์ƒ๋‹จ๋ถ€ํ„ฐ ์ฐจ๋ก€๋Œ€๋กœ ๋‚ด๋ ค๊ฐ€๋ฉฐ ๋กœ๋“œ๋œ๋‹ค. ๋ธŒ๋ผ์šฐ์ € ๋กœ๋“œ ์‹œ, HTML๊ณผ CSS์ด ๋™์‹œ์— ํŒŒ์‹ฑ๋˜๋Š”๋ฐ ์ด๋•Œ Script ํŒŒ์ผ์„ ๋งŒ๋‚œ๋‹ค๋ฉด HTML๊ณผ CSS ํŒŒ์‹ฑ์„ ๋ฉˆ์ถ”๊ณ , JS ํŒŒ์‹ฑ์„ ์‹œ์ž‘ํ•œ๋‹ค. ์ด์ฒ˜๋Ÿผ HTML ํŒŒ์‹ฑ์„ ์ฐจ๋‹จํ•˜๋Š” ์š”์†Œ๋ฅผ Block Resource(๋ธ”๋ก ์ฐจ๋‹จ ๋ฆฌ์†Œ์Šค)๋ผ๊ณ  ํ•œ๋‹ค.

๊ทธ๋Ÿฐ๋ฐ Block Resource๊ฐ€ ์™œ ๋กœ๋”ฉ ์„ฑ๋Šฅ๊ณผ ๊ด€๋ จ ์žˆ์ฃ ? ๐Ÿค”

๊ทธ๋ƒฅ JS ํŒŒ์‹ฑ ํ•˜๊ณ  HTML ๋‹ค์‹œ ํŒŒ์‹ฑํ•˜๋ฉด ๋˜๋Š”๊ฑฐ ์•„๋‹Œ๊ฐ€?

  • HTML์€ Script ํƒœ๊ทธ๋ฅผ ๋งŒ๋‚˜๋ฉด DOM ์ƒ์„ฑ์„ ์ค‘์ง€ํ•˜๊ณ  JS ์—”์ง„์—๊ฒŒ ์ œ์–ด ๊ถŒํ•œ์„ ๋„˜๊ธด๋‹ค. JS ์—”์ง„์˜ ์‹คํ–‰์ด ์™„๋ฃŒ๋œ ํ›„ ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ์ค‘์ง€ํ–ˆ๋˜ DOM ์ƒ์„ฑ์„ ๋‹ค์‹œ ํ•œ๋‹ค! ์ด๋ ‡๊ฒŒ ์ธ๋ผ์ธ Script๋ฅผ ์‹คํ–‰ํ•˜๋ฉด DOM ์ƒ์„ฑ์ด ์ฐจ๋‹จ๋˜๊ณ , ์ด๋กœ ์ธํ•ด ์ดˆ๊ธฐ ๋ Œ๋”๋ง์ด ์ง€์—ฐ๋œ๋‹ค. ์ฆ‰, Block Resource๋Š” ๋ Œ๋”๋ง ์ฐจ๋‹จ ์š”์‡ผ์ด๊ธฐ ๋•Œ๋ฌธ์— ์˜ฌ๋ฐ”๋ฅธ ์œ„์น˜์—์„œ ์‹คํ–‰ ๋˜์–ด์•ผ ํ•œ๋‹ค.

๐Ÿงฉ Block Resource ์ตœ์ ํ™” ๋ฐฉ๋ฒ•์„ ์†Œ๊ฐœํ•˜์ง€!

โญ๋ฐฉ๋ฒ• 1โญ CSS๋Š” head ํƒœ๊ทธ ๋‚ด์—์„œ, JS๋Š” body ํƒœ๊ทธ ๋‚ด์—์„œ import ํ•˜๊ธฐ

  • HTML๊ณผ CSS๋Š” ์šฐ๋ฆฌ๊ฐ€ ๋ณด๋Š” ์‹œ๊ฐ์ ์ธ ๋ถ€๋ถ„์„ ๊ตฌํ˜„ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋ธŒ๋ผ์šฐ์ € ๋กœ๋“œ ์‹œ, ๋น ๋ฅด๊ฒŒ ๊ทธ๋ ค์งˆ์ˆ˜๋ก ์ข‹๋‹ค. ๋”ฐ๋ผ์„œ CSS๋Š” head ๋‚ด์—์„œ import ํ•œ๋‹ค.

  • ๋ธŒ๋ผ์šฐ์ €๋Š” HTML, CSS๋ฅผ ํŒŒ์‹ฑํ•˜๊ณ  ์žˆ์–ด๋„ Script ํƒœ๊ทธ๋ฅผ ๋งŒ๋‚˜๋ฉด ํŒŒ์‹ฑ์„ ์ค‘์ง€ํ•˜๊ธฐ ๋•Œ๋ฌธ์—, HTML๊ณผ CSS์˜ ๋กœ๋“œ๊ฐ€ ๋๋‚˜๊ณ  Script๊ฐ€ ๋“ค์–ด์˜ค๋Š” ๊ตฌ์กฐ๋กœ ํ•˜๋Š”๊ฒŒ ์ข‹๋‹ค. ๋”ฐ๋ผ์„œ Script ํƒœ๊ทธ๋กœ ์‹คํ–‰๋˜๋Š” JS๋Š” ์ผ๋ฐ˜์ ์œผ๋กœ body ํƒœ๊ทธ๋ฅผ ๋‹ซ๊ธฐ ์ „ ๋งจ ํ•˜๋‹จ์— ์œ„์น˜์‹œํ‚จ๋‹ค.

โญ๋ฐฉ๋ฒ• 2โญ CSS- media attribute

media attribute์€ ๋‹จ๋ง๊ธฐ ์œ ํ˜•์— ๋”ฐ๋ผ ์กฐ๊ฑด๋ณ„๋กœ CSS ๋ถˆ๋Ÿฌ์™€์„œ, ๋ถˆํ•„์š”ํ•œ ๋ธ”๋กœํ‚น์„ ๋ฐฉ์ง€ํ•  ์ˆ˜ ์žˆ๋‹ค.

<link href="style.css" rel="stylesheet" />
<link href="print.css" rel="stylesheet" media="print" />
<link href="mobile.css" rel="stylesheet" media="width:790px" />

โญ๋ฐฉ๋ฒ• 3โญ JS- async/defer

async์™€ defer ์†์„ฑ์€ Script ํŒŒ์ผ์„ ๋น„๋™๊ธฐ๋กœ ๋‹ค์šด๋กœ๋“œ ํ•˜๊ฒŒ ํ•ด์ค€๋‹ค. ์ฆ‰, HTML ํŒŒ์‹ฑ ์ค‘์— Script๋ฅผ ๋งŒ๋‚˜๋„ ํŒŒ์‹ฑ์„ ๋ฉˆ์ถ”์ง€ ์•Š๊ณ  Script๋ฅผ ๋‹ค์šด๋กœ๋“œ ํ•  ์ˆ˜ ์žˆ๋‹ค.

๐ŸŒž async

HTML ํŒŒ์‹ฑ๋™์•ˆ Script๋„ ๊ฐ™์ด ๋‹ค์šด๋กœ๋“œ ๋œ๋‹ค. Script๋Š” ๋‹ค์šด๋กœ๋“œ ํ›„ ์ฆ‰์‹œ ์‹คํ–‰๋˜๋ฉฐ, HTML์€ ์‹คํ–‰๋˜๋Š” ๋™์•ˆ ์ค‘์ง€๋˜์—ˆ๋‹ค๊ฐ€ ์‹คํ–‰์ด ๋๋‚˜๋ฉด ๋‹ค์‹œ ํŒŒ์‹ฑ๋œ๋‹ค.

ํ•˜์ง€๋งŒ asynk Script๋Š” ๋‹ค์šด๋กœ๋“œ๋ฅผ ๋งˆ์น˜๋ฉด ์ฆ‰์‹œ HTML ํŒŒ์‹ฑ์„ ๋ฉˆ์ถ”๊ณ  Script ํŒŒ์ผ์„ ํ•ด์„ํ•œ๋‹ค. ๋•Œ๋ฌธ์— asynk ์†์„ฑ์œผ๋กœ ํŒŒ์ผ์„ ๋ถˆ๋Ÿฌ์˜จ๋‹ค๊ณ  ํ•ด๋„, ์Šคํฌ๋ฆฝํŠธ์˜ ํ•ด์„์ด ์–ผ๋งˆ๋‚˜ ์˜ค๋ž˜ ๊ฑธ๋ฆด์ง€ ๋ชจ๋ฅธ๋‹ค. ๋”ฐ๋ผ์„œ asynk ์Šคํฌ๋ฆฝํŠธ๋Š” ์‹คํ–‰ ์ˆœ์„œ๊ฐ€ ๋ณด์žฅ๋˜์ง€ ์•Š๋Š”๋‹ค.

<!-- large.js ๋Š” ๋กœ๋“œ๋˜๋Š”๋ฐ 5์ดˆ๊ฐ€ ๊ฑธ๋ฆฝ๋‹ˆ๋‹ค -->
<script src="large.js" async></script>

<!-- small.js ๋Š” ๋กœ๋“œ๋˜๋Š”๋ฐ 1์ดˆ๊ฐ€ ๊ฑธ๋ฆฝ๋‹ˆ๋‹ค -->
<script src="small.js" async></script>

์›๋ž˜๋Š” ์ˆœ์„œ์— ๋”ฐ๋ผ large.js๊ฐ€ ๋จผ์ € ์‹คํ–‰๋˜์–ด์•ผ ํ•˜์ง€๋งŒ, ๋จผ์ € ๋กœ๋“œ ๋˜๋Š” ์Šคํฌ๋ฆฝํŠธ์ธ small.js๊ฐ€ ์‹คํ–‰๋˜๋ฏ€๋กœ ์Šคํฌ๋ฆฝํŠธ์˜ ์ˆœ์„œ๊ฐ€ ๋ณด์žฅ๋˜์ง€ ์•Š๋Š”๋‹ค !!!

๐ŸŒž defer

HTML ํŒŒ์‹ฑ๋™์•ˆ Script๋„ ๊ฐ™์ด ๋‹ค์šด๋กœ๋“œ ๋œ๋‹ค. Script๋Š” ๋‹ค์šด๋กœ๋“œ ํ›„ ์ฆ‰์‹œ ์‹คํ–‰๋˜๋Š” asynk Script์™€๋Š” ๋‹ค๋ฅด๊ฒŒ, ๋ชจ๋“  DOM์ด ๋กœ๋“œ๋œ ํ›„์— ์‹คํ–‰๋œ๋‹ค.

<!-- large.js ๋Š” ๋กœ๋“œ๋˜๋Š”๋ฐ 5์ดˆ๊ฐ€ ๊ฑธ๋ฆฝ๋‹ˆ๋‹ค -->
<script src="large.js" async></script>

<!-- small.js ๋Š” ๋กœ๋“œ๋˜๋Š”๋ฐ 1์ดˆ๊ฐ€ ๊ฑธ๋ฆฝ๋‹ˆ๋‹ค -->
<script src="small.js" async></script>

defer Script๋Š” ๋กœ๋“œ๊ฐ€ ๋” ๋นจ๋ฆฌ๋œ Script๊ฐ€ ์žˆ๋”๋ผ๋„, ํ•ญ์ƒ ์ˆœ์„œ์— ๋”ฐ๋ผ์„œ ์‹คํ–‰๋˜๋ฏ€๋กœ ์ˆœ์„œ๊ฐ€ ๋ณด์žฅ๋œ๋‹ค.


(2) ๐Ÿงฉ Image ์ตœ์ ํ™”

โญ๋ฐฉ๋ฒ• 1โญ picture ํƒœ๊ทธ์˜ type ์†์„ฑ ์‚ฌ์šฉ

picture ํƒœ๊ทธ๋Š” img ํƒœ๊ทธ์— ๋Œ€ํ•ด ์—ฌ๋Ÿฌ๊ฐœ์˜ ๋ฐ˜์‘ํ˜• ์ด๋ฏธ์ง€๋ฅผ ์ œ๊ณตํ•˜๋Š” source ํƒœ๊ทธ๊ฐ€ ํฌํ•จ๋œ ๋ถ€๋ชจ ์š”์†Œ์ด๋‹ค. picture ํƒœ๊ทธ๋Š” source ํƒœ๊ทธ๋ฅผ ์ด์šฉํ•œ ๋ฐ˜์‘ํ˜• ์ด๋ฏธ์ง€๋ฅผ ์‚ฌ์šฉํ•จ์œผ๋กœ์จ ๋Œ€์—ญํญ์„ ์ ˆ์•ฝํ•˜๊ณ  ํŽ˜์ด์ง€ ๋กœ๋“œ ์‹œ๊ฐ„ ๋‹จ์ถ•์„ ์œ„ํ•ด ์“ฐ์ธ๋‹ค.

<picture>
    <source srcset="small.jpg" media="(max-width: 768px)">
    <source srcset="large.jpg" media="(min-width: 769px)">
    <img src="fallback-image.jpg" alt="image">
</picture>

๐Ÿ“Œ picture ํƒœ๊ทธ ์‚ฌ์šฉ ์‹œ ์ฃผ์˜์‚ฌํ•ญ

  • source ํƒœ๊ทธ ๋˜๋Š” img ํƒœ๊ทธ ๋‘˜ ์ค‘ ํ•˜๋‚˜๋Š” ์žˆ์–ด์•ผ ํ•œ๋‹ค.

  • source ํƒœ๊ทธ, img ํƒœ๊ทธ ๋‘˜ ๋‹ค ์žˆ์„ ๊ฒฝ์šฐ, img ํƒœ๊ทธ๊ฐ€ ๋‚˜์ค‘์— ์œ„์น˜ํ•ด์•ผ ํ•œ๋‹ค. => source ํƒœ๊ทธ ์ค‘ ์–ด๋Š ๊ฒƒ๋„ ๋ฐ˜์‘ํ˜•์œผ๋กœ ์ œ๊ณตํ•  ์ˆ˜ ์—†๋Š” ๊ฒฝ์šฐ img ํƒœ๊ทธ์˜ ์ด๋ฏธ์ง€ ์ œ๊ณต!

  • img ํƒœ๊ทธ๋ฅผ ์‚ญ์ œํ•  ๊ฒฝ์šฐ, alt ์†์„ฑ์ด ์—†์œผ๋ฏ€๋กœ ์›น ์ ‘๊ทผ์„ฑ์ด ๋–จ์–ด์ง€๋ฉฐ source ํƒœ๊ทธ ์ค‘ ์ œ๊ณตํ•  ์ด๋ฏธ์ง€๊ฐ€ ์—†๋‹ค๋ฉด fallback ์ด๋ฏธ์ง€๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๋‹ค.

โญ๋ฐฉ๋ฒ• 2โญ image ์ง€์—ฐ ๋กœ๋”ฉ


์‡ผํ•‘๋ชฐ ์›น ํŽ˜์ด์ง€์ฒ˜๋Ÿผ ์ด๋ฏธ์ง€๊ฐ€ ๋งŽ์ด ํ•„์š”ํ•œ ์„œ๋น„์Šค์—์„œ ์‚ฌ์šฉ์ž ์ฒซ ํ™”๋ฉด์— ๋ณด์ด๋Š” ์ด๋ฏธ์ง€๋งŒ ์š”์ฒญํ•˜๊ณ , ์‚ฌ์šฉ์ž๊ฐ€ ์Šคํฌ๋กค์„ ํ†ตํ•ด ๋‚ด๋ ค์•ผ ๋ณด์ด๋Š” ์ด๋ฏธ์ง€๋Š” ์ง€์—ฐ ๋กœ๋”ฉ์„ ํ†ตํ•ด ๋ฆฌ์†Œ์Šค ์š”์ฒญ์„ ์ค„์ผ ์ˆ˜ ์žˆ๋‹ค.

<!-- auto๋Š” default ๊ฐ’์œผ๋กœ, loading ์†์„ฑ์„ ์•ˆ ์“ด ๊ฒƒ๊ณผ ๊ฐ™์Œ -->
 <img src="image.jpg" loading="auto" alt>

<!-- lazy๋Š” ์‚ฌ์šฉ์ž๊ฐ€ ๋ณด์ด๋Š” ๋ถ€๋ถ„๋งŒ ๋จผ์ € ์ถœ๋ ฅํ•˜๊ณ , ๋ณด์ด์ง€ ์•Š๋Š” ๋ถ€๋ถ„์€ ์‚ฌ์šฉ์ž๊ฐ€ ์Šคํฌ๋กค ์‹œ ์ถœ๋ ฅ๋จ -->
 <img src="image.jpg" loading="lazy" alt>

<!-- eager์€ ๋ณด์ด๋“ , ์•ˆ ๋ณด์ด๋“  ์ด๋ฏธ์ง€๋ฅผ ๋กœ๋“œํ•œ๋‹ค.-->
 <img src="image.jpg" loading="eager" alt>

โญ๋ฐฉ๋ฒ• 3โญ ์Šคํ”„๋ผ์ดํŠธ ์ด๋ฏธ์ง€

์Šคํ”„๋ผ์ดํŠธ ์ด๋ฏธ์ง€๋ž€, ์—ฌ๋Ÿฌ๊ฐœ์˜ ์ด๋ฏธ์ง€๋ฅผ ํ•˜๋‚˜์˜ ์ด๋ฏธ์ง€๋กœ ํ•ฉ์ณ ๊ด€๋ฆฌํ•˜๋Š” ์ด๋ฏธ์ง€์ด๋‹ค. ์ด๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์ด๋ฏธ์ง€๋ฅผ ๋‹ค์šด๋ฐ›๊ธฐ ์œ„ํ•œ ์„œ๋ฒ„ ์š”์ฒญ์„ ์ค„์ผ ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์›น ํŽ˜์ด์ง€์˜ ๋กœ๋”ฉ ์‹œ๊ฐ„์„ ์ค„์ผ ์ˆ˜ ์žˆ๋‹ค.

โญ๋ฐฉ๋ฒ• 4โญ .jpg, .png๋ฅผ webp์œผ๋กœ ๋ณ€ํ™˜

์ด๋ฏธ์ง€ ํ˜•์‹์„ webp์œผ๋กœ ๋ณ€ํ™˜ํ•˜๋ฉด .jpg, .png๋ณด๋‹ค ํŒŒ์ผ์˜ ํฌ๊ธฐ๋ฅผ ์ตœ์†Œ 25~30% ์ค„์ผ ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์••์ถ•์—๋„ ์šฉ์ดํ•˜๋‹ค. ๋”ฐ๋ผ์„œ ๊ธฐ์กด ์ด๋ฏธ์ง€ ํ˜•์‹์— ๋น„ํ•ด ๋กœ๋“œ ์†๋„๊ฐ€ ๋” ๋น ๋ฅด๋‹ค.


(3) ๐Ÿงฉ Webpack

๋ชจ๋“ˆ ๋ฒˆ๋“ค๋Ÿฌ ์›นํŒฉ(Webpack)์„ ์‚ฌ์šฉํ•ด์„œ css์™€ js ๋ชจ๋“ˆ์„ ํ•˜๋‚˜์˜ ํŒŒ์ผ๋กœ ๋ณ‘ํ•ฉํ•˜๋Š” ๋ชจ๋“ˆ ๋ฒˆ๋“ค๋ง์„ ํ†ตํ•ด ๋ฆฌ์†Œ์Šค ์š”์ฒญ์„ ์ค„์ผ ์ˆ˜ ์žˆ๋‹ค.

๐Ÿ“Œ Before- ๋ฒˆ๋“ค๋ง ์ „

  <head>
    <link href="main.css" rel="stylesheet">
    <link href="sub.css" rel="stylesheet">
  </head>
  <body>
	...
    <script async src="main.js" type="text/javascript"></script>
    <script async src="sub.js" type="text/javascript"></script>
  </body>

๐Ÿ“Œ After- ๋ฒˆ๋“ค๋ง ํ›„

  <head>
    <link href="budle.css" rel="stylesheet">
  </head>
  <body>
	...
    <script async src="bundle.js" type="text/javascript"></script>
  </body>

3์žฅ. ๋ Œ๋”๋ง ์„ฑ๋Šฅ ์ตœ์ ํ™” ๐Ÿƒ

(1) ๐Ÿงฉ HTML ์ตœ์ ํ™”

โญ๋ฐฉ๋ฒ• 1โญ inline style ์‚ฌ์šฉ ๊ธˆ์ง€

HTML ์š”์†Œ์— style์„ ์ž‘์„ฑํ•˜๋ฉด Reflow๋ฅผ ๊ณ„์† ๋ฐœ์ƒ์‹œ์ผœ ๋ Œ๋”๋ง ์™„๋ฃŒ ์‹œ์ ์„ ๋Šฆ์ถ˜๋‹ค.

<div style="margin: 10px;"></div> 

โญ๋ฐฉ๋ฒ• 2โญ DOM ํŠธ๋ฆฌ ๊ฐ„๋‹จํ•˜๊ฒŒ!

DOM ํŠธ๋ฆฌ๋Š” ๊ฐ€๋ฒผ์›Œ์•ผ ๊ณ„์‚ฐ์ด ๋น ๋ฅด๋‹ค. ๋ถˆํ•„์š”ํ•œ div, wrap๋Š” ์‚ญ์ œํ•ด์ค˜์•ผ ํ•œ๋‹ค.


(2) ๐Ÿงฉ CSS ์ตœ์ ํ™”

โญ๋ฐฉ๋ฒ• 1โญ Reflow, Repaint ๊ณ ๋ ค

๐ŸŒž Reflow
๋ Œ๋”๋ง ์—”์ง„์— ์˜ํ•ด์„œ ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ๊ทธ๋ ค์งˆ ๋•Œ, Layout(reflow) ๋‹จ๊ณ„๊ฐ€ ์žˆ๋‹ค. ์ด ๋‹จ๊ณ„์—์„œ ๋ธŒ๋ผ์šฐ์ €๋Š” ํ™”๋ฉด ์ „์ฒด์˜ ํฌ๊ธฐ๋‚˜ ์Šคํฌ๋กค ์œ„์น˜ ๋“ฑ์˜ ์š”์†Œ๋ฅผ ๊ณ ๋ คํ•œ๋‹ค.

๋”ฐ๋ผ์„œ ํ™”๋ฉด์˜ ๋„ˆ๋น„, ๋†’์ด, ์œ„์น˜ ๋“ฑ์— ์˜ํ–ฅ์„ ์ฃผ๋Š” CSS ์†์„ฑ์„ ๋ณ€๊ฒฝํ•˜๋Š” ๊ฒฝ์šฐ, Layout ๋‹จ๊ณ„๋ถ€ํ„ฐ ๋‹ค์‹œ ๊ทธ๋ ค์ง€๊ฒŒ ๋œ๋‹ค. ์ด ๋‹จ๊ณ„๋ฅผ Refolw๋ผ๊ณ  ํ•œ๋‹ค.

  • Reflow ๋ฐœ์ƒ ์š”์†Œ
    position, width, height, margin, padding , display , top, left, right, bottom, box-sizing, border-color, text-align, border, border-width, font-family, float, font-size, font-weight, line-height, vertical-align ...

๐ŸŒž Repaint
Paint ๋‹จ๊ณ„๋Š” Layout ๋‹จ๊ณ„๋ฅผ ํ†ตํ•ด ํ™”๋ฉด์— ๋ฐฐ์น˜๋œ ์š”์†Œ๋“ค์—๊ฒŒ ์ƒ‰์„ ์ž…ํžˆ๋Š” ๋‹จ๊ณ„์ด๋‹ค. ๋ ˆ์ด์•„์›ƒ์— ์˜ํ–ฅ์„ ์ฃผ์ง€ ์•Š๋Š” ์†์„ฑ์„ ๋ณ€๊ฒฝํ•˜๋ฉด Layout ๋‹จ๊ณ„๋ฅผ ์Šคํ‚ตํ•˜๊ณ  Paint ๋‹จ๊ณ„๋ถ€ํ„ฐ ๋‹ค์‹œ ์ˆ˜ํ–‰ํ•˜๊ฒŒ ๋œ๋‹ค. ์ด ๋‹จ๊ณ„๋ฅผ Repaint๋ผ๊ณ  ํ•œ๋‹ค.

๋”ฐ๋ผ์„œ Reflow๊ฐ€ ์ผ์–ด๋‚˜๋ฉด ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ์ „์ฒด ํ”ฝ์…€์„ ๋‹ค์‹œ ๊ณ„์‚ฐํ•ด์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— Repaint ์†์„ฑ์„ ์‚ฌ์šฉํ•˜์—ฌ ์Šคํƒ€์ผ์„ ์ž‘์„ฑํ•˜๋ฉด ์„ฑ๋Šฅ์„ ๋†’์ผ ์ˆ˜ ์žˆ๋‹ค.

  • Repaint ๋ฐœ์ƒ ์š”์†Œ
    color, border-style, visibility, background, background-color, background-image, background-position , background-repeat, background-size, text-decoration, outline, outline-style, outline-color, outline-width, border-radius, box-shadow ...

โญ๋ฐฉ๋ฒ• 2โญ ๋ถˆํ•„์š”ํ•œ CSS ์ œ๊ฑฐ

๋ถˆํ•„์š”ํ•œ CSS๋Š” ํฌ๋กฌ lightHouse๋ฅผ ํ†ตํ•ด ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

โญ๋ฐฉ๋ฒ• 3โญ ๊ฐ„๊ฒฐํ•œ CSS ์ž‘์„ฑ

์„ ํƒ์ž๋ฅผ ๊ฐ„๊ฒฐํ•˜๊ฒŒ ํ•˜์ž!
CSS๊ฐ€ ๋ณต์žกํ• ์ˆ˜๋ก Layout์„ ๊ทธ๋ฆฌ๋Š” ๋ฐ์— ๋งŽ์€ ์‹œ๊ฐ„์ด ์†Œ์š”๋œ๋‹ค.

<!-- โŒ ์•ˆ ์ข‹์€ ์˜ˆ-->
.parent .parent_child{
	...
}

<!-- โญ• ์ข‹์€ ์˜ˆ-->
.parent_child{
	...
}

(3) ๐Ÿงฉ ์• ๋‹ˆ๋ฉ”์ด์…˜ ์ตœ์ ํ™”

์• ๋‹ˆ๋ฉ”์ด์…˜์€ ์—ฌ๋Ÿฌ์žฅ์˜ ์ด๋ฏธ์ง€๋ฅผ ์—ฐ์†์ ์œผ๋กœ ๋ณด์—ฌ์ค˜์„œ ์›€์ง์ด๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๋ณด์ด๊ฒŒ ํ•˜๋Š” ๊ฒƒ์ด๋‹ค. ๊ทธ๋ ‡๋‹ค๋ฉด ์• ๋‹ˆ๋ฉ”์ด์…˜์˜ ์„ฑ๋Šฅ์ด ๋–จ์–ด์ง„๋‹ค๋Š” ๊ฒƒ์€ ๋ญ˜๊นŒ? ๋ฐ”๋กœ ์• ๋‹ˆ๋ฉ”์ด์…˜์ด ๋ถ€๋“œ๋Ÿฝ๊ฒŒ ๋‹ค์Œ์žฅ์œผ๋กœ ์ด์–ด์ง€๋Š” ๊ฒƒ์ด ์•„๋‹Œ ๋š๋š ๋Š๊ฒจ ๋ณด์ด๋Š” '์Ÿํฌ ํ˜„์ƒ'์ด ๋‚˜ํƒ€๋‚  ๋•Œ ์„ฑ๋Šฅ์ด ๋–จ์–ด์ง„๋‹ค๋Š” ์˜๋ฏธ์ด๋‹ค.

๊ทธ๋Ÿผ ์• ๋‹ˆ๋ฉ”์ด์…˜์˜ ์„ฑ๋Šฅ์€ ์–ด๋–ป๊ฒŒ ๊ฐœ์„ ํ•˜๋‚˜์šฉ? ๐Ÿค”

  • CSS ์†์„ฑ ์ค‘์—๋Š” GPU์˜ ๋„์›€์„ ๋ฐ›์„ ์ˆ˜ ์žˆ๋Š” ์†์„ฑ์ด ์žˆ๋Š”๋ฐ, ๊ทธ ์ค‘ ๋Œ€ํ‘œ์ ์ธ ์†์„ฑ์€ transform๊ณผ opacity๊ฐ€ ์žˆ๋‹ค. transform์€ Reflow์™€ Repaint๋ฅผ ๋ฐœ์ƒ์‹œํ‚ค์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ๋ Œ๋”๋ง ์†๋„๋ฅผ ํ–ฅ์ƒ์‹œํ‚ฌ ์ˆ˜ ์žˆ๋‹ค. (GPU๋Š” ์ปดํ“จํ„ฐ ๊ทธ๋ž˜ํ”ฝ ์ฒ˜๋ฆฌ ์žฅ์น˜์ด๋‹ค!)

(3) ๐Ÿงฉ JS ์ตœ์ ํ™”

โญ๋ฐฉ๋ฒ• 1โญ ๋ถˆํ•„์š”ํ•œ ๊ธฐ๋Šฅ, ๋‹จ๊ณ„ ์ œ๊ฑฐ

๋ฐ˜๋“œ์‹œ ์žˆ์–ด์•ผ ํ•  ์ฝ”๋“œ๊ฐ€ ์•„๋‹ˆ๋ผ๋ฉด ์ œ๊ฑฐํ•˜๊ณ , ํ•จ์ˆ˜๊ฐ€ ์ตœ์ข… ๊ฒฐ๊ณผ๋ฅผ ์–ป๊ธฐ๊นŒ์ง€ ํ•„์š”ํ•œ ๋‹จ๊ณ„๊ฐ€ ์•„๋‹ˆ๋ผ๋ฉด ๋‹จ์ˆœํ™”ํ•ด์•ผ ํ•œ๋‹ค.

๋งŒ์•ฝ, ์ฝ”๋“œ๋ฅผ ์ค„์ผ ์ˆ˜ ์—†๋‹ค๋ฉด ๋œ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ํ™•์ธํ•œ๋‹ค. ์˜ˆ๋ฅผ๋“ค๋ฉด ๋ฐ˜๋ณต๋ฌธ์—์„œ ๋๊นŒ์ง€ ๊ฐ’์„ ์–ป์ง€ ์•Š์•„๋„ ๋œ๋‹ค๋ฉด, break๋ฅผ ํ†ตํ•ด ๋น ์ ธ๋‚˜์™€์•ผ ํ•œ๋‹ค.

โญ๋ฐฉ๋ฒ• 2โญ ๋ณ€์ˆ˜ Polymorphism(๋‹คํ˜•์„ฑ) ํ”ผํ•˜๊ธฐ

JS์˜ ๋ณ€์ˆ˜๋Š” ๋‹คํ˜•์„ฑ์„ ๊ฐ–๋Š”๋‹ค. ๋ฐ˜๋ณตํ•ด์„œ ์‚ฌ์šฉํ•ด์•ผ ํ•˜๋Š” ์ˆซ์ž๊ฐ€ ์•„๋‹ˆ๋ผ๋ฉด ๊ตณ์ด ๋ณ€์ˆ˜๋กœ ์„ ์–ธํ•ด์„œ ์“ฐ์ง€ ์•Š๋Š” ๊ฒƒ์ด ์ข‹๋‹ค.

const x=2, y=4;

mutifly(x,y);

// 1% ๋” ๋น ๋ฆ„
mutifly(2,4);

โญ๋ฐฉ๋ฒ• 3โญ Code Splitting

๋Œ€๋ถ€๋ถ„์˜ ๋ฆฌ์•กํŠธ ํŒŒ์ผ์€ Webpack ๋“ฑ์„ ์‚ฌ์šฉํ•ด์„œ ํŒŒ์ผ์„ ๋ฒˆ๋“ค๋งํ•˜์—ฌ ํ•˜๋‚˜๋กœ ๋ฌถ๋Š”๋‹ค. ๋‹ค๋งŒ, ์ด ํฌ๊ธฐ๊ฐ€ ์ปค์ง€๋ฉด ์„ฑ๋Šฅ์— ์•…์˜ํ–ฅ์„ ๋ผ์น˜๊ฒŒ ๋œ๋‹ค. ์ด๋•Œ Code Splitting์„ ์‚ฌ์šฉํ•œ๋‹ค. ๋ฒˆ๋“ค ํŒŒ์ผ์˜ ์ฝ”๋“œ๋ฅผ ๋ถ„ํ• ํ•˜์—ฌ ๋ชจ๋“  ์ฝ”๋“œ๋ฅผ ํ•œ ๋ฒˆ์— ๋ถˆ๋Ÿฌ์˜ค์ง€ ์•Š๊ณ  ์‚ฌ์šฉ์ž๊ฐ€ ํ•„์š”๋กœ ํ•  ๋•Œ์— ํ•„์š”ํ•œ ์ฝ”๋“œ๋งŒ ๋ถˆ๋Ÿฌ์˜ค๋Š” ๊ฐœ๋…์ด๋‹ค.

(+) Code Splitting์€ SPA์˜ ์„ฑ๋Šฅ์„ ํ–ฅ์ƒ์‹œํ‚ค๋Š” ๋ฐฉ๋ฒ•์ด๋‹ค. SPA๋Š” ์ดˆ๊ธฐ ์‹คํ–‰ ์‹œ ๋กœ๋”ฉ ์†๋„๊ฐ€ ์ง€์—ฐ๋  ์ˆ˜ ์žˆ๋‹ค. ์ด๋•Œ Code Splitting์„ ์‚ฌ์šฉํ•˜๋ฉด ์†๋„ ๊ฐœ์„ ๊ณผ SEO์— ๋„์›€์ด ๋œ๋‹ค.

Code Splitting์„ ์–ด๋–ป๊ฒŒ ์“ฐ๋Š”์ง€์š”? ๐Ÿค”

1. dynamic import() ๊ตฌ๋ฌธ ์‚ฌ์šฉ

Code Splitting์„ ๋„์ž…ํ•˜๋Š” ๊ฐ€์žฅ ์ข‹์€ ๋ฐฉ๋ฒ•์€ import() ๋ฌธ๋ฒ•์„ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์ด๋‹ค.

๐Ÿ“Œ Before- ์ •์  ๋ถˆ๋Ÿฌ์˜ค๊ธฐ (static import)

import { add } from './math';

console.log(add(16, 26));

๐Ÿ“Œ After- ๋™์  ๋ถˆ๋Ÿฌ์˜ค๊ธฐ (dynamic import)

import('./math').then((math)=> {
	console.log(add(16, 26));
}

dynamic import ๊ตฌ๋ฌธ์€ ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ๋ฌธ๋ฒ• ํ˜•ํƒœ์ด์ง€๋งŒ, import๋Š” ํ•จ์ˆ˜๊ฐ€ ์•„๋‹ˆ๋‹ค !! ๋˜ํ•œ static import๋Š” ๋งจ ์ƒ๋‹จ์— ์œ„์น˜ํ•ด์•ผ ํ•˜์ง€๋งŒ, dynamic import๋Š” ์ฝ”๋“œ์˜ ์œ„์น˜์— ์ƒ๊ด€ ์—†์ด ์‚ฌ์šฉ์ด ๊ฐ€๋Šฅํ•˜๋‹ค.

2. React.lazy ์‚ฌ์šฉ
React์—์„œ ์ปดํฌ๋„ŒํŠธ ํŒŒ์ผ์„ ์ •์˜ํ•˜๊ณ  dynamic import๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.
์ด๋Ÿฐ ์ƒํ™ฉ์—์„œ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋™์ ์œผ๋กœ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ ์œ„ํ•ด์„œ React.lazy๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.

import React, { Suspense } from 'react';

const OtherComponent = React.lazy(() => import('./OtherComponent'));

function MyComponent() {
  return (
    <div>
      <Suspense fallback={<div>Loading...</div>}>
        <OtherComponent />
      </Suspense>
    </div>
  );
}

React.laz๋Š” import() ๊ตฌ๋ฌธ์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ์ฝœ๋ฐฑํ•จ์ˆ˜๋ฅผ ์ธ์ž๋กœ ๋ฐ›๋Š”๋‹ค. ๋™์  ๋ถˆ๋Ÿฌ์˜ค๊ธฐ๋กœ ๋ถˆ๋Ÿฌ์™€์ง€๋Š” ๋ชจ๋“ˆ์€ 1. ReactComponent๋ฅผ ํฌํ•จํ•˜๋ฉฐ 2. default export๋ฅผ ๊ฐ€์ง„ ๋ชจ๋“ˆ์ด์–ด์•ผ ํ•œ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋ถˆ๋Ÿฌ์˜จ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

React.lazy๋กœ ๋ถˆ๋Ÿฌ์˜จ ์ปดํฌ๋„ŒํŠธ๋Š” ๋‹จ๋…์œผ๋กœ ์“ฐ์ผ ์ˆ˜ ์—†๊ณ , React.Suspense ์ปดํฌ๋„ŒํŠธ๋กœ ํ•˜์œ„์—์„œ ๋ Œ๋”๋ง๋˜์–ด์•ผ ํ•œ๋‹ค. ๊ทธ๋ฆฌ๊ณ  Suspense๋Š” lazy ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋กœ๋“œ๋˜๋Š” ๋™์•ˆ Loding ... ์ด๋ผ๋Š” ํ™”๋ฉด์„ ๋ณด์—ฌ์ค€๋‹ค.(๊ทธ๋ž˜์„œ ์ง€์—ฐ๋กœ๋”ฉ์ด๋ผ ๋ถ€๋ฅด๋Š” ๊ฒƒ ...!! ๐Ÿ˜ฒ) ์ด๋•Œ fallback prop๋Š” ํ•„์ˆ˜์ด๋‹ค !!

Code Splitting์€ ์–ด๋””์— ์“ฐ๋Š”์ง€์š”? ๐Ÿค”

React ๊ณต์‹๋ฌธ์„œ์˜ ์ฝ”๋“œ ๋ถ„ํ•  ํ•ญ๋ชฉ์— ์˜ํ•˜๋ฉด, Router ๋ฐ”๋กœ ์•„๋ž˜์— Suspense๋ฅผ ์œ„์น˜์‹œํ‚ค๊ณ , Route๋กœ ๋ณด์—ฌ์ค„ ์ปดํฌ๋„ŒํŠธ๋“ค์„ React.lazy๋กœ ๋ถˆ๋Ÿฌ์˜ฌ ๊ฒƒ์„ ๊ถŒ์žฅํ•˜๊ณ  ์žˆ๋‹ค.

import React, { Suspense, lazy } from 'react';
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';

const Home = lazy(() => import('./routes/Home'));
const About = lazy(() => import('./routes/About'));

const App = () => (
  <Router>
    <Suspense fallback={<div>Loading...</div>}>
      <Switch>
        <Route exact path="/" component={Home}/>
        <Route path="/about" component={About}/>
      </Switch>
    </Suspense>
  </Router>
);

profile
๊ธฐ๋ก์žฅ ๐Ÿ“

0๊ฐœ์˜ ๋Œ“๊ธ€