React Router μ½λ μ€ν리ν κ³Ό μ±λ₯ μ΅μ νλ₯Ό μν lazyμ Suspense λμ μ»΄ν¬λνΈ λ‘λ©
νλ μΉ μ ν리μΌμ΄μ μ μ μ λ 볡μ‘ν΄μ§κ³ κΈ°λ₯μ΄ νλΆν΄μ§μ λ°λΌ, μ΄κΈ° λ‘λ© μλμ μ 체 μ±λ₯μ΄ μ¬μ©μ κ²½νμ ν° μν₯μ λ―ΈμΉκ² λμμ΅λλ€. νΉν, 리μ‘νΈ(React) κΈ°λ° μ ν리μΌμ΄μ μμλ λΆνμν μλ°μ€ν¬λ¦½νΈ λ²λ€μ ν¬κΈ°κ° 컀μ§λ©΄μ νμ΄μ§ λ‘λ© μκ°μ΄ κΈΈμ΄μ§κ³ , μ¬μ©μ μ΄νλ₯ μ΄ μ¦κ°ν μ μμ΅λλ€. μ΄λ¬ν λ¬Έμ λ₯Ό ν΄κ²°νκΈ° μν΄ λ¦¬μ‘νΈμμλ μ½λ μ€ν리ν (Code Splitting)κ³Ό λμ μ»΄ν¬λνΈ λ‘λ© κΈ°λ²μ λμ νμ¬ μ΄κΈ° λ‘λ© μλλ₯Ό κ°μ νκ³ , μ¬μ©μκ° μ€μ λ‘ νμν 리μμ€λ§ λ‘λν μ μλλ‘ μ΅μ ννλ λ°©λ²μ μ 곡ν©λλ€.

