Lieto: Lazy Loading (React.Lazy, Suspense) ๐Ÿš€

๋ฐ•์ƒํ•˜ยท2024๋…„ 1์›” 18์ผ
0

Lieto

๋ชฉ๋ก ๋ณด๊ธฐ
7/9

์ปดํฌ๋„ŒํŠธ๊ฐ€ ๊ฝค ๋งŽ์•„์ง€๋ฉด์„œ (๋ฉ”์ธ ์ปดํฌ๋„ŒํŠธ 6๊ฐœ..ใ…Žใ…Ž..๋งŽ๋‚˜?..) ์ปดํฌ๋„ŒํŠธ๋ฅผ ํ•œ๋ฒˆ์— ๋‹ค ๊ฐ€์ ธ์˜ค์ง€ ์•Š๊ณ  ๋‚˜๋ˆ„์–ด์„œ importํ•ด์˜ค๋ฉด ์ข‹๊ฒ ๋‹ค ๋ผ๊ณ  ์ƒ๊ฐ์„ ํ–ˆ๋‹ค.

๊ทธ๋ž˜์„œ ๋™์ ์ธ Import๋ฅผ ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•ด์ฃผ๋Š” React.Lazy๋ฅผ ์‚ฌ์šฉํ•ด๋ดค๋‹ค.

Lazy Loading ๐ŸŽฏ

Lazy Loading ์ด๋ž€? ๊ฒŒ์œผ๋ฅธ ๋กœ๋”ฉ?
์›น ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์„ฑ๋Šฅ์„ ํ–ฅ์ƒ์‹œํ‚ค๋Š” ๊ธฐ์ˆ  ์ค‘ ํ•˜๋‚˜๋กœ ์›น ํŽ˜์ด์ง€๊ฐ€ ์ฒ˜์Œ ๋กœ๋“œ ๋  ๋•Œ ํ•„์š”ํ•˜์ง€ ์•Š์€ ๋ฆฌ์†Œ์Šค๋ฅผ ๋กœ๋“œํ•˜์ง€ ์•Š๋Š” ๋ฐฉ์‹์ด๋‹ค! ๋Œ€์‹  ์‚ฌ์šฉ์ž๊ฐ€ ๊ทธ๊ฒƒ์„ ์‹ค์ œ๋กœ ํ•„์š”ํ•  ๋•Œ (Ex ํŠน์ • ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ณด์—ฌ์ฃผ๊ณ  ์‹ถ์„๋•Œ) ๋กœ๋“œ๋  ์ˆ˜ ์žˆ๋‹ค.

์žฅ์ ?
"์ดˆ๊ธฐ ๋กœ๋”ฉ์„ ์ค„์ผ ์ˆ˜ ์žˆ๋‹ค." + "์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์ „๋ฐ˜์ ์ธ ์„ฑ๋Šฅ ํ–ฅ์ƒ"

์ฆ‰, ๊ผญ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์•„๋‹ˆ๋”๋ผ๋„ ์ด๋ฏธ์ง€๋„ Lazy Loading์„ ํ†ตํ•ด ์›ํ•˜๋Š” ๋งŒํผ๋งŒ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ๋‹ค.

;;๐Ÿ•์‚ฌ๊ธฐ;;

์˜คํžˆ๋ ค ๊ณผ๊ฑฐ์—๋Š” ํฐ ์ด๋ฏธ์ง€, ํฐ ํŒŒ์ผ์— ์ ์šฉ๋˜๋Š” ๊ธฐ์ˆ ์ด์—ˆ์œผ๋‚˜ ํ˜„์žฌ๋Š” ์ปดํฌ๋„ŒํŠธ๊นŒ์ง€ ๋™์ ์œผ๋กœ ๋กœ๋”ฉํ•  ์ˆ˜ ์žˆ๋‹ค.

๋™์ž‘์›๋ฆฌ ๐ŸŽฏ

React.lazy๋Š” ์ผ๋‹จ ๋™์ ์œผ๋กœ importํ•  ์ˆ˜ ์žˆ๋Š” ๋ฉ”์„œ๋“œ์ด๋‹ค.

์ด๋Š” Promise๋ฅผ ์ธ์ˆ˜๋กœ ๋ฐ›๋Š”๋‹ค. ํ•ด๋‹น Promise๊ฐ€ ํ•ด๊ฒฐ๋˜๋ฉด ๋กœ๋“œ๋œ ํŒŒ์ผ์ด ๋ฐ˜ํ™˜์ด ๋œ๋‹ค!

์ด๋•Œ ์ค‘์š”ํ•œ๊ฑด Suspense์ด๋‹ค.

Suspense ๐ŸŽฏ

Suspense๋Š” ์œ„ ๋™์ž‘์—์„œ ํ•ด๋‹น Promise๊ฐ€ pending์ธ์ง€ fullfill์ธ์ง€๋ฅผ ์•Œ๊ณ  loader๋ฅผ ์ œ๊ณตํ•ด์ค€๋‹ค.

์ฆ‰ ReactLazy๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ๋Š” Suspense๋กœ ํ•ด๋‹น ์ž‘์—…์ด ์ž˜ ์ด๋ฃจ์–ด์กŒ๋Š”์ง€ ํ™•์ธํ•ด์•ผํ•œ๋‹ค.

