lazy
lazy
๋ฅผ ์ฌ์ฉํ๋ฉด ์ปดํฌ๋ํธ๊ฐ ์ฒ์ ๋ ๋๋ง๋ ๋๊น์ง ํด๋น ์ปดํฌ๋ํธ์ ์ฝ๋๋ฅผ ๋ก๋ฉํ๋ ๊ฒ์ ์ง์ฐํ ์ ์์ต๋๋ค.
const SomeComponent = lazy(load)
๋ ํผ๋ฐ์ค
lazy(load)
lazy
๋ฅผ ์ปดํฌ๋ํธ ์ธ๋ถ์์ ํธ์ถํ์ฌ ์ง์ฐ ๋ก๋ฉ๋ React ์ปดํฌ๋ํธ๋ฅผ ์ ์ธํ์ธ์.
import { lazy } from 'react';
const MarkdownPreview = lazy(() => import('./MarkdownPreview.js'));
์๋ ์์๋ฅผ ์ฐธ๊ณ ํ์ธ์.
๋งค๊ฐ๋ณ์
load
: Promise ํน์ ๋ ๋ค๋ฅธ thenable (then
๋ฉ์๋๊ฐ ์๋ Promise ์ ์ฌ ๊ฐ์ฒด)์ ๋ฐํํ๋ ํจ์์ ๋๋ค. React๋ ๋ฐํ๋ ์ปดํฌ๋ํธ๋ฅผ ์ฒ์ ๋ ๋๋งํ๋ ค๊ณ ์๋ํ ๋๊น์งload
๋ฅผ ํธ์ถํ์ง ์์ต๋๋ค. React๊ฐ ์ฒ์์ผ๋กload
๋ฅผ ํธ์ถํ๋ฉด, ๊ทธ๊ฒ์ด ํด๊ฒฐ๋ ๋๊น์ง ๊ธฐ๋ค๋ฆฌ๊ณ , ๊ทธ ํ ํด๊ฒฐ๋ ๊ฐ์.default
๋ฅผ React ์ปดํฌ๋ํธ๋ก ๋ ๋๋งํฉ๋๋ค. ๋ฐํ๋ Promise์ Promise์ ํด๊ฒฐ๋ ๊ฐ์ ์บ์๋๋ฏ๋ก, React๋load
๋ฅผ ํ ๋ฒ๋ง ํธ์ถํฉ๋๋ค. ๋ง์ฝ Promise๊ฐ ๊ฑฐ๋ถ๋๋ฉด, React๋ ๊ฑฐ๋ถ ์ด์ ๋ฅผ ๊ฐ์ฅ ๊ฐ๊น์ด Error Boundary๊ฐ ์ฒ๋ฆฌํ ์ ์๋๋กthrow
ํฉ๋๋ค.
๋ฐํ๊ฐ
lazy
๋ ํธ๋ฆฌ์ ๋ ๋๋งํ ์ ์๋ React ์ปดํฌ๋ํธ๋ฅผ ๋ฐํํฉ๋๋ค. ์ปดํฌ๋ํธ์ ์ฝ๋๊ฐ ์ฌ์ ํ ๋ก๋ฉ๋๋ ๋์ ๋ ๋๋ง์ ์๋ํ๋ฉด ์ผ์ ์ค์ง๋ฉ๋๋ค. ๋ก๋ฉ ์ค์ Loading Indicator๋ฅผ ํ์ํ๋ ค๋ฉด <Suspense>
๋ฅผ ์ฌ์ฉํ์ธ์.
load
ํจ์
๋งค๊ฐ๋ณ์
load
๋ ๋งค๊ฐ๋ณ์๋ฅผ ๋ฐ์ง ์์ต๋๋ค.
๋ฐํ๊ฐ
Promise ๋๋ ๋ค๋ฅธ thenable (then
๋ฉ์๋๊ฐ ์๋ Promise ์ ์ฌ ๊ฐ์ฒด)์ ๋ฐํํด์ผ ํฉ๋๋ค. ๊ฒฐ๊ตญ .default
ํ๋กํผํฐ๊ฐ ํจ์, memo
, forwardRef
์ปดํฌ๋ํธ์ ๊ฐ์ ์ ํจํ React ์ปดํฌ๋ํธ ์ ํ์ธ ๊ฐ์ฒด๋ก ํด์๋์ด์ผ ํฉ๋๋ค.
์ฌ์ฉ๋ฒ
Suspense์ ์ง์ฐ ๋ก๋ฉ ์ปดํฌ๋ํธ
์ผ๋ฐ์ ์ผ๋ก ์ ์ import
์ ์ธ์ผ๋ก ์ปดํฌ๋ํธ๋ฅผ ๊ฐ์ ธ์ต๋๋ค.
import MarkdownPreview from './MarkdownPreview.js';
ํด๋น ์ปดํฌ๋ํธ ์ฝ๋๊ฐ ์ฒ์ ๋ ๋๋ง ๋ ๋๊น์ง ๋ก๋ํ๋ ๊ฒ์ ์ฐ๊ธฐํ๋ ค๋ฉด import
๋ฅผ ๋ค์๊ณผ ๊ฐ์ด ๋์ฒดํฉ๋๋ค.
import { lazy } from 'react';
const MarkdownPreview = lazy(() => import('./MarkdownPreview.js'));
์์ ์ฝ๋๋ ๋์ import()
์ ์์กดํ๋ฏ๋ก ๋ฒ๋ค๋ฌ ๋๋ ํ๋ ์์ํฌ์ ์ง์์ด ํ์ํ ์ ์์ต๋๋ค. ์ด ํจํด์ ์ฌ์ฉํ๋ ค๋ฉด ์ํฌํธํ๋ ค๋ lazy
์ปดํฌ๋ํธ๊ฐ default
๋ด๋ณด๋ด๊ธฐ๋ก ๋ด๋ณด๋ด์ ธ ์์ด์ผ ํฉ๋๋ค.
์ด์ ์์ฒญ์ ๋ฐ๋ผ ์ปดํฌ๋ํธ์ ์ฝ๋๊ฐ ๋ก๋ฉ๋๋ฏ๋ก, ๋ก๋ฉํ๋ ๋์ ํ์ํ ํญ๋ชฉ๋ ์ง์ ํด์ผ ํฉ๋๋ค. lazy
์ปดํฌ๋ํธ ๋๋ ํด๋น ๋ถ๋ชจ ์ปดํฌ๋ํธ ์ค ํ๋๋ฅผ <Suspense>
๊ฒฝ๊ณBoundary๋ก ๊ฐ์ธ์ ์ด ์์
์ ์ํํ ์ ์์ต๋๋ค.
<Suspense fallback={<Loading />}>
<h2>Preview</h2>
<MarkdownPreview />
</Suspense>
์ด ์์์์ MarkdownPreview
์ฝ๋๋ ๋ ๋๋ง์ ์๋ํ ๋๊น์ง ๋ก๋ฉ๋์ง ์์ต๋๋ค. MarkdownPreview
๊ฐ ์์ง ๋ก๋ฉ๋์ง ์๋ ๊ฒฝ์ฐ์๋ ๊ทธ ์๋ฆฌ์ Loading
์ฝ๋๊ฐ ๋์ ํ์๋ฉ๋๋ค. ์ฒดํฌ๋ฐ์ค๋ฅผ ์ ํํด ๋ณด์ธ์.
import { useState, Suspense, lazy } from 'react'; import Loading from './Loading.js'; const MarkdownPreview = lazy(() => delayForDemo(import('./MarkdownPreview.js'))); export default function MarkdownEditor() { const [showPreview, setShowPreview] = useState(false); const [markdown, setMarkdown] = useState('Hello, **world**!'); return ( <> <textarea value={markdown} onChange={e => setMarkdown(e.target.value)} /> <label> <input type="checkbox" checked={showPreview} onChange={e => setShowPreview(e.target.checked)} /> Show preview </label> <hr /> {showPreview && ( <Suspense fallback={<Loading />}> <h2>Preview</h2> <MarkdownPreview markdown={markdown} /> </Suspense> )} </> ); } // ๋ก๋ฉ ์ํ๋ฅผ ํ์ธํ๊ธฐ ์ํด, ํ ์คํธ๋ฅผ ์ํ ์ง์ฐ๊ฐ์ ์ถ๊ฐํฉ๋๋ค. function delayForDemo(promise) { return new Promise(resolve => { setTimeout(resolve, 2000); }).then(() => promise); }
์ด ๋ฐ๋ชจ๋ ์ธ์์ ์ธ ์ง์ฐ์ผ๋ก ๋ก๋ฉ๋ฉ๋๋ค. ๋ค์์ ์ฒดํฌ๋ฐ์ค๋ฅผ ์ ํ ํด์ ํ๊ณ ๋ค์ ์ ํํ๋ฉด Preview
๊ฐ ์บ์ ๋์ด ๋ก๋ฉ ์ํ๊ฐ ๋์ง ์์ต๋๋ค. ๋ก๋ฉ ์ํ๋ฅผ ๋ค์ ๋ณด๋ ค๋ฉด ์๋๋ฐ์ค์์ โResetโ์ ํด๋ฆญํ์ธ์.
Suspense๋ฅผ ์ฌ์ฉํ์ฌ ๋ก๋ฉ ์ํ๋ฅผ ๊ด๋ฆฌํ๋ ๋ฐฉ๋ฒ์ ๋ํด ์์ธํ ์์๋ณด์ธ์.
๋ฌธ์ ํด๊ฒฐ
lazy
์ปดํฌ๋ํธ์ ์ํ๊ฐ ์๋์น ์๊ฒ ์ฌ์ค์ ๋ฉ๋๋ค.
lazy
์ปดํฌ๋ํธ๋ฅผ ๋ค๋ฅธ ์ปดํฌ๋ํธ ๋ด๋ถ์์ ์ ์ธํ์ง ๋ง์ธ์.
import { lazy } from 'react';
function Editor() {
// ๐ด ์๋ชป๋ ๋ฐฉ๋ฒ: ์ด๋ ๊ฒ ํ๋ฉด ๋ค์ ๋ ๋๋งํ ๋ ๋ชจ๋ ์ํ๊ฐ ์ฌ์ค์ ๋ฉ๋๋ค.
const MarkdownPreview = lazy(() => import('./MarkdownPreview.js'));
// ...
}
๋์ ํญ์ ๋ชจ๋์ ์ต์์ ์์ค์์ ์ ์ธํ์ธ์.
import { lazy } from 'react';
// โ
์ฌ๋ฐ๋ฅธ ๋ฐฉ๋ฒ: `lazy` ์ปดํฌ๋ํธ๋ฅผ ์ปดํฌ๋ํธ ์ธ๋ถ์ ์ ์ธํฉ๋๋ค.
const MarkdownPreview = lazy(() => import('./MarkdownPreview.js'));
function Editor() {
// ...
}