포스트

[Frontend] Next.js 핵심 기능: App Router, Prerendering, Intercepting Routes 가이드

[Frontend] Next.js 핵심 기능: App Router, Prerendering, Intercepting Routes 가이드

들어가며

Next.js는 React 기반의 풀스택 웹 프레임워크로, 버전 13부터 도입된 App Router와 다양한 렌더링 전략으로 웹 개발의 새로운 패러다임을 제시하고 있습니다. 이번 포스트에서는 Next.js의 핵심 기능인 App Router, Prerendering, 그리고 Intercepting Routes에 대해 상세히 알아보겠습니다.

App Router의 이해

App Router는 Next.js 13에서 도입된 새로운 라우팅 시스템입니다. React Server Components를 기본으로 채택하여 서버 사이드 렌더링의 이점을 극대화했습니다.

주요 특징

1. 파일 시스템 기반 라우팅

파일 시스템을 통한 라우팅은 직관적이고 관리하기 쉽습니다. app 디렉토리 내의 폴더 구조가 곧 URL 경로가 됩니다.

1
2
3
4
5
6
7
8
9
app/
├── layout.tsx      # 루트 레이아웃
├── page.tsx        # 홈페이지
├── about/
│   └── page.tsx    # /about 페이지
└── blog/
    ├── layout.tsx  # 블로그 레이아웃
    └── [slug]/     # 동적 라우팅
        └── page.tsx

2. Server Components의 활용

서버 컴포넌트를 기본으로 사용하여 성능을 최적화할 수 있습니다.

1
2
3
4
5
6
7
8
9
10
11
// app/page.tsx
async function HomePage() {
  const data = await fetchData(); // 서버에서 직접 데이터 페칭
  
  return (
    <div>
      <h1>Welcome to my blog</h1>
      <PostList posts={data} />
    </div>
  );
}

3. 중첩 레이아웃

공통 UI 요소를 효율적으로 재사용할 수 있는 레이아웃 시스템을 제공합니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// app/blog/layout.tsx
export default function BlogLayout({
  children
}: {
  children: React.ReactNode
}) {
  return (
    <div className="blog-layout">
      <nav className="blog-nav">
        {/* 블로그 네비게이션 */}
      </nav>
      {children}
    </div>
  );
}

Prerendering 전략

Next.js는 다양한 렌더링 전략을 제공하여 애플리케이션의 성능을 최적화할 수 있습니다.

1. 정적 생성 (Static Generation)

빌드 시점에 페이지를 미리 생성하여 CDN에서 제공할 수 있습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// app/posts/[id]/page.tsx
export async function generateStaticParams() {
  const posts = await getPosts();
  
  return posts.map((post) => ({
    id: post.id.toString()
  }));
}

export default async function PostPage({ params }: { params: { id: string } }) {
  const post = await getPost(params.id);
  
  return (
    <article>
      <h1>{post.title}</h1>
      <div>{post.content}</div>
    </article>
  );
}

2. 서버 사이드 렌더링 (Server-side Rendering)

요청 시점에 페이지를 생성하여 최신 데이터를 제공할 수 있습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// app/dashboard/page.tsx
export const dynamic = 'force-dynamic';

export default async function DashboardPage({
  searchParams
}: {
  searchParams: { [key: string]: string }
}) {
  const data = await fetchDashboardData(searchParams);
  
  return (
    <div>
      <DashboardMetrics data={data} />
    </div>
  );
}

3. 부분적 프리렌더링 (Partial Prerendering)

Next.js 14에서 도입된 혁신적인 기능으로, 정적 콘텐츠와 동적 콘텐츠를 효과적으로 조합할 수 있습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import { Suspense } from 'react';

export default function Page() {
  return (
    <div>
      <h1>Welcome</h1>
      {/* 정적으로 생성되는 부분 */}
      <StaticContent />
      
      {/* 동적으로 로드되는 부분 */}
      <Suspense fallback={<Loading />}>
        <DynamicContent />
      </Suspense>
    </div>
  );
}

Intercepting Routes

Intercepting Routes는 현재 페이지의 컨텍스트를 유지하면서 새로운 라우트를 오버레이하는 기능입니다.

구현 방법

1. 기본 설정

특수한 파일 명명 규칙을 사용하여 인터셉터 라우트를 구성할 수 있습니다.

1
2
3
4
5
6
7
8
app/
├── feed/
│   └── page.tsx
└── photos/
    ├── [id]/
    │   └── page.tsx
    └── (.)[id]/
        └── page.tsx  // 인터셉터 라우트

2. 모달 구현 예시

1
2
3
4
5
6
7
8
// app/photos/(.)[id]/page.tsx
export default function PhotoModal({ params }: { params: { id: string } }) {
  return (
    <Dialog>
      <PhotoView id={params.id} />
    </Dialog>
  );
}

실제 활용 사례

  1. 모달 다이얼로그
    • 피드에서 사진을 클릭할 때 모달로 표시
    • URL 상태 유지 및 공유 가능
  2. 슬라이드오버
    • 사이드 패널로 추가 정보 표시
    • 메인 컨텐츠의 컨텍스트 유지

성능 최적화 전략

Next.js의 다양한 기능을 활용한 성능 최적화 방법을 알아보겠습니다.

1. Route Segments 최적화

1
2
3
4
5
6
7
8
9
10
11
12
import { Suspense } from 'react';

export default function Layout({ children }) {
  return (
    <>
      <Suspense fallback={<NavSkeleton />}>
        <Navigation />
      </Suspense>
      {children}
    </>
  );
}

2. 데이터 페칭 최적화

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// utils/fetchUtils.ts
export async function fetchWithCache(url: string) {
  const res = await fetch(url, {
    next: {
      revalidate: 3600 // 1시간마다 재검증
    }
  });
  
  if (!res.ok) {
    throw new Error('Failed to fetch data');
  }
  
  return res.json();
}

결론

Next.js의 App Router, Prerendering, 그리고 Intercepting Routes는 현대적인 웹 애플리케이션 개발에 필수적인 도구입니다. 이러한 기능들을 적절히 활용하면 성능이 뛰어나고 사용자 경험이 우수한 웹 애플리케이션을 구축할 수 있습니다.

각 기능은 고유한 장점을 가지고 있으며, 프로젝트의 요구사항에 따라 적절히 조합하여 사용하는 것이 중요합니다. 특히 Next.js 14에서 도입된 부분적 프리렌더링은 정적 생성과 서버 사이드 렌더링의 장점을 모두 활용할 수 있는 혁신적인 기능입니다.

참고자료

이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.