์‚ฌ์šฉ ๐ŸŽฏ

import React from "react";
import { Suspense } from "react";
import { Loader } from "./Loader";

const Title = React.lazy(() => import("./Title/Title.jsx"));
const ArtistView = React.lazy(() => import("./Artist/View.jsx"));
const PosterView = React.lazy(() => import("./Poster/View.jsx"));
const MapView = React.lazy(() => import("./Map/View.jsx"));
function App() {
  //useEffect๋Š” ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋ Œ๋”๋ง ๋  ๋•Œ๋งˆ๋‹ค ์ž‘์—…์„ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜๋Š” Hook
  // ๋งŒ์•ฝ []๋ฅผ ๋„ฃ์œผ๋ฉด ์ตœ์ดˆ 1๋ฒˆ ๋ Œ๋”๋ง๋  ๋•Œ ์‹คํ–‰
  // []๋ฅผ ๋„ฃ์ง€ ์•Š์œผ๋ฉด ๋ฆฌ๋ Œ๋”๋งํ• ๋•Œ๋งˆ๋‹ค ์‹คํ–‰
  // ๋งŒ์•ฝ ํŠน์ • ๊ฐ’์ด ์—…๋ฐ์ดํŠธ ๋  ๋•Œ ์‹คํ–‰ํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด []์— ํ•ด๋‹น ์—…๋ฐ์ดํŠธ ๋ณ€์ˆ˜๋ฅผ ๋„ฃ์–ด์ฃผ๋ฉด๋œ๋‹ค.

  return (
    <div className="App">
      <Suspense fallback={<Loader />}>
        <Title />
      </Suspense>
      <Suspense fallback={<Loader />}>
        <ArtistView />
      </Suspense>
      <Suspense fallback={<Loader />}>
        <PosterView />
      </Suspense>
      <Suspense fallback={<Loader />}>
        <MapView />
      </Suspense>
    </div>
  );
}

์œ„ ์ฒ˜๋Ÿผ ํ•„์ž๋Š” ๋ชจ๋“  ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋™์ ์œผ๋กœ ๋ฐ›์•„์™”๋‹ค. ์‚ฌ์‹ค ์ด๋ ‡๊ฒŒ ํ• ๊ฑฐ๋ผ๋ฉด Loader์— ์Šค์ผˆ๋ ˆํ†ค UI๋ฅผ ์ง‘์–ด๋„ฃ์–ด์ฃผ๋Š”๊ฒŒ ๋” ์ข‹์„ ๊ฑฐ ๊ฐ™๋‹ค.

์ €๋ ‡๊ฒŒ ํ•˜๋‹ˆ ์„ฑ๋Šฅ์€ ์–ด๋–ค ์ฐจ์ด๋ฅผ ๋ณด์˜€์„๊นŒ?

์„ฑ๋Šฅ์ฐจ์ด ๐ŸŽฏ

์ฝ”๋“œ ์Šคํ”Œ๋ฆฌํŒ… ํ•˜๊ธฐ์ „(React.lazy๋กœ ๋™์ ์œผ๋กœ ๋ฐ›์•„์˜ค๊ธฐ์ „)

ํ•ด๋‹น ํŒŒ์ผ์„ ๋ฐ›์•„์˜ค๊ธฐ ๊นŒ์ง€ 14.24ms๊ฐ€ ๊ฑธ๋ ธ๊ณ 


(๊ทธ๋ƒฅ ํ•ธ๋“œํฐ์œผ๋กœ ์ฐ์–ด๋ฒ„๋ฆผ ;;)

๋‹ค์Œ๊ณผ ๊ฐ™์ด Total Blocking Time์€ 360ms

First Contentful Paint ์ฆ‰, ์ดˆ๊ธฐ ๋กœ๋”ฉ ์‹œ๊ฐ„์ด 1.9s๊ฐ€ ๋‚˜์™”๋‹ค.

์ฝ”๋“œ ์Šคํ”Œ๋ฆฌํŒ…์„ ํ•œ ํ›„

ํ•ด๋‹น ํŒŒ์ผ์„ ๋ฐ›์•„์˜ค๊ธฐ ๊นŒ์ง€ 9.84ms๊ฐ€ ๊ฑธ๋ ธ๊ณ 

Total Blocking Time์€ ์ ˆ๋ฐ˜ ์ด์ƒ ๊ฐ์†Œํ•œ 160ms๊ฐ€ ๊ฑธ๋ ธ๊ณ 

First Contentful Paint ์ฆ‰, ์ดˆ๊ธฐ ๋กœ๋”ฉ ์‹œ๊ฐ„์ด 1.8s๊ฐ€ ๊ฑธ๋ ธ๋‹ค. ๊ทธ๋ ‡๊ฒŒ ๊ทน์ ์ด์ง„ ์•Š์ง€๋งŒ.. ๋…ธ๋ž€๋ถˆ์ด ์ดˆ๋ก๋ถˆ๋กœ ๋ฐ”๋€Œ๋Š”๊ฒŒ ์‹ ๊ธฐํ•˜๊ณ  ๋ณด๋žŒ์žˆ๋‹ค.

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

๊ด€๋ จ ์ฑ„์šฉ ์ •๋ณด