Next.js의 Pages Router vs App Router: 상세 비교 가이드

Next.js의 Pages Router vs App Router: 상세 비교 가이드
Photo by James Wiseman / Unsplash

On this page

Next.js는 React 기반의 강력한 웹 프레임워크로, 서버 사이드 렌더링(SSR)과 정적 사이트 생성(SSG)을 쉽게 구현할 수 있게 해줍니다. Next.js 13 버전부터는 기존의 Pages Router와 함께 새로운 App Router가 도입되었습니다. 이 포스트에서는 두 라우팅 시스템의 차이점을 자세히 살펴보고, 각각의 장단점을 비교해보겠습니다.

목차

  1. Pages Router 소개
  2. App Router 소개
  3. 주요 차이점
  4. Pages Router 예제
  5. App Router 예제
  6. 언제 어떤 라우터를 사용해야 할까?
  7. 결론

Pages Router 소개

Pages Router는 Next.js의 전통적인 라우팅 시스템입니다. 이 시스템은 파일 시스템 기반 라우팅을 사용하며, pages 디렉토리 내의 파일 구조가 곧 애플리케이션의 라우트 구조가 됩니다.

주요 특징:

  • pages 디렉토리 사용
  • 파일 이름 기반의 라우팅
  • getStaticProps, getServerSideProps 등을 통한 데이터 페칭
  • 간단하고 직관적인 구조

App Router 소개

App Router는 Next.js 13에서 도입된 새로운 라우팅 시스템입니다. React 18의 새로운 기능들을 활용하며, 특히 React Server Components를 기본적으로 지원합니다.

주요 특징:

  • app 디렉토리 사용
  • 폴더 구조 기반의 라우팅
  • 레이아웃, 로딩 상태, 에러 처리 등을 위한 특수 파일들
  • 서버 컴포넌트 기본 지원
  • 향상된 성능과 유연성

주요 차이점

  1. 디렉토리 구조
    • Pages Router: pages 디렉토리
    • App Router: app 디렉토리
  2. 라우트 정의
    • Pages Router: 파일 이름으로 라우트 정의
    • App Router: 폴더 이름으로 라우트 정의, page.js 파일이 해당 라우트의 UI를 담당
  3. 레이아웃
    • Pages Router: _app.js_document.js로 전역 레이아웃 관리
    • App Router: 각 폴더에 layout.js 파일을 두어 중첩 레이아웃 쉽게 구현
  4. 데이터 페칭
    • Pages Router: getStaticProps, getServerSideProps 등의 특수 함수 사용
    • App Router: 컴포넌트 내에서 직접 async/await 사용 가능
  5. 서버 컴포넌트
    • Pages Router: 클라이언트 컴포넌트만 사용
    • App Router: 서버 컴포넌트 기본 지원, 'use client' 지시어로 클라이언트 컴포넌트 지정
  6. 동적 라우트
    • Pages Router: [param].js 파일로 동적 라우트 생성
    • App Router: [param] 폴더로 동적 라우트 생성

Pages Router 예제

다음은 Pages Router를 사용한 간단한 블로그 애플리케이션의 예제입니다:

pages/
  index.js
  about.js
  posts/
    [id].js

pages/index.js

import Link from 'next/link'

export default function Home() {
  return (
    <div>
      <h1>Welcome to my blog</h1>
      <Link href="/about">About</Link>
      <Link href="/posts/1">First Post</Link>
    </div>
  )
}

pages/about.js

export default function About() {
  return <h1>About Us</h1>
}

pages/posts/[id].js

import { useRouter } from 'next/router'

export default function Post() {
  const router = useRouter()
  const { id } = router.query

  return <h1>Post: {id}</h1>
}

export async function getServerSideProps(context) {
// 서버 사이드에서 데이터 페칭
  return {
    props: {},// 컴포넌트에 전달할 props
  }
}

App Router 예제

같은 블로그 애플리케이션을 App Router로 구현해보겠습니다:

app/
  layout.js
  page.js
  about/
    page.js
  posts/
    [id]/
      page.js

app/layout.js

export default function RootLayout({ children }) {
  return (
    <html lang="en">
      <body>{children}</body>
    </html>
  )
}

app/page.js

import Link from 'next/link'

export default function Home() {
  return (
    <div>
      <h1>Welcome to my blog</h1>
      <Link href="/about">About</Link>
      <Link href="/posts/1">First Post</Link>
    </div>
  )
}

app/about/page.js

export default function About() {
  return <h1>About Us</h1>
}

app/posts/[id]/page.js

export default function Post({ params }) {
  return <h1>Post: {params.id}</h1>
}

