새발블로그
[Next.js] 동적 컴포넌트 로딩으로 분석 페이지 최적화 본문
1. 문제 상황
처음에는 분석 페이지에 필요한 모든 컴포넌트와 차트 라이브러리를 한 번에 import했습니다.
- 종합/가스/전기 모든 탭의 차트가 초기 번들에 포함
- 탭을 보지 않아도 모든 차트 컴포넌트가 준비될 때까지 기다려야 함
- 결과적으로 첫 진입이 너무 느리고, 개발 서버 HMR도 둔감
// (Before) 전부 정적 로딩 — 첫 진입이 무거움
import { ComposedChart, LineChart, BarChart, ... } from "recharts";
// ...중략...
<TabsContent value="comprehensive">
{/* 이 안에서 바로 차트 그리기 */}
<ComposedChart data={yearOverYearData}>...</ComposedChart>
</TabsContent>
<TabsContent value="gas">
<ComposedChart data={gasExpenseData}>...</ComposedChart>
</TabsContent>
<TabsContent value="electric">
<ComposedChart data={electricExpenseData}>...</ComposedChart>
</TabsContent>
2. 해결 방법: next/dynamic으로 탭 단위 분리
차트가 들어있는 무거운 탭을 동적 import로 분리했습니다.
- ssr: false: 클라이언트 전용으로 실행
- loading: 로딩 중에 보여줄 스피너 UI 제공
import dynamic from "next/dynamic";
import { Spinner } from "@/components/ui/spinner";
function SpinnerUI() {
return <div className="flex justify-center p-4"><Spinner /></div>;
}
// 탭 컴포넌트 동적 로딩
const ComprehensiveAnalysisTab = dynamic(
() => import("@/components/analysis/ComprehensiveAnalysisTab"),
{ ssr: false, loading: () => <SpinnerUI /> }
);
const GasAnalysisTab = dynamic(
() => import("@/components/analysis/GasAnalysisTab"),
{ ssr: false, loading: () => <SpinnerUI /> }
);
const ElectricAnalysisTab = dynamic(
() => import("@/components/analysis/ElectricAnalysisTab"),
{ ssr: false, loading: () => <SpinnerUI /> }
);
이제 페이지에서는 탭만 정의해두고, 실제 컴포넌트는 탭이 열릴 때 네트워크로 가져오도록 변경했습니다.
<Tabs value={analysisTab} onValueChange={setAnalysisTab}>
<TabsList> ... </TabsList>
<TabsContent value="comprehensive">
<ComprehensiveAnalysisTab {...props} />
</TabsContent>
<TabsContent value="gas">
<GasAnalysisTab {...props} />
</TabsContent>
<TabsContent value="electric">
<ElectricAnalysisTab {...props} />
</TabsContent>
</Tabs>
3. 효과
- 초기 번들에서 차트 관련 코드 제외 → 첫 화면 로딩 속도 개선
- 탭에 들어갈 때만 차트 로딩 → 불필요한 지연 제거
- 개발 서버 HMR 속도도 눈에 띄게 빨라짐