๐Ÿ–ฅFrontEnd/React

React 18 ๋ฒ„์ „ ์ดํ›„) React์—์„œ ์ฝ”๋“œ ๋ถ„ํ•  ํ•˜๋Š” ๋ฐฉ๋ฒ•, dynamic import ๋ฐฉ๋ฒ•, React.lazy์™€ Suspense

hellohailie 2022. 7. 28. 11:29

์ฝ”๋“œ ๋ถ„ํ•  (Code Spliting)

๋ฒˆ๋“ค๋ง์„ ํ•  ๋•Œ, HTML ์›น ํŽ˜์ด์ง€์— JS๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š”๋ฐ, ๋ชจ๋˜ ์›น์œผ๋กœ ๋ฐœ์ „ํ•˜๋ฉด์„œ ์ ์  DOM์„ ๋‹ค๋ฃจ๋Š” ์ •๋„๊ฐ€ ์ •๊ตํ•ด์ง€๋ฉด์„œ JS ์ฝ”๋“œ ์ž์ฒด๊ฐ€ ๋ฐฉ๋Œ€ํ•ด์ง€๊ณ  ๋ฌด๊ฑฐ์›Œ์กŒ๋‹ค. 

 

์ด๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•œ ๋ฐฉ๋ฒ•์œผ๋กœ, ๋ฒˆ๋“ค์„ ๋ฌผ๋ฆฌ์ ์œผ๋กœ ๋‚˜๋ˆˆ ํ›„, ํ•„์š”ํ•œ ์ฝ”๋“œ๋งŒ ๋ถˆ๋Ÿฌ์˜ค๊ณ  ๋‚˜์ค‘์— ํ•„์š”ํ•œ ์ฝ”๋“œ๋Š” ๋‚˜์ค‘์— ๋ถˆ๋Ÿฌ์˜ค๋Š” ๊ฒƒ์ด๋‹ค. 

=> ์ด๊ฒŒ ๋ฐ”๋กœ ์ฝ”๋“œ ๋ถ„ํ• !

์ฝ”๋“œ ๋ถ„ํ• ์€ ๋Ÿฐํƒ€์ž„ ์‹œ ์—ฌ๋Ÿฌ ๋ฒˆ๋“ค์„ ๋™์ ์œผ๋กœ ๋งŒ๋“ค๊ณ  ๋ถˆ๋Ÿฌ์˜ค๋Š” ๊ฒƒ์œผ๋กœ, Webpack, Rollup๊ณผ ๊ฐ™์€ ๋ฒˆ๋“ค๋Ÿฌ๊ฐ€ ์ง€์›ํ•˜๋Š” ๊ธฐ๋Šฅ์ด๋‹ค.

 

๋ฒˆ๋“ค ๋ถ„ํ•  ํ•˜๋Š” ๋ฐฉ๋ฒ• => ์„œ๋“œํŒŒํ‹ฐ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋Š” npm์„ ํ†ตํ•ด ๋‹ค์šด๋ฐ›๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ธ๋ฐ, ์‚ฌ์šฉ์ž์—๊ฒŒ ๋‹ค์–‘ํ•œ ๋ฉ”์†Œ๋“œ๋ฅผ ์ œ๊ณตํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ฝ”๋“œ์˜ ์–‘์ด ๋งŽ๊ณ , ๋ฒˆ๋“ค๋ง ์‹œ ๋งŽ์€ ๊ณต๊ฐ„์„ ์ฐจ์ง€ํ•œ๋‹ค. ๊ทธ๋ž˜์„œ ์‚ฌ์šฉ ์ค‘์ธ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ „๋ถ€๋ฅผ ๋ถˆ๋Ÿฌ์™€์„œ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ๋ณด๋‹ค ๋”ฐ๋กœ๋”ฐ๋กœ ๋ถˆ๋Ÿฌ์™€์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์œผ๋ฉด ์ฐจ์ง€ํ•˜๋Š” ๊ณต๊ฐ„์„  ์ค„์ผ ์ˆ˜ ์žˆ๋‹ค. 


โœ”๏ธ React์—์„œ ์ฝ”๋“œ ๋ถ„ํ•  ํ•˜๋Š” ๋ฐฉ๋ฒ• => dynamic import(๋™์  ๋ถˆ๋Ÿฌ์˜ค๊ธฐ)๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ

 

๊ธฐ์กด ๋ฐฉ๋ฒ• (static import /์ •์  ๋ถˆ๋Ÿฌ์˜ค๊ธฐ)