// 서버 컴포넌트에서 직접 데이터 페칭
export async function generateMetadata({ params }) {
  const post = await fetchPost(params.id)
  return { title: post.title }
}

언제 어떤 라우터를 사용해야 할까?

  1. Pages Router 사용이 좋은 경우:
    • 기존 Next.js 프로젝트를 유지보수하는 경우
    • 팀이 새로운 App Router에 익숙하지 않은 경우
    • 간단한 웹사이트나 애플리케이션을 빠르게 개발해야 하는 경우
  2. App Router 사용이 좋은 경우:
    • 새로운 프로젝트를 시작하는 경우
    • 서버 컴포넌트의 이점을 활용하고 싶은 경우
    • 복잡한 레이아웃 구조가 필요한 경우
    • 최신 React 기능을 최대한 활용하고 싶은 경우

결론

Pages Router와 App Router는 각각의 장단점이 있습니다. Pages Router는 간단하고 직관적이지만, App Router는 더 강력하고 유연한 기능을 제공합니다. 프로젝트의 요구사항과 팀의 숙련도를 고려하여 적절한 라우팅 시스템을 선택하는 것이 중요합니다. Next.js는 두 시스템을 동시에 지원하므로, 필요에 따라 점진적으로 App Router로 마이그레이션할 수 있습니다.

Next.js의 발전과 함께 App Router가 더욱 중요해질 것으로 예상되므로, 새로운 프로젝트를 시작한다면 App Router를 고려해보는 것이 좋겠습니다. 하지만 궁극적으로는 프로젝트의 특성과 팀의 상황에 가장 적합한 선택을 해야 합니다.

실제 차이 예시

PagesRouter

import type { NextApiRequest, NextApiResponse } from 'next'

export default async function handler(req: NextApiRequest, res: NextApiResponse) {
  const { memberIdx, page = '0', size = '10' } = req.query;

  try {
    const response = await fetch(`${process.env.API_BASE_URL}/short-url/list?memberIdx=${memberIdx}&page=${page}&size=${size}`, {
      headers: {
        // 필요한 경우 인증 헤더 등을 추가
      },
    });

    if (!response.ok) {
      throw new Error('Failed to fetch short URLs');
    }

    const data = await response.json();
    res.status(200).json(data);
  } catch (error) {
    console.error('Error fetching short URLs:', error);
    res.status(500).json({ error: 'Failed to fetch short URLs' });
  }
}

AppRouter

import { NextResponse } from 'next/server';

export async function GET(request: Request) {
  const { searchParams } = new URL(request.url);
  const memberIdx = searchParams.get('memberIdx');
  const page = searchParams.get('page') || '0';
  const size = searchParams.get('size') || '10';

  try {
    const response = await fetch(`${process.env.API_BASE_URL}/short-url/list?memberIdx=${memberIdx}&page=${page}&size=${size}`, {
      headers: {
        // 필요한 경우 인증 헤더 등을 추가
      },
    });

    console.log(response);

    if (!response.ok) {
      throw new Error('Failed to fetch short URLs');
    }

    const data = await response.json();
    return NextResponse.json(data);
  } catch (error) {
    console.error('Error fetching short URLs:', error);
    return NextResponse.json({ error: 'Failed to fetch short URLs' }, { status: 500 });
  }
}

실제 사용 경험과 추세

  1. Pages Router 선호 이유:
    • 익숙함: 많은 개발자들이 이미 Pages Router에 익숙합니다.
    • 단순성: 간단한 프로젝트에서는 Pages Router가 더 직관적일 수 있습니다.
    • 안정성: Pages Router는 오랜 기간 사용되어 안정적입니다.
    • 학습 곡선: App Router는 새로운 개념 학습이 필요합니다.
  2. App Router 불편 사항:
    • 복잡성: 일부 개발자들은 App Router의 구조가 더 복잡하다고 느낍니다.
    • 호환성 문제: 일부 라이브러리가 App Router와 완벽히 호환되지 않을 수 있습니다.
    • 변화 속도: Next.js의 빠른 변화로 인한 학습 부담이 있습니다.
  3. 실제 사용 추세:
    • 점진적 도입: 많은 팀들이 새 프로젝트에서 App Router를 시도하고 있습니다.
    • 혼합 사용: 일부는 두 라우터를 혼합해서 사용하며 점진적으로 전환합니다.
    • 기업 환경: 대규모 기업에서는 안정성 때문에 Pages Router를 선호하는 경향이 있습니다.

Subscribe to Keun's Story newsletter and stay updated.

Don't miss anything. Get all the latest posts delivered straight to your inbox. It's free!
Great! Check your inbox and click the link to confirm your subscription.
Error! Please enter a valid email address!