페이지 라우팅 기초 (App Router)
App Router를 사용하여 기본적인 페이지 라우팅 방법을 학습합니다.
📌 이번 회차 학습 목표
- Next.js App Router의 기본 개념을 이해하고 설명할 수 있습니다.
- 파일 시스템 기반 라우팅 원리를 파악하고, 이를 통해 페이지를 생성할 수 있습니다.
- 정적 라우팅과 동적 라우팅의 차이를 이해하고, 각각의 사용 사례를 구분할 수 있습니다.
- Next.js 프로젝트 내에서 새로운 페이지를 생성하고 접근하는 방법을 실습할 수 있습니다.
- 레이아웃(Layout)과 페이지(Page) 파일의 역할을 구분할 수 있습니다.
📝 개념 설명
App Router란 무엇인가요?
Next.js 13 버전부터 도입된 App Router는 React Server Components를 기반으로 하는 새로운 라우팅 패러다임입니다. 기존의 Pages Router가 클라이언트 사이드 렌더링(CSR)과 서버 사이드 렌더링(SSR)을 혼합하여 사용했던 것과 달리, App Router는 기본적으로 서버 컴포넌트(Server Components)를 사용하여 더 나은 성능과 개발 경험을 제공합니다.
App Router는 프로젝트의 app 디렉토리 내에서 작동하며, 파일 시스템을 기반으로 라우팅을 정의합니다. 즉, 특정 경로에 파일을 생성하는 것만으로 해당 경로에 접근할 수 있는 페이지를 만들 수 있습니다.
파일 시스템 기반 라우팅의 원리
App Router는 app 디렉토리 내의 폴더 구조를 기반으로 라우팅 경로를 결정합니다. 각 폴더는 URL 경로 세그먼트에 해당하며, 폴더 내에 page.js, page.jsx, page.ts, 또는 page.tsx 파일을 생성하면 해당 경로에 대한 UI가 렌더링됩니다.
예를 들어, app/dashboard/page.js 파일을 생성하면 /dashboard 경로로 접근할 수 있게 됩니다. 이는 직관적이고 관리하기 쉬운 라우팅 방식을 제공합니다.
app 디렉토리 생성app/about)page.js 파일 생성 (예: app/about/page.js)/about)로 접근 가능page.js 파일의 역할
page.js 파일은 특정 경로에 대한 고유한 UI를 렌더링하는 페이지 컴포넌트를 정의합니다. 이 파일은 항상 export default로 React 컴포넌트를 내보내야 합니다. 이 컴포넌트가 해당 경로에 접속했을 때 사용자에게 보여지는 내용이 됩니다.
layout.js 파일의 역할
layout.js 파일은 해당 폴더 및 그 하위 폴더의 모든 페이지에 적용되는 공유 UI를 정의합니다. 예를 들어, app/layout.js는 전체 애플리케이션에 적용되는 최상위 레이아웃이 되며, app/dashboard/layout.js는 /dashboard 경로와 그 하위 경로에만 적용되는 레이아웃이 됩니다.
레이아웃 컴포넌트는 반드시 children prop을 받아야 하며, 이 children prop은 해당 레이아웃이 감싸는 페이지 또는 하위 레이아웃을 나타냅니다. 이를 통해 중첩된 레이아웃 구조를 만들 수 있습니다.
page.jslayout.js정적 라우팅과 동적 라우팅
- 정적 라우팅 (Static Routing): 경로가 고정되어 있는 라우팅 방식입니다. 예를 들어,
app/about/page.js는 항상/about경로에 매핑됩니다. - 동적 라우팅 (Dynamic Routing): 경로의 일부가 변할 수 있는 라우팅 방식입니다. 대괄호
[]를 사용하여 동적 세그먼트를 정의합니다. 예를 들어,app/products/[id]/page.js는/products/1,/products/abc등id부분이 변하는 모든 경로에 매핑됩니다. 동적 세그먼트의 값은 페이지 컴포넌트의paramsprop을 통해 접근할 수 있습니다.
💡 예제 & 실습
Next.js 프로젝트를 생성하고 App Router를 사용하여 기본적인 페이지 라우팅을 실습해 보겠습니다.
1단계: Next.js 프로젝트 생성
먼저 터미널을 열고 다음 명령어를 실행하여 새로운 Next.js 프로젝트를 생성합니다.
npx create-next-app@latest nextjs-app-router-basic --use-pnpm설치 과정에서 다음과 같이 선택합니다:
- Would you like to use TypeScript? No
- Would you like to use ESLint? Yes
- Would you like to use Tailwind CSS? No
- Would you like to use `src/` directory? No
- Would you like to use App Router? (recommended) Yes
- Would you like to customize the default import alias (@/*)? No
프로젝트 생성이 완료되면, 생성된 디렉토리로 이동합니다.
cd nextjs-app-router-basic2단계: 기본 페이지 확인
프로젝트를 VS Code와 같은 코드 에디터로 열어보세요. app 디렉토리 안에 page.js와 layout.js 파일이 이미 생성되어 있을 것입니다.
app/layout.js: 애플리케이션의 최상위 레이아웃입니다. HTML 문서의 기본 구조를 정의합니다.
// app/layout.js
import './globals.css';
export const metadata = {
title: 'Next.js App Router Basic',
description: 'Generated by create next app',
};
export default function RootLayout({ children }) {
return (
<html lang='ko'>
<body>{children}</body>
</html>
);
}app/page.js: 루트 경로(/)에 해당하는 페이지입니다.
// app/page.js
export default function Home() {
return (
<main>
<h1>환영합니다! Next.js App Router 기본 페이지입니다.</h1>
<p>이것은 루트 경로(/) 페이지입니다.</p>
</main>
);
}프로젝트를 실행하여 기본 페이지를 확인해 보세요.
pnpm dev브라우저에서 http://localhost:3000으로 접속하면 app/page.js의 내용이 보일 것입니다.
3단계: 새로운 정적 페이지 생성
/about 경로에 접근할 수 있는 ‘소개’ 페이지를 만들어 보겠습니다.
app디렉토리 안에about이라는 새 폴더를 생성합니다:app/aboutapp/about폴더 안에page.js파일을 생성합니다.
// app/about/page.js
export default function AboutPage() {
return (
<main>
<h1>회사 소개 페이지</h1>
<p>저희는 Next.js App Router를 학습하는 팀입니다.</p>
<p><a href='/'>홈으로 돌아가기</a></p>
</main>
);
}이제 브라우저에서 http://localhost:3000/about으로 접속하면 ‘회사 소개 페이지’가 나타나는 것을 확인할 수 있습니다.
4단계: 중첩된 레이아웃 생성
/dashboard 경로와 그 하위 경로에만 적용되는 레이아웃을 만들어 보겠습니다.
app디렉토리 안에dashboard폴더를 생성합니다:app/dashboardapp/dashboard폴더 안에layout.js파일을 생성합니다.
// app/dashboard/layout.js
export default function DashboardLayout({ children }) {
return (
<html lang='ko'>
<body>
<header style={{ background: '#eee', padding: '10px' }}>
<nav>
<a href='/dashboard' style={{ marginRight: '10px' }}>대시보드 홈</a>
<a href='/dashboard/settings'>설정</a>
</nav>
</header>
<main style={{ padding: '20px' }}>
{children}
</main>
<footer style={{ background: '#eee', padding: '10px', marginTop: '20px' }}>
<p>대시보드 푸터</p>
</footer>
</body>
</html>
);
}주의: app/dashboard/layout.js는 app/layout.js와 독립적으로 동작합니다. app/dashboard/layout.js는 자체적으로 <html>과 <body> 태그를 포함하여 독립적인 문서 구조를 가지도록 작성되었습니다. 실제 프로젝트에서는 app/layout.js가 <html>과 <body>를 제공하고, 하위 레이아웃은 <main> 태그 내에서 children을 렌더링하는 형태로 중첩됩니다. 여기서는 이해를 돕기 위해 독립적인 구조로 작성했습니다.
app/dashboard폴더 안에page.js파일을 생성하여 대시보드 홈 페이지를 만듭니다.
// app/dashboard/page.js
export default function DashboardHomePage() {
return (
<div>
<h2>대시보드 홈</h2>
<p>대시보드에 오신 것을 환영합니다!</p>
</div>
);
}app/dashboard폴더 안에settings폴더를 만들고, 그 안에page.js파일을 생성하여 설정 페이지를 만듭니다.
// app/dashboard/settings/page.js
export default function SettingsPage() {
return (
<div>
<h2>설정 페이지</h2>
<p>여기서 대시보드 설정을 변경할 수 있습니다.</p>
<p><a href='/dashboard'>대시보드 홈으로 돌아가기</a></p>
</div>
);
}이제 브라우저에서 http://localhost:3000/dashboard 또는 http://localhost:3000/dashboard/settings로 접속하면, app/dashboard/layout.js에 정의된 헤더와 푸터가 적용된 페이지를 볼 수 있습니다.
5단계: 동적 라우팅 생성
사용자 프로필 페이지와 같이 동적인 경로를 만들어 보겠습니다.
app디렉토리 안에users폴더를 생성합니다:app/usersapp/users폴더 안에[id]라는 새 폴더를 생성합니다:app/users/[id]
이[id]가 동적 세그먼트입니다.app/users/[id]폴더 안에page.js파일을 생성합니다.
// app/users/[id]/page.js
export default function UserProfilePage({ params }) {
return (
<main>
<h1>사용자 프로필 페이지</h1>
<p>사용자 ID: <strong>{params.id}</strong></p>
<p><a href='/'>홈으로 돌아가기</a></p>
</main>
);
}이제 브라우저에서 http://localhost:3000/users/123 또는 http://localhost:3000/users/john-doe와 같이 /users/ 뒤에 어떤 값을 넣어도 해당 페이지가 렌더링되고, params.id를 통해 그 값을 가져올 수 있습니다.
⚠️ 자주 틀리는 것 / 주의사항
page.js또는layout.js파일명 오타: 파일 시스템 라우팅은 정확한 파일명을 요구합니다.page.js,layout.js와 같이 정확하게 작성해야 합니다.app디렉토리 외부에서 라우팅 정의: App Router는app디렉토리 내에서만 작동합니다.pages디렉토리에 파일을 생성하면 Pages Router 방식으로 처리되므로 혼동하지 않도록 주의해야 합니다.- 레이아웃 파일에서
childrenprop 누락:layout.js컴포넌트는 반드시childrenprop을 받아 렌더링해야 합니다. 그렇지 않으면 하위 페이지나 레이아웃의 내용이 표시되지 않습니다. - 동적 라우팅 폴더명 오타:
[id]와 같이 대괄호를 사용하여 동적 세그먼트를 정의할 때, 대괄호를 빠뜨리거나 다른 문자를 사용하지 않도록 주의해야 합니다. - 서버 컴포넌트와 클라이언트 컴포넌트 혼동: App Router의 기본은 서버 컴포넌트입니다. 브라우저에서 인터랙티브한 기능을 사용하려면 파일 상단에
'use client';지시어를 추가하여 클라이언트 컴포넌트로 명시해야 합니다. (이 부분은 다음 회차에서 더 자세히 다룰 예정입니다.)
🔗 다음 회차 예고
이번 회차에서는 App Router를 이용한 기본적인 페이지 라우팅 방법을 학습했습니다. 다음 회차에서는 ‘클라이언트 컴포넌트와 서버 컴포넌트 이해’를 주제로, Next.js App Router의 핵심 개념인 서버 컴포넌트와 클라이언트 컴포넌트의 차이점, 그리고 각각의 사용 시기와 방법을 심도 있게 다룰 예정입니다. 이를 통해 더욱 효율적이고 성능 좋은 Next.js 애플리케이션을 개발하는 기반을 다질 수 있을 것입니다.
- Next.js App Router는
app디렉토리 내의 파일 시스템을 기반으로 라우팅을 정의합니다. page.js파일은 특정 경로의 UI를 렌더링하며,layout.js파일은 해당 경로 및 하위 경로의 공유 UI를 정의합니다.- 정적 라우팅은 고정된 경로를, 동적 라우팅은
[폴더명]과 같이 변할 수 있는 경로를 정의합니다. layout.js는 반드시childrenprop을 받아 하위 콘텐츠를 렌더링해야 합니다.- App Router는 기본적으로 서버 컴포넌트 기반으로 작동하며, 클라이언트 컴포넌트는
'use client';지시어를 통해 명시적으로 선언합니다.