Next.jsNext.js 기초강의 8개 중 2번째난이도 기초

페이지와 라우팅 — 동적 라우트와 레이아웃

발행 읽는 시간 약 1 분

  • Next.js
  • 라우팅
  • 동적라우트
  • 레이아웃
  • Link

강의 소개

Next.js App Router에서 동적 라우트, 중첩 레이아웃, 라우트 그룹, 병렬 라우트를 구현하는 방법을 배웁니다. Link 컴포넌트와 useRouter도 익힙니다.

파일 기반 라우팅#

Text
app/
├── page.tsx              → /
├── about/page.tsx        → /about
├── blog/
│   ├── page.tsx          → /blog
│   └── [slug]/page.tsx   → /blog/my-post
├── shop/
│   └── [...category]/    → /shop/a/b/c (catch-all)
│       └── page.tsx
└── (auth)/               → 라우트 그룹 (URL에 영향 없음)
    ├── login/page.tsx    → /login
    └── signup/page.tsx   → /signup

동적 라우트#

TSX
// app/users/[id]/page.tsx
interface UserPageProps {
    params: { id: string };
    searchParams: { tab?: string };
}

export default async function UserPage({ params, searchParams }: UserPageProps) {
    const user = await fetchUser(params.id);
    const tab = searchParams.tab ?? "profile";

    return (
        <div>
            <h1>{user.name}</h1>
            <p>탭: {tab}</p>
        </div>
    );
}

// generateStaticParams: 빌드 시 정적 생성
export async function generateStaticParams() {
    const users = await fetchAllUsers();
    return users.map(user => ({ id: user.id }));
}

중첩 레이아웃#

TSX
// app/dashboard/layout.tsx
// /dashboard/* 모든 경로에 적용됨
export default function DashboardLayout({
    children,
}: {
    children: React.ReactNode;
}) {
    return (
        <div className="flex">
            <aside className="w-64 bg-gray-100">
                <nav>
                    <a href="/dashboard">홈</a>
                    <a href="/dashboard/analytics">분석</a>
                    <a href="/dashboard/settings">설정</a>
                </nav>
            </aside>
            <main className="flex-1 p-6">{children}</main>
        </div>
    );
}

라우트 그룹#

URL에 영향 없이 폴더로 구분할 때 사용합니다.

Text
app/
├── (marketing)/          ← URL에 포함 안 됨
│   ├── layout.tsx        ← 마케팅 레이아웃
│   ├── page.tsx          → /
│   └── about/page.tsx    → /about
└── (dashboard)/
    ├── layout.tsx        ← 대시보드 레이아웃
    └── analytics/
        └── page.tsx      → /analytics

TSX
import Link from "next/link";

function Navigation() {
    return (
        <nav>
            {/* 기본 */}
            <Link href="/">홈</Link>

            {/* 동적 */}
            <Link href={`/users/${userId}`}>프로필</Link>

            {/* 쿼리 파라미터 */}
            <Link href={{ pathname: "/search", query: { q: "react" } }}>
                검색
            </Link>

            {/* prefetch 비활성 */}
            <Link href="/heavy-page" prefetch={false}>
                무거운 페이지
            </Link>
        </nav>
    );
}

프로그래밍 방식 이동#

TSX
"use client";
import { useRouter, usePathname, useSearchParams } from "next/navigation";

function SearchForm() {
    const router = useRouter();
    const pathname = usePathname();       // 현재 경로
    const searchParams = useSearchParams();

    function handleSearch(query: string) {
        const params = new URLSearchParams(searchParams.toString());
        params.set("q", query);
        router.push(`${pathname}?${params.toString()}`);
    }

    function goBack() {
        router.back();
    }

    function refresh() {
        router.refresh();  // 서버 컴포넌트 데이터 재요청
    }
}

특수 파일#

Text
app/
├── page.tsx          ← 페이지 UI
├── layout.tsx        ← 레이아웃 (유지됨)
├── loading.tsx       ← 로딩 UI (Suspense 자동 적용)
├── error.tsx         ← 에러 UI (Error Boundary 자동 적용)
├── not-found.tsx     ← 404 UI
└── template.tsx      ← 레이아웃과 유사하나 매번 새로 마운트
TSX
// app/loading.tsx
export default function Loading() {
    return <div className="spinner">로딩 중...</div>;
}

// app/error.tsx
"use client";
export default function Error({
    error,
    reset,
}: {
    error: Error;
    reset: () => void;
}) {
    return (
        <div>
            <p>오류 발생: {error.message}</p>
            <button onClick={reset}>다시 시도</button>
        </div>
    );
}

정리#

파일/폴더역할
page.tsx라우트 UI
layout.tsx공유 레이아웃
loading.tsx로딩 상태
error.tsx에러 상태
[param]동적 세그먼트
(group)URL 없는 폴더 그룹
Link클라이언트 사이드 이동
useRouter프로그래밍 이동

다음 편에서는 데이터 패칭 — 서버 컴포넌트에서 데이터를 가져오고 캐싱하는 방법을 배웁니다.

Follow · Ask · Work

이 글이 도움이 됐다면

짧은 작업 기록과 데모는 인스타그램에 올립니다. 만들고 싶은 것이 있다면 프로젝트 의뢰나 협업 제안도 편하게 보내 주세요.

글쓴이

파란여우

직접 만든 AI 앱·제품의 개발·배포를 공개하는 실전형 테크 크리에이터

파란여우 소개 Instagram @bluefox._.hi

이어서 보기

만들고 싶은 것이 있다면 프로젝트 의뢰로 알려 주세요.