μ΄λ² ν¬μ€ν μμλ 리μ‘νΈμ λ΄μ₯ κΈ°λ₯μΈ lazyμ Suspenseλ₯Ό νμ©νμ¬ μ½λ μ€ν리ν μ ꡬννλ λ°©λ², λμ μ»΄ν¬λνΈ λ‘λ© κΈ°λ²μ ν΅ν μ±λ₯ μ΅μ ν μ λ΅, κ·Έλ¦¬κ³ μ΄λ₯Ό μ€μ νλ‘μ νΈμ μ μ©νλ μ¬λ‘μ λν΄ κ΅¬μ²΄μ μΌλ‘ μκ°ν΄λλ¦¬κ² μ΅λλ€.
μ½λ μ€ν리ν μ κ°λ κ³Ό νμμ±
μ½λ μ€ν리ν μ μ ν리μΌμ΄μ μ μ¬λ¬ κ°μ μμ λ²λ€λ‘ λΆν νμ¬, μ¬μ©μκ° μ²μ μ μν λ λͺ¨λ μμμ ν λ²μ λ‘λνμ§ μκ³ , νμν μμ μ λμ μΌλ‘ νμν λΆλΆλ§ λΆλ¬μ€λ κΈ°μ μ λλ€. μ΄λ₯Ό ν΅ν΄ μ΄κΈ° λ‘λ© μκ°μ λ¨μΆνκ³ , μ¬μ©μ μΈν°λμ μ λ°λΌ μΆκ° 리μμ€λ₯Ό λ‘λνμ¬ ν¨μ¨μ μΈ λ€νΈμν¬ μ¬μ©κ³Ό ν₯μλ μ±λ₯μ κΈ°λν μ μμ΅λλ€.
νΉν, SPA(Single Page Application) ꡬ쑰μ 리μ‘νΈ μ ν리μΌμ΄μ μμλ νμ΄μ§ μ΄λ μμ΄ λͺ¨λ κΈ°λ₯μ νλμ λ²λ€λ‘ μ 곡νλ κ²½μ°κ° λ§μ, μ ν리μΌμ΄μ ν¬κΈ°κ° 컀μ§μλ‘ μ΄κΈ° λ‘λ© μκ°μ΄ κΈΈμ΄μ§λ λ¬Έμ κ° λ°μν©λλ€. μ΄λ¬ν λ¬Έμ μ μ ν΄κ²°νκΈ° μν΄ μ½λ μ€ν리ν μ λ€μκ³Ό κ°μ μ₯μ μ μ 곡ν©λλ€.
- μ΄κΈ° λ‘λ© μλ κ°μ : μ΄κΈ° νμ΄μ§ λ‘λ μ νμν μ΅μνμ μ½λλ§ λ‘λνμ¬ λΉ λ₯Έ λ λλ§μ κ°λ₯νκ² ν©λλ€.
- λ€νΈμν¬ μ¬μ© μ΅μ ν: μ¬μ©μ νλμ λ°λΌ νμν μ½λλ§ λμ μΌλ‘ μμ²νλ―λ‘, λΆνμν λ°μ΄ν° λ€μ΄λ‘λλ₯Ό λ°©μ§ν©λλ€.
- μ¬μ©μ κ²½ν ν₯μ: λΉ λ₯Έ μλ΅μ±κ³Ό λΆλλ¬μ΄ μΈν°λμ μ μ 곡νμ¬ μ λ°μ μΈ μ¬μ©μ λ§μ‘±λλ₯Ό λμ λλ€.
- μ μ§λ³΄μμ± κ°ν: μ ν리μΌμ΄μ μ κΈ°λ₯λ³λ‘ λΆλ¦¬νμ¬ λͺ¨λννλ©΄, μ½λ κ΄λ¦¬ λ° μ λ°μ΄νΈκ° μ©μ΄ν΄μ§λλ€.
리μ‘νΈμ lazyμ Suspenseλ₯Ό νμ©ν λμ μ»΄ν¬λνΈ λ‘λ©
리μ‘νΈλ 16.6 λ²μ λΆν° μ½λ μ€ν리ν μ μν΄ lazyμ Suspense APIλ₯Ό λμ νμμ΅λλ€. μ΄ λ κΈ°λ₯μ νμ©νλ©΄, μ»΄ν¬λνΈλ₯Ό λμ μΌλ‘ λ‘λν μ μμΌλ©°, λ‘λ© μ€μ λ체 UIλ₯Ό μ 곡νλ κ²λ κ°λ₯ν©λλ€.
1. React.lazyλ₯Ό μ΄μ©ν λμ μν¬νΈ
React.lazy ν¨μλ λμ import()λ₯Ό νμ©νμ¬ μ»΄ν¬λνΈλ₯Ό λΉλκΈ°μ μΌλ‘ λ‘λν μ μκ² ν΄μ€λλ€. μ΄λ₯Ό ν΅ν΄ λ²λ€μ μ¬λ¬ κ°μ μ²ν¬(chunk)λ‘ λΆν νκ³ , μ¬μ©μκ° ν΄λΉ μ»΄ν¬λνΈλ₯Ό νμλ‘ ν λλ§ λ‘λν μ μμ΅λλ€.
μλ μμ λ λμ μΌλ‘ λ‘λλλ μ»΄ν¬λνΈλ₯Ό ꡬνν μ¬λ‘μ λλ€.
import React, { lazy, Suspense } from 'react';
// λμ μν¬νΈλ₯Ό ν΅ν΄ μ»΄ν¬λνΈλ₯Ό lazyλ‘ λ‘λν©λλ€.
const LazyComponent = lazy(() => import('./LazyComponent'));
const App = () => {
return (
<div style={{ padding: '20px' }}>
<h2>λμ μ»΄ν¬λνΈ λ‘λ© μμ </h2>
{/* Suspenseλ₯Ό ν΅ν΄ λ‘λ© μνλ₯Ό νμν©λλ€. */}
<Suspense fallback={<div>λ‘λ© μ€μ
λλ€...</div>}>
<LazyComponent />
</Suspense>
</div>
);
};
export default App;
μ μμ μμ LazyComponentλ μ¬μ©μκ° μ€μ λ‘ ν΄λΉ μ»΄ν¬λνΈλ₯Ό νμλ‘ ν λ λ‘λλ©λλ€. Suspense μ»΄ν¬λνΈλ λ‘λ μ€μΈ μνλ₯Ό λ체 UI(μ: λ‘λ© λ©μμ§)λ‘ λ³΄μ¬μ€μΌλ‘μ¨ μ¬μ©μμκ² λͺ νν νΌλλ°±μ μ 곡ν©λλ€.
2. Suspenseμ μν κ³Ό 컀μ€ν°λ§μ΄μ§
Suspenseλ λμ λ‘λ© μ€μ λ체 μ½ν μΈ λ₯Ό νμνλ μν μ νλ©°, λ‘λ© μνλ₯Ό λ³΄λ€ μΈλ°νκ² μ μ΄ν μ μμ΅λλ€. fallback μμ±μ μ¬μ©νλ©΄ λ‘λ© μ€μ 보μ¬μ€ μ»΄ν¬λνΈλ₯Ό μ§μ ν μ μμΌλ©°, μ΄λ₯Ό ν΅ν΄ μ¬μ©μ κ²½νμ κ°μ ν μ μμ΅λλ€.
μλ₯Ό λ€μ΄, λ¨μν λ‘λ© λ©μμ§ λμ μ€νΌλλ μ λλ©μ΄μ ν¨κ³Όλ₯Ό μ μ©ν μλ μμ΅λλ€.
import React, { lazy, Suspense } from 'react';
import Spinner from './Spinner'; // μ€νΌλ μ»΄ν¬λνΈ
const LazyComponent = lazy(() => import('./LazyComponent'));
const App = () => {
return (
<div style={{ padding: '20px' }}>
<h2>λμ μ»΄ν¬λνΈ λ‘λ© - 컀μ€ν°λ§μ΄μ§λ λ‘λ© UI</h2>
<Suspense fallback={<Spinner />}>
<LazyComponent />
</Suspense>
</div>
);
};
export default App;
μ΄μ κ°μ΄, Suspenseμ ν¨κ» 컀μ€ν°λ§μ΄μ§λ λ‘λ© UIλ₯Ό μ 곡νλ©΄ μ¬μ©μλ λ‘λ μ€μλ μκ°μ νΌλλ°±μ λ°κ² λμ΄ μ λ°μ μΈ μΈν°λμ νμ§μ΄ ν₯μλ©λλ€.
κ³ κΈ μ½λ μ€ν리ν μ λ΅
리μ‘νΈμ κΈ°λ³Έ lazyμ Suspense μΈμλ, λ³΄λ€ λ³΅μ‘ν μ ν리μΌμ΄μ μμλ μ¬λ¬ νμ΄μ§λ κΈ°λ₯ λ¨μλ‘ μ½λλ₯Ό λΆλ¦¬νλ μ λ΅μ κ³ λ €ν μ μμ΅λλ€. λνμ μΈ λ°©λ²μΌλ‘λ λ€μκ³Ό κ°μ κΈ°λ²μ΄ μμ΅λλ€.
1. λΌμ°ν κ³Ό κ²°ν©ν μ½λ μ€ν리ν
리μ‘νΈ λΌμ°ν°(React Router)μ μ½λ μ€ν리ν μ κ²°ν©νλ©΄, κ° λΌμ°νΈλ³λ‘ νμν μ»΄ν¬λνΈλ§ λμ μΌλ‘ λ‘λν μ μμ΅λλ€. μ΄λ₯Ό ν΅ν΄, μ¬μ©μκ° λ°©λ¬Ένμ§ μλ νμ΄μ§μ λν 리μμ€ λ‘λλ₯Ό λ°©μ§ν μ μμ΅λλ€.
import React, { lazy, Suspense } from 'react';
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
const HomePage = lazy(() => import('./pages/HomePage'));
const AboutPage = lazy(() => import('./pages/AboutPage'));
const ContactPage = lazy(() => import('./pages/ContactPage'));
const App = () => {
return (
<Router>
<Suspense fallback={<div>νμ΄μ§λ₯Ό λΆλ¬μ€λ μ€μ
λλ€...</div>}>
<Switch>
<Route exact path="/" component={HomePage} />
<Route path="/about" component={AboutPage} />
<Route path="/contact" component={ContactPage} />
</Switch>
</Suspense>
</Router>
);
};
export default App;
μ΄λ¬ν λ°©μμ μ¬μ©μκ° μ€μ λ‘ λ°©λ¬Ένλ νμ΄μ§μ λν΄μλ§ λ¦¬μμ€λ₯Ό λ‘λνλ―λ‘, μ΄κΈ° λ‘λ© μλλ₯Ό λν κ°μ ν μ μμ΅λλ€.
2. λ²λ€ ν¬κΈ° λͺ¨λν°λ§κ³Ό μ΅μ ν
μ½λ μ€ν리ν μ ꡬνν νμλ μ£ΌκΈ°μ μΌλ‘ λ²λ€ ν¬κΈ°λ₯Ό λͺ¨λν°λ§νμ¬, λΆνμν λΌμ΄λΈλ¬λ¦¬λ μ€λ³΅ μ½λκ° ν¬ν¨λμ§ μλλ‘ μ΅μ ννλ κ²μ΄ μ€μν©λλ€. Webpack Bundle Analyzer, Source Map Explorer λ± λꡬλ₯Ό νμ©νμ¬ κ° μ²ν¬μ ν¬κΈ°λ₯Ό λΆμνκ³ , κ°μ κ°λ₯ν λΆλΆμ μ°Ύμλ΄λ κ²μ΄ νμν©λλ€.
3. μΊμ±κ³Ό ν리λ‘λ© μ λ΅
λμ μ»΄ν¬λνΈ λ‘λ© μ, μΊμ± μ λ΅κ³Ό ν리λ‘λ©(Preloading)μ μ μ©νλ©΄ μ¬μ©μκ° νμ΄μ§ μ΄λ μ λμ± λΉ λ₯Έ μλ΅ μλλ₯Ό κ²½νν μ μμ΅λλ€. μλ₯Ό λ€μ΄, μ¬μ©μκ° νΉμ νμ΄μ§λ₯Ό μμ£Ό λ°©λ¬Ένλ€λ©΄, ν΄λΉ νμ΄μ§μ μ»΄ν¬λνΈλ₯Ό 미리 λ‘λν΄λκ±°λ μΊμνμ¬ λ€μ μ κ·Ό μ λΉ λ₯΄κ² λ λλ§ν μ μμ΅λλ€.
μ±λ₯ μ΅μ νμ μ¬μ©μ κ²½ν ν₯μ
μ½λ μ€ν리ν κ³Ό λμ μ»΄ν¬λνΈ λ‘λ©μ μ΄κΈ° λ‘λ© μλλ₯Ό κ°μ νμ¬ μ¬μ©μ κ²½νμ ν₯μμν€λ λ° ν΅μ¬μ μΈ μν μ ν©λλ€. μ΄λ₯Ό ν΅ν΄ μ»μ μ μλ μ£Όμ μ΄μ μ λ€μκ³Ό κ°μ΅λλ€.
- λΉ λ₯Έ μ΄κΈ° λ λλ§: νμν μ΅μνμ μ½λλ§ λ‘λν¨μΌλ‘μ¨, νμ΄μ§ μ΅μ΄ λ λλ§ μκ°μ λ¨μΆν μ μμ΅λλ€.
- ν¨μ¨μ μΈ λ€νΈμν¬ μ¬μ©: μ¬μ©μ μΈν°λμ μ λ°λΌ μΆκ° 리μμ€λ₯Ό λμ μΌλ‘ λ‘λνμ¬, λΆνμν λ€νΈμν¬ μμ²μ μ€μ λλ€.
- λͺ¨λνμ μ μ§λ³΄μμ± κ°ν: κΈ°λ₯λ³λ‘ μ½λλ₯Ό λΆλ¦¬ν¨μΌλ‘μ¨, μ½λ κ΅¬μ‘°κ° λͺ νν΄μ§κ³ μ μ§λ³΄μκ° μ©μ΄ν΄μ§λλ€.
- ν₯μλ μ¬μ©μ μΈν°λμ : Suspenseμ κ°μ λ체 UIλ₯Ό νμ©νμ¬ λ‘λ© μ€μλ μ¬μ©μμκ² λͺ νν νΌλλ°±μ μ 곡, μ λ°μ μΈ UXλ₯Ό κ°μ ν©λλ€.
λν, μ΄λ¬ν μ΅μ ν κΈ°λ²μ λͺ¨λ°μΌ μ¬μ©μλ λ€νΈμν¬ μλκ° λλ¦° νκ²½μμλ ν¨κ³Όμ μ λλ€. μ΄κΈ° λ‘λ©μ΄ λΉ¨λΌμ§μ λ°λΌ μ¬μ©μ μ΄νλ₯ μ΄ μ€μ΄λ€κ³ , μ 체 μ ν리μΌμ΄μ μ λ°μμ±μ΄ ν₯μλμ΄ λ§μ‘±μ€λ¬μ΄ μ¬μ©μ κ²½νμ μ 곡ν©λλ€.
μ€μ νλ‘μ νΈμμμ μ μ© μ¬λ‘
λκ·λͺ¨ 리μ‘νΈ μ ν리μΌμ΄μ μ΄λ λ€μμ νμ΄μ§λ₯Ό κ°μ§ νλ‘μ νΈμμλ μ½λ μ€ν리ν μ μ κ·Ή νμ©νλ κ²μ΄ νμμ μ λλ€. μλ₯Ό λ€μ΄, μ μμκ±°λ μΉμ¬μ΄νΈμμλ ν, μν λͺ©λ‘, μν μμΈ νμ΄μ§, κ²°μ νμ΄μ§ λ± κ° νμ΄μ§λ³λ‘ λ²λ€μ λΆλ¦¬νμ¬ μ¬μ©μμκ² νμν 리μμ€λ§ λ‘λνκ² ν μ μμ΅λλ€. μ΄λ₯Ό ν΅ν΄ μ΄κΈ° λ‘λ© μλλ₯Ό κ°μ νκ³ , μ¬μ©μ νλμ λ°λΌ λΆλλ¬μ΄ νμ΄μ§ μ νμ ꡬνν μ μμ΅λλ€.
λν, κ΄λ¦¬ λꡬλ λμ보λμ κ°μ 볡μ‘ν μΉ μ ν리μΌμ΄μ μμλ λμ λ‘λ©κ³Ό μΊμ± μ λ΅μ κ²°ν©νμ¬, μ¬μ©μκ° νΉμ κΈ°λ₯μ μ¬μ©ν λλ§ ν΄λΉ μ»΄ν¬λνΈλ₯Ό λΆλ¬μ€κ³ , μ¬μ©νμ§ μλ κΈ°λ₯μ λμ€μ λ‘λν μ μλλ‘ μ΅μ νν μ μμ΅λλ€. μ΄λ¬ν μ κ·Ό λ°©μμ μλ² λΆν κ°μμ ν¨κ» ν΄λΌμ΄μΈνΈ μΈ‘ μ±λ₯μ κ·Ήλννλ ν¨κ³Όλ₯Ό κ°μ Έμ΅λλ€.
κ²°λ‘
리μ‘νΈμ lazyμ Suspenseλ₯Ό νμ©ν μ½λ μ€ν리ν κ³Ό λμ μ»΄ν¬λνΈ λ‘λ©μ νλ μΉ μ ν리μΌμ΄μ μ μ±λ₯ μ΅μ νμμ λ§€μ° μ€μν μν μ ν©λλ€. μ΄λ₯Ό ν΅ν΄ μ΄κΈ° λ‘λ© μλλ₯Ό κ°μ νκ³ , μ¬μ©μκ° μ€μ λ‘ νμν 리μμ€λ§ λ‘λνμ¬ λ€νΈμν¬ μ¬μ©μ μ΅μ νν μ μμ΅λλ€. λν, λΌμ°ν κ³Ό κ²°ν©ν μ½λ μ€ν리ν , λ²λ€ ν¬κΈ° λͺ¨λν°λ§, μΊμ± λ° ν리λ‘λ© μ λ΅ λ± λ€μν κΈ°λ²μ ν¨κ» μ μ©νλ©΄, μ¬μ©μ κ²½νκ³Ό μ 체 μ ν리μΌμ΄μ μ ν¨μ¨μ±μ ν¬κ² ν₯μμν¬ μ μμ΅λλ€.
μμΌλ‘μ νλ‘μ νΈμμ 리μ‘νΈ μ ν리μΌμ΄μ μ κ°λ°ν λ, μ½λ μ€ν리ν κΈ°λ²μ μ κ·Ή λμ νμ¬ μ΄κΈ° λ‘λ© μκ°μ λ¨μΆνκ³ , μ¬μ©μμκ² λΉ λ₯΄κ³ λ§€λλ¬μ΄ μΈν°λμ μ μ 곡νμκΈΈ κΆμ₯λ립λλ€. μ΅μ νλ λ²λ€ ꡬμ±κ³Ό λμ λ‘λ© μ λ΅μ μ μ§λ³΄μμ νμ₯μ± μΈ‘λ©΄μμλ ν° μ΄μ μ μ 곡νλ©°, κ°λ°μλ‘μ λ³΄λ€ λͺ¨λνλ μ½λ ꡬ쑰λ₯Ό μ μ§ν μ μλλ‘ λμμ€λλ€.
μ΄μ κ°μ μ κ·Ό λ°©μμ μ¬μ©μμ λ€μν νκ²½μ λ§μΆ μ΅μ μ κ²½νμ μ 곡νκ³ , μΉ μ ν리μΌμ΄μ μ μ±κ³΅μ μΈ μ΄μμ μ€μν μν μ ν κ²μ λλ€.
λκΈ