2025.1.13 월요일의 공부기록
Next.js에서는 loading.js
파일과 React Suspense를 활용해 로드 중 상태를 처리하고, 사용자 경험을 개선할 수 있다. 로딩 UI와 스트리밍은 사용자가 콘텐츠를 기다리는 동안 의미 있는 피드백을 제공하는 데 도움을 준다.
loading.js
는 Next.js의 특수 파일로, React Suspense와 통합되어 의미 있는 로딩 UI를 생성할 수 있도록 도와준다.
이 파일은 라우트 세그먼트(route segment)의 콘텐츠가 로드되는 동안 즉시 로드 상태를 표시하며, 로드가 완료되면 새로운 콘텐츠로 자동 교체된다.
사용자가 특정 경로로 탐색하거나 콘텐츠가 로드 중인 상태일 때:
loading.js
파일에서 정의된 로딩 UI가 즉시 렌더링된다.콘텐츠 로드 완료 시:
loading.tsx
사용법app
폴더 하위의 라우트 세그먼트에 loading.tsx
파일을 추가한다.
app/
├── dashboard/
│ ├── loading.tsx // 대체 UI
│ └── page.tsx // 실제 페이지
loading.tsx
예제export default function Loading() {
return (
<div style={{ textAlign: "center", marginTop: "50px" }}>
<p>Loading...</p>
<div className="spinner"></div>
</div>
);
}
/dashboard
경로로 이동하면, 콘텐츠가 로드될 때까지 "Loading..." 메시지와 스피너가 표시된다.React Suspense는 React에서 비동기 데이터를 로드하거나, 컴포넌트가 준비될 때까지 로딩 상태를 관리할 수 있도록 하는 기능이다.
Next.js는 Suspense를 활용하여 콘텐츠를 부분적으로 스트리밍하고, 필요할 때 로드된 부분만 즉시 렌더링한다.
스트리밍 렌더링은 서버에서 완전히 로드된 콘텐츠를 한 번에 전송하지 않고, 부분적으로 전송하여 즉시 렌더링할 수 있도록 한다.
이를 통해 초기 로드 속도가 빨라지고, 대기 시간이 단축된다.
loading.tsx
)를 렌더링한다.loading.js
조합 예제app/
├── dashboard/
│ ├── loading.tsx // 로딩 UI
│ ├── page.tsx // 실제 콘텐츠
│ └── components/
│ ├── Stats.tsx // 느리게 로드되는 컴포넌트
│ └── Profile.tsx
page.tsx
:
import React, { Suspense } from "react";
import Profile from "./components/Profile";
import Stats from "./components/Stats";
export default function DashboardPage() {
return (
<div>
<h1>Dashboard</h1>
<Suspense fallback={<p>Loading Profile...</p>}>
<Profile />
</Suspense>
<Suspense fallback={<p>Loading Stats...</p>}>
<Stats />
</Suspense>
</div>
);
}
Profile.tsx
:
export default function Profile() {
// Simulate delay
return <p>User Profile Data</p>;
}
Stats.tsx
:
export default function Stats() {
// Simulate delay
return <p>Dashboard Statistics</p>;
}
스켈레톤 로딩
로딩 상태를 의미 있게 전달하기 위해 실제 콘텐츠의 레이아웃과 비슷한 스켈레톤 UI를 표시.
export default function Loading() {
return (
<div>
<div className="skeleton-title"></div>
<div className="skeleton-paragraph"></div>
</div>
);
}
페이지 전환 시 스피너
페이지 탐색 중 사용자에게 피드백 제공.
export default function Loading() {
return <div className="spinner">Loading...</div>;
}