본문으로 건너뛰기

안동민 개발노트

본문 시작

페이지 생성

app 폴더에 page.tsx를 배치해 About과 대시보드 페이지를 만들고 중첩 경로와 Link 이동을 확인합니다.

이제 App Router의 기본 구조를 이해했으니, 실제로 페이지를 생성하고 브라우저에서 확인하는 실습을 진행해 볼 시간입니다.

이 절에서는 새 폴더와 page.tsx가 URL을 만드는 규칙, 중첩 라우트(Nested Routes), 그리고 <Link> 이동을 단계별로 안내합니다.

새 페이지는 폴더와 page.tsx가 함께 있어야 URL로 열린다

about 페이지 실습은 폴더 생성, page.tsx 작성, 브라우저 확인의 세 조건을 맞추는 과정이다.

작업파일 위치URL 결과확인 기준
라우트 폴더 만들기src/app/about/about 후보 경로폴더만 있으면 아직 화면은 없음
page.tsx 추가src/app/about/page.tsx/about 접근 가능default export 컴포넌트가 화면 담당
내용 작성AboutPage 컴포넌트서버에서 HTML 생성use client가 없으면 서버 컴포넌트
개발 서버 확인npm run devlocalhost:3000/aboutAbout Us 화면이 보이면 성공
문제 발생 시폴더명과 파일명 재확인404 또는 빈 화면about/page.tsx 철자와 위치부터 확인

첫 번째 새 페이지 만들기: about 페이지

가장 기본적인 형태의 페이지인 About 페이지를 만들어 보겠습니다.

src/app 디렉터리로 이동: 프로젝트의 루트 디렉터리에 있는 src/app 폴더로 이동합니다.

이곳이 모든 라우트와 페이지가 시작되는 지점입니다.

새로운 폴더 생성: src/app 디렉터리 안에 about이라는 이름의 새로운 폴더를 생성합니다.

layout.tsx
page.tsx

page.tsx 파일 생성: 방금 생성한 about 폴더 안에 page.tsx라는 이름의 파일을 생성합니다.

page.tsx
layout.tsx
page.tsx

page.tsx 파일 내용 작성: src/app/about/page.tsx 파일을 열고 다음 코드를 작성합니다.

src/app/about/page.tsx
export default function AboutPage() {
  return (
    <div>
      <h1>About Us</h1>
      <p>
        이 페이지는 '나 혼자 Next.js' 교재의 예시 프로젝트입니다.
      </p>
      <p>Next.js 16와 함께 웹 개발을 학습하고 있습니다.</p>
    </div>
  );
}

이 파일은 기본적인 React 컴포넌트이며, 특별한 지시어가 없으므로 기본적으로 서버 컴포넌트로 동작합니다.

개발 서버 확인: 개발 서버가 실행 중이지 않다면, 프로젝트 루트 디렉터리에서 npm run dev (또는 yarn dev) 명령어를 실행합니다.

브라우저를 열고 http://localhost:3000/about 주소로 접속해 보세요.

방금 만든 About Us 페이지가 성공적으로 렌더링되는 것을 확인할 수 있습니다.

핵심: App Router에서는 폴더 이름이 URL 경로가 되고, 그 폴더 안의 page.tsx 파일이 해당 경로의 실제 UI를 담당합니다.


중첩 라우트(Nested Routes) 만들기

아래 표는 dashboard/settings처럼 폴더를 중첩할 때 URL과 page.tsx가 어떻게 대응되는지 정리한 것입니다.

중첩 라우트는 폴더 깊이가 URL 깊이로 이어진다

dashboard와 settings 폴더를 차례로 넣으면 /dashboard/settings처럼 URL도 같은 순서로 깊어진다.

폴더 구조만드는 파일생성되는 URL역할
src/app/dashboarddashboard/page.tsx/dashboard대시보드 홈 페이지
src/app/dashboard/settingssettings/page.tsx/dashboard/settings대시보드 설정 페이지
상위 layout이 있다면dashboard/layout.tsx/dashboard 아래 공유 UI메뉴, 제목, 공통 영역
폴더만 만든 경우page.tsx 없음접근 가능한 페이지 아님URL 후보일 뿐 화면 없음
확인 순서폴더 → page.tsx → 브라우저예상 URL 직접 입력파일 시스템과 URL 대응 확인

이제 좀 더 복잡한 페이지 구조를 만들어 보겠습니다.

예를 들어, 대시보드(Dashboard) 안에 설정(Settings) 페이지가 있는 형태입니다.

dashboard 폴더 생성: src/app 디렉터리 안에 dashboard라는 새 폴더를 만듭니다.

layout.tsx
page.tsx

dashboard/page.tsx 파일 생성: dashboard 폴더 안에 page.tsx 파일을 생성하고 다음 내용을 작성합니다.

이 파일은 /dashboard 경로의 페이지가 됩니다.

