본문 바로가기

개발 공부/React

Next.js loading.tsx

Next.js에서 loading.tsx는 로딩 UI를 제공하는 컴포넌트 파일로, App Router (app/ 디렉터리)에서 동적 데이터를 가져올 때 자동으로 사용됩니다.

이를 활용하면 데이터 로딩 중에도 부드러운 사용자 경험(UX)을 제공할 수 있습니다.

 

 

loading.tsx의 역할

  • 자동 로딩 UI 제공: Next.js가 데이터를 불러오는 동안 loading.tsx가 자동으로 렌더링됩니다.
  • 서버 및 클라이언트 컴포넌트에서 사용 가능: 서버에서 데이터를 가져오거나, 클라이언트에서 Suspense를 사용할 때 적용할 수 있습니다.
  • 레이아웃(layout.tsx)에도 적용 가능: 특정 경로에 대한 전체 로딩 UI를 설정할 수도 있습니다.
 
 
 

특정 경로에서 loading.tsx를 생성하면, 해당 경로가 로딩 중일 때 자동으로 표시됩니다.

예시 /dashboard의 로딩 UI 추가

app/dashboard/loading.tsx

export default function Loading() {
  return <p>Loading Dashboard...</p>;
}
  • /dashboard 페이지가 서버에서 데이터를 가져오는 동안 "Loading Dashboard..."가 표시됩니다.
 

loading.tsx가 실행되는 시점

  • 서버에서 데이터를 패칭하는 동안 (fetch(), 데이터베이스 요청 등)
  • Suspense를 사용할 때 (React.lazy, 클라이언트 사이드 컴포넌트 등)
  • 레이아웃(layout.tsx)이 적용된 하위 페이지가 로딩될 때
  • 즉, 특정 페이지가 완전히 렌더링되기 전에 Next.js가 자동으로 loading.tsx를 보여줍니다.
 
 

서버 데이터 패칭과 로딩 UI 적용하기

app/dashboard/page.tsx

export default async function DashboardPage() {
  const data = await fetch("https://jsonplaceholder.typicode.com/posts")
    .then((res) => res.json());

  return (
    <div>
      <h1>Dashboard</h1>
      <ul>
        {data.slice(0, 5).map((post: any) => (
          <li key={post.id}>{post.title}</li>
        ))}
      </ul>
    </div>
  );
}
  • fetch()를 사용하여 데이터를 가져오는 동안 /dashboard/loading.tsx가 먼저 렌더링됩니다.
 

레이아웃(layout.tsx)과 함께 사용하기

loading.tsx는 특정 경로(app/dashboard/)의 모든 하위 페이지에도 적용할 수 있습니다.

app/dashboard/layout.tsx

export default function DashboardLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <div>
      <h1>Dashboard Layout</h1>
      {children}
    </div>
  );
}

 

app/dashboard/loading.tsx

export default function Loading() {
  return <p>🔥 Loading Dashboard Content...</p>;
}
  • 이제 /dashboard/* 경로의 모든 페이지가 로딩될 때 loading.tsx가 표시됩니다.
 

Suspense와 함께 사용하기 (클라이언트 컴포넌트)

Next.js의 Suspense를 활용하면 클라이언트 사이드에서도 loading.tsx 대신 별도의 로딩 UI를 설정할 수 있습니다.

app/dashboard/page.tsx

import { Suspense } from "react";
import DashboardContent from "./DashboardContent";

export default function DashboardPage() {
  return (
    <Suspense fallback={<p>⏳ Loading Content...</p>}>
      <DashboardContent />
    </Suspense>
  );
}

app/dashboard/DashboardContent.tsx

export default async function DashboardContent() {
  const data = await fetch("https://jsonplaceholder.typicode.com/posts").then((res) => res.json());

  return (
    <ul>
      {data.slice(0, 5).map((post: any) => (
        <li key={post.id}>{post.title}</li>
      ))}
    </ul>
  );
}
  •  Suspense의 fallback을 설정하면, loading.tsx가 아니라 특정 컴포넌트의 로딩 UI를 지정할 수도 있습니다.

'개발 공부 > React' 카테고리의 다른 글

React Virtual DOM  (0) 2025.04.09
React 함수형 컴포넌트 vs 클래스형 컴포넌트  (0) 2025.04.06
React Focus Lock  (0) 2025.03.22
Next.js LoginForm  (0) 2025.03.19
Next.js Metadata  (0) 2025.03.10