import moduleA from "library";

 

โœ”๏ธ dynamic import(๋™์  ๋ถˆ๋Ÿฌ์˜ค๊ธฐ)๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ• => React.lazy์™€ ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜๊ธฐ

 

React.lazy ์‚ฌ์šฉ๋ฐฉ๋ฒ•

React.lazy๋กœ ๊ฐ์‹ผ ์ปดํฌ๋„ŒํŠธ๋Š” ๋‹จ๋…์œผ๋กœ ์“ฐ์ผ ์ˆ˜๋Š” ์—†๊ณ , React.suspense ์ปดํฌ๋„ŒํŠธ์˜ ํ•˜์œ„์—์„œ ๋ Œ๋”๋ง์„ ํ•ด์•ผ ํ•œ๋‹ค.

import Component from './Component';

/* React.lazy๋กœ dynamic import๋ฅผ ๊ฐ์Œ‰๋‹ˆ๋‹ค. */
const Component = React.lazy(() => import('./Component'));

 

React.Suspense ์‚ฌ์šฉ๋ฐฉ๋ฒ•

Router๋กœ ๋ถ„๊ธฐ๊ฐ€ ๋‚˜๋ˆ„์–ด์ง„ ์ปดํฌ๋„ŒํŠธ๋“ค์„ ์œ„ ์ฝ”๋“œ์ฒ˜๋Ÿผ lazy๋ฅผ ํ†ตํ•ด importํ•˜๋ฉด ํ•ด๋‹น path๋กœ ์ด๋™ํ•  ๋•Œ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ถˆ๋Ÿฌ์˜ค๊ฒŒ ๋˜๋Š”๋ฐ, ์ด ๊ณผ์ •์—์„œ ๋กœ๋”ฉํ•˜๋Š” ์‹œ๊ฐ„์ด ์ƒ๊ธด๋‹ค. 

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

/* suspense ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” import ํ•ด์™€์•ผ ํ•ฉ๋‹ˆ๋‹ค. */
import { Suspense } from 'react';

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

function MyComponent() {
  return (
    <div>
			{/* ์ด๋Ÿฐ ์‹์œผ๋กœ React.lazy๋กœ ๊ฐ์‹ผ ์ปดํฌ๋„ŒํŠธ๋ฅผ Suspense ์ปดํฌ๋„ŒํŠธ์˜ ํ•˜์œ„์— ๋ Œ๋”๋งํ•ฉ๋‹ˆ๋‹ค. */}
      <Suspense fallback={<div>Loading...</div>}>
				{/* Suspense ์ปดํฌ๋„ŒํŠธ ํ•˜์œ„์— ์—ฌ๋Ÿฌ ๊ฐœ์˜ lazy ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ Œ๋”๋ง์‹œํ‚ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. */}
        <OtherComponent />
				<AnotherComponent />
      </Suspense>
    </div>
  );
}

 

โžฅ Supense ์ปดํฌ๋„ŒํŠธ์˜ fallback prop์€ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋กœ๋“œ๋  ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆฌ๋Š” ๋™์•ˆ ๋กœ๋”ฉ ํ™”๋ฉด์œผ๋กœ ๋ณด์—ฌ์ค„ React ์—˜๋ฆฌ๋จผํŠธ๋ฅผ ๋ฐ›์•„๋“ค์ธ๋‹ค. 

 

 


โœ”๏ธ ๊ทธ๋ž˜์„œ React.lazy์™€ Suspense๋ฅผ ์–ด๋””์— ์ ์šฉํ•  ์ˆ˜ ์žˆ๋Š”๊ฐ€? 

 

์›น ํŽ˜์ด์ง€๋ฅผ ๋ถˆ๋Ÿฌ์˜ค๊ณ  ์ง„์ž…ํ•˜๋Š” ๋‹จ๊ณ„์ธ Route์— ์ด ๊ธฐ๋Šฅ์„ ์ ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹๋‹ค. 

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

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

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

 

๐Ÿ˜ƒ ์ž˜๋ชป๋œ ๊ฐœ๋… ์ „๋‹ฌ์ด ์žˆ๋‹ค๋ฉด ๋Œ“๊ธ€ ๋ถ€ํƒ๋“œ๋ฆฝ๋‹ˆ๋‹ค. ์ €์˜ ์„ฑ์žฅ์— ํฐ ๋„์›€์ด ๋ฉ๋‹ˆ๋‹ค๐Ÿค“