src/app/dashboard/page.tsx
export default function DashboardHomePage() {
  return (
    <div>
      <h1>Welcome to Dashboard!</h1>
      <p>여기는 대시보드의 홈 페이지입니다.</p>
    </div>
  );
}

http://localhost:3000/dashboard로 접속하여 확인해 보세요.

dashboard/settings 폴더 생성: dashboard 폴더 안에 다시 settings라는 새 폴더를 만듭니다.

page.tsx
layout.tsx
page.tsx

dashboard/settings/page.tsx 파일 생성: settings 폴더 안에 page.tsx 파일을 생성하고 다음 내용을 작성합니다.

이 파일은 /dashboard/settings 경로의 페이지가 됩니다.

src/app/dashboard/settings/page.tsx
export default function DashboardSettingsPage() {
  return (
    <div>
      <h2>Dashboard Settings</h2>
      <p>대시보드 설정을 관리하는 페이지입니다.</p>
    </div>
  );
}

개발 서버 확인: http://localhost:3000/dashboard/settings 주소로 접속하여 방금 만든 중첩 페이지가 잘 렌더링되는지 확인합니다.

핵심: 폴더 안에 폴더를 생성하고 그 안에 page.tsx를 두는 방식으로 URL 경로가 계속 중첩됩니다.

이는 파일 시스템 구조와 URL 경로가 일치하는 매우 직관적인 방식입니다.


웹 애플리케이션에서는 페이지 간에 이동하는 기능이 필수적입니다.

Next.js는 페이지 간의 클라이언트 사이드 탐색을 위해 <Link> 컴포넌트를 제공합니다.

이는 일반적인 HTML의 <a> 태그보다 여러 이점을 제공합니다.

  • 클라이언트 사이드 탐색: <Link>는 페이지 전체를 새로 고치지 않고, JavaScript를 사용하여 페이지 간의 부드러운 전환을 제공합니다.
  • 사전 로딩 (Preloading): 뷰포트에 들어오는 <Link> 컴포넌트의 대상을 자동으로 미리 로드하여 사용자가 링크를 클릭했을 때 더 빠른 페이지 전환을 경험할 수 있게 합니다.

아래 표는 <Link>가 일반 <a>와 달리 어떤 탐색 책임을 맡는지 정리합니다.

Link는 href 대상 페이지를 빠르게 이동하게 만드는 App Router 탐색 컴포넌트다

새로고침 없이 이동하고, 화면에 보이는 링크 대상은 미리 준비될 수 있다.

항목Link가 하는 일일반 a와 다른 점실습 확인
href/about, /dashboard내부 라우트 이동 대상 선언클릭 시 해당 page.tsx로 이동
클라이언트 탐색현재 앱 안에서 화면 교체전체 문서 새로고침을 줄임주소와 내용만 바뀌는지 확인
사전 로딩보이는 링크 대상 준비사용자 클릭 전 일부 리소스 확보전환이 즉시 되는지 체감
외부 링크필요하면 a 태그 사용다른 사이트는 일반 링크가 자연스러움내부/외부 링크를 구분
문제 신호href 오타 또는 없는 page404나 이동 실패폴더와 href 철자를 비교

이제 src/app/page.tsx (루트 페이지)에 다른 페이지로 이동하는 링크를 추가해 보겠습니다.

src/app/page.tsx 수정: src/app/page.tsx 파일을 열고 다음과 같이 수정합니다.

src/app/page.tsx
import Link from 'next/link'; // Link 컴포넌트 임포트

export default function HomePage() {
  return (
    <div>
      <h1>Welcome to '나 혼자 Next.js'!</h1>
      <p>Next.js 16 App Router와 함께 웹 개발을 시작합니다.</p>

      <nav style={{ marginTop: '20px' }}>
        <ul>
          <li>
            <Link href="/about">
              About 페이지로 이동
            </Link>
          </li>
          <li>
            <Link href="/dashboard">
              Dashboard 홈으로 이동
            </Link>
          </li>
          <li>
            <Link href="/dashboard/settings">
              Dashboard 설정 페이지로 이동
            </Link>
          </li>
        </ul>
      </nav>
    </div>
  );
}

주의: Next.js 13부터 <Link>가 자체적으로 <a> 요소를 렌더링합니다.

따라서 <Link><a>...</a></Link>처럼 <a>를 중첩하면 안 됩니다.

텍스트나 React 요소를 바로 자식으로 전달하고, 스타일 클래스와 링크 속성은 <Link>에 지정합니다.

개발 서버 확인: http://localhost:3000으로 접속하여 링크들이 잘 표시되는지 확인하고, 각 링크를 클릭하여 페이지가 부드럽게 전환되는지 테스트해 보세요.

브라우저의 새로고침 없이 내용만 바뀌는 것을 보실 수 있을 겁니다.


정적 페이지, 중첩 페이지, 링크 이동은 아래 기준으로 함께 점검하면 구조가 흔들리지 않습니다.

정적 페이지, 중첩 페이지, Link 이동은 파일 위치와 URL 대응으로 함께 점검한다

새 페이지가 열리지 않을 때는 코드보다 먼저 폴더 깊이, page.tsx 위치, href 값을 맞춰 본다.

점검 대상올바른 상태틀렸을 때 신호바로 볼 곳
정적 페이지src/app/about/page.tsx/about 404 발생about 폴더와 page.tsx 철자
중첩 페이지src/app/dashboard/settings/page.tsx/dashboard/settings 404settings 폴더 위치
홈 링크<Link href="/about">클릭해도 다른 곳으로 감href 문자열
서버 확인dev 서버 실행 중브라우저 접속 실패터미널과 포트
화면 내용default export 컴포넌트 반환빈 화면 또는 오류page.tsx의 return 구문

동적 라우트 개념 잡기 (예고편)

지금까지는 정적인 경로를 가진 페이지만 만들었습니다.

하지만 게시물 상세 페이지(/posts/1), 사용자 프로필 페이지(/users/john-doe)와 같이 URL의 일부가 동적으로 변하는 페이지는 어떻게 만들까요?

Next.js App Router는 대괄호([])를 사용해 동적 라우트 세그먼트를 정의합니다.

예를 들어 src/app/blog/[slug]/page.tsx 파일을 만들면 /blog/my-first-post, /blog/nextjs-basics 같은 경로를 처리할 수 있습니다.

[slug] 부분은 페이지 컴포넌트의 params prop을 통해 접근할 수 있습니다.

이 동적 라우트(Dynamic Routes) 개념은 다음 절에서 더 자세히 다루겠지만, 여기서 그 가능성을 미리 인지해 두시는 것이 좋습니다.

정적 페이지에서 중첩 페이지, 그리고 동적 라우트로 확장할 때의 판단 순서는 아래처럼 정리할 수 있습니다.

정적 경로에서 중첩 경로, 동적 경로로 확장할수록 폴더 이름의 의미가 달라진다

이번 절에서는 정적·중첩 경로를 만들고, 다음 절에서 대괄호 동적 세그먼트로 확장한다.

경로 유형폴더 예시URL 예시판단 기준
정적 경로app/about/page.tsx/about주소가 고정된 소개 페이지
중첩 경로app/dashboard/settings/page.tsx/dashboard/settings상위 기능 아래 하위 화면
동적 경로app/blog/[slug]/page.tsx/blog/nextjs-basics값이 URL마다 바뀌는 상세 화면
Link 대상<Link href="/dashboard/settings">고정 URL로 이동정적·중첩은 문자열로 명시
다음 학습[slug] params사용자/게시물별 URLparams로 URL 값을 읽음

이제는 App Router를 사용하여 새로운 페이지를 만들고, 중첩 라우트를 구성하며, <Link> 컴포넌트를 사용하여 페이지 간에 이동하는 기본적인 방법을 숙지하셨습니다.

새 페이지를 만든 뒤에는 파일 위치, URL, 링크 대상, 브라우저 확인 순서를 함께 점검해야 합니다.

새 페이지를 만든 뒤에는 파일, URL, 링크, 브라우저 네 가지를 같은 순서로 확인한다

오류를 줄이려면 새 화면을 만들 때마다 같은 점검 루틴을 반복한다.

순서확인 항목정상 신호오류 신호
1폴더가 app 아래에 있는가src/app/aboutsrc/pages나 다른 폴더에 둠
2page.tsx가 있는가default export 컴포넌트파일명 오타 또는 index.tsx 착각
3URL이 폴더와 맞는가about → /about대소문자나 깊이 불일치
4Link href가 맞는가href="/dashboard"없는 경로를 가리킴
5브라우저에서 직접 열리는가새로고침해도 화면 유지클라이언트 이동만 되고 직접 접속 실패

마지막으로 새 페이지 생성, 중첩 라우트, Link 이동을 하나의 구현 흐름으로 연결합니다.

페이지 생성 흐름은 만들기, 연결하기, 확인하기로 끝난다

about, dashboard, settings를 만들고 홈에서 Link로 연결한 뒤 브라우저에서 직접 URL까지 확인한다.

단계할 일완료 기준놓치기 쉬운 점
1. 만들기폴더와 page.tsx 생성직접 URL로 페이지 열림폴더만 만들고 page 누락
2. 내용 쓰기컴포넌트 반환 UI 작성제목과 문장이 화면에 보임default export 누락
3. 중첩하기dashboard/settings 추가URL 깊이가 폴더 깊이와 일치settings 위치를 app 바로 아래에 둠
4. 연결하기홈에서 Link href 추가클릭 이동과 주소 변경 확인href 철자 불일치
5. 마감 확인새로고침과 직접 접속 테스트각 URL이 독립적으로 열림클라이언트 이동만 확인하고 끝냄