[React] Proxy๋ฅผ ํ์ฉํ Custom Lazy Import
React.lazy()
React์์ ์ฝ๋ ๋ถํ ์ ๋ชฉ์ ์ผ๋ก(Chunk ๋ถ๋ฆฌ) ์ปดํฌ๋ํธ๋ฅผ Dynamic Import ํ ๋ React.lazy()
ํจ์๋ฅผ ์ฌ์ฉํ๋ค. ์ปดํฌ๋ํธ๊ฐ ํ์ํ ์์ ์๋ง ๋ก๋๋๊ธฐ ๋๋ฌธ์, ๋ก๋ฉ ์ค ํ์ํ ์ปดํฌ๋ํธ๋ ๋ฉ์์ง๋ <Suspense>
๋ฅผ ํ์ฉํ์ฌ ์ค์ ํ๋ค. ์ฌ๋ฌ ๊ฐ์ lazy ์ปดํฌ๋ํธ๋ฅผ ๋ฌถ์ด์ fallback์ ํ ๋ฒ์ ํ์ํ ์๋ ์๋ค.
๋ํ, React.lazy()
๋ก ๋ถ๋ฌ์ค๋ ค๋ ์ปดํฌ๋ํธ๋ ๊ธฐ๋ณธ์ ์ผ๋ก default export๋ฅผ ์ฌ์ฉํด์ ๋ด๋ณด๋ด์ผ ํ๋ค.
// Child.tsx
export default function Child() { /* ... */ }
// Parent.tsx
import { Suspense } from 'react';
// ์ปดํฌ๋ํธ ๋ฐ๋์์ ํธ์ถํ๋ฉด ์ ์ ์๋ํ์ง ์์ผ๋ฏ๋ก ์ฃผ์
const Child = React.lazy(() => import('./Child'));
const Parent = () => {
return (
<Suspense fallback={<Loading />}>
<Child />
</Suspense>
);
}
์ปดํฌ๋ํธ๊ฐ named export ๋ผ๋ฉด ์๋์ฒ๋ผ ๋ชจ๋์ ํ๋กํผํฐ(์ปดํฌ๋ํธ ์ด๋ฆ)๋ฅผ default
์์ฑ์ ๋ด์์ ๋ฐํํ๋ Workaround(์ฐจ์ ์ฑ
)๋ฅผ ์ฌ์ฉํด์ผ ํ๋ค.
const Child = React.lazy(() =>
import('./Child').then((module) => ({ default: module.Child })),
);
Proxy๋ฅผ ํ์ฉํ ์ปค์คํ LazyImport
๊ฐ์ฒด ํ๋กํผํฐ์ ์ฝ๊ธฐ / ์ฐ๊ธฐ ์์
์ ์ค๊ฐ์ ๊ฐ๋ก์ฑ์ ์ํ๋ ์์
์ ์ํํ ๋ Proxy๋ฅผ ์ฌ์ฉํ๋ค. Proxy๋ก React.lazy()
ํจ์๋ฅผ ๋ฉํํด์ ์ปค์คํ
ํ๋ฉด named export ์ปดํฌ๋ํธ๋ ๊น๋ํ๊ฒ ๋์ importํ ์ ์๋ค.
import { ComponentType, lazy } from 'react';
type ComponentName = string;
type Loader<T> = () => Promise<T>;
type NamedComponents = Record<ComponentName, unknown>;
export const lazyImport = <T extends NamedComponents>(loader: Loader<T>) => {
return new Proxy({} as T, {
get: (_target, name: ComponentName) => {
return lazy(async () => {
const module = await loader();
const Component = module[name] as ComponentType<T>;
return { default: Component };
});
},
});
};
// lazyImport ์ฌ์ฉ
const { Home, About } = lazyImport(() => import('@/features/misc'));
lazyImport
๋ Promise๋ฅผ ๋ฐํํ๋ loader
ํจ์(() => import('path')
)๋ฅผ ์ธ์๋ก ๋ฐ์ Proxy ๊ฐ์ฒด๋ฅผ ๋ฐํํ๋ค. ์ด ๋ฐํ๋ Proxy ๊ฐ์ฒด๋ GET ํธ๋ฉ์ ํตํด ์ธ ๋จ๊ณ์ ์ปค์คํฐ๋ง์ด์ง๋ ๋์์ ์ํํ๋ค.
- ๋ชจ๋์ ํ๋กํผํฐ(์ปดํฌ๋ํธ ์ด๋ฆ)์ ์ ๊ทผํ ๋ GET ํธ๋ฉ ์คํ
loader
ํจ์๋ฅผ ํตํด ๋น๋๊ธฐ์ ์ผ๋ก ๋ชจ๋ ๋ก๋(import)- ๋ถ๋ฌ์จ ๋ชจ๋์ ํ๋กํผํฐ(์ปดํฌ๋ํธ) ๋ฐํ
์๋ฅผ๋ค์ด ์๋์ ๊ฐ์ด ๋ ๊ฐ์ ์ปดํฌ๋ํธ๋ฅผ ๋ด๋ณด๋ด๊ณ ์๋ misc.tsx
ํ์ผ์ด ์๋ค๊ณ ๊ฐ์ ํด๋ณด์. ์ด ํ์ผ์ ๋ถ๋ฌ์ค๋ฉด ๋ชจ๋์ {Home: (props) => {...}, About: (props) => {...}}
ํํ๊ฐ ๋๋ค.
// src/features/misc.tsx
export const Home = (props) => { /* ... */ };
export const About = (props) => { /* ... */ };
const { Home } = lazyImport(...)
์ด๋ฐ ์์ผ๋ก Home
์ปดํฌ๋ํธ๋ฅผ ๊ตฌ์กฐ๋ถํดํ ๋นํ๋ฉด GET ํธ๋ฉ์ ๋ ๋ฒ์งธ ์ธ์์ธ name
ํ๋ผ๋ฏธํฐ ๊ฐ์ 'Home'
์ด ๋๋ค. ์ด์ด์ loader
ํจ์๋ฅผ ํตํด misc.tsx
๋ชจ๋์ ๋ถ๋ฌ์จ ํ module['Home']
๋ฐํ ๊ฐ์ธ Home
์ปดํฌ๋ํธ๋ฅผ default
์์ฑ์ ๋ด์์ ๋ฐํํ๋ค.
๋ ํผ๋ฐ์ค
- Allow for named imports in React.lazy · Issue #14603 · facebook/react
- https://github.com/JLarky/react-lazily
๊ธ ์์ ์ฌํญ์ ๋ ธ์ ํ์ด์ง์ ๊ฐ์ฅ ๋น ๋ฅด๊ฒ ๋ฐ์๋ฉ๋๋ค. ๋งํฌ๋ฅผ ์ฐธ๊ณ ํด ์ฃผ์ธ์
'๐ช Programming' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[Algorithm] ๋ ๋ฐ๋จน๊ธฐ ์๊ณ ๋ฆฌ์ฆ / ๋์ ๊ณํ๋ฒ (2) | 2024.05.25 |
---|---|
[JS] split() ๋ฉ์๋์์ ๋น ๋ฌธ์์ด์ด ์๊ธฐ๋ ์๋ฆฌ (0) | 2024.05.24 |
[Vite] ์ด๊ธฐ ๋ก๋ ์๊ฐ ๊ฐ์ ์ ์ํ Vendor Chunk ์ชผ๊ฐ๊ธฐ (0) | 2024.05.24 |
[Markdown] GitHub ๋งํฌ๋ค์ด ์์ฑ ๊ฟํ ๋ชจ์ (0) | 2024.05.23 |
[JS] ์๋ฐ์คํฌ๋ฆฝํธ ES2023 ๋ถ๋ณ์ฑ ๋ฐฐ์ด ๋ฉ์๋ ํบ์๋ณด๊ธฐ (0) | 2024.05.23 |
๋๊ธ
์ด ๊ธ ๊ณต์ ํ๊ธฐ
-
๊ตฌ๋
ํ๊ธฐ
๊ตฌ๋ ํ๊ธฐ
-
์นด์นด์คํก
์นด์นด์คํก
-
๋ผ์ธ
๋ผ์ธ
-
ํธ์ํฐ
ํธ์ํฐ
-
Facebook
Facebook
-
์นด์นด์ค์คํ ๋ฆฌ
์นด์นด์ค์คํ ๋ฆฌ
-
๋ฐด๋
๋ฐด๋
-
๋ค์ด๋ฒ ๋ธ๋ก๊ทธ
๋ค์ด๋ฒ ๋ธ๋ก๊ทธ
-
Pocket
Pocket
-
Evernote
Evernote
๋ค๋ฅธ ๊ธ
-
[Algorithm] ๋ ๋ฐ๋จน๊ธฐ ์๊ณ ๋ฆฌ์ฆ / ๋์ ๊ณํ๋ฒ
[Algorithm] ๋ ๋ฐ๋จน๊ธฐ ์๊ณ ๋ฆฌ์ฆ / ๋์ ๊ณํ๋ฒ
2024.05.25 -
[JS] split() ๋ฉ์๋์์ ๋น ๋ฌธ์์ด์ด ์๊ธฐ๋ ์๋ฆฌ
[JS] split() ๋ฉ์๋์์ ๋น ๋ฌธ์์ด์ด ์๊ธฐ๋ ์๋ฆฌ
2024.05.24 -
[Vite] ์ด๊ธฐ ๋ก๋ ์๊ฐ ๊ฐ์ ์ ์ํ Vendor Chunk ์ชผ๊ฐ๊ธฐ
[Vite] ์ด๊ธฐ ๋ก๋ ์๊ฐ ๊ฐ์ ์ ์ํ Vendor Chunk ์ชผ๊ฐ๊ธฐ
2024.05.24 -
[Markdown] GitHub ๋งํฌ๋ค์ด ์์ฑ ๊ฟํ ๋ชจ์
[Markdown] GitHub ๋งํฌ๋ค์ด ์์ฑ ๊ฟํ ๋ชจ์
2024.05.23