
각 디렉토리의 page.js라는 파일이 해당 디렉토리의 이름으로 매핑되는 파일이 된다.
React의 index.jsx와 유사하다고 생각하면 될 것이다.
import Image from "next/image";
export default function Home() {
return (
<div className="grid grid-rows-[20px_1fr_20px] items-center justify-items-center min-h-screen p-8 pb-20 gap-16 sm:p-20 font-[family-name:var(--font-geist-sans)]">
Hello, Nextjs!
</div>
);
}
import './globals.css'
export const metadata = {
title: 'WEB tutorial',
description: 'Generated by egoing',
}
export default function RootLayout({ children }) {
return (
<html>
<body>
<h1><a href="/">WEB</a></h1>
<ol>
<li><a href="/read/1">html</a></li>
<li><a href="/read/2">css</a></li>
</ol>
{children}
<ul>
<li><a href="/create">create</a></li>
<li><a href="/update/id">update</a></li>
<li><button>delete</button></li>
</ul>
</body>
</html>
)
}
page.js, layout.js, not-found.js 같은 특정 예약된 파일의 경우, 파일 이름이 중요하지 코드 상 컴포넌트의 이름은 뭐가 되었든 동작에 영향을 주지 않는다. (심지어 대문자가 아니어도 된다!)
page.js, layout.js)page.js, layout.js 같은 특정 예약된 파일이름은 다른 방식으로 동작한다.page.js : 각 디렉토리 마다 하나씩만 존재할 수 있으며, 해당 폴더의 경로가 URL 경로로 매핑된다.layout.js : 특정 경로와 하위 경로에 적용될 레이아웃을 ****정의한다.not-found.jserror.jslayout.js 파일을 정의할 수 있다.app/
├── (marketing)/
│ ├── about/
│ │ └── page.js
│ └── contact/
│ └── page.js
├── (dashboard)/
│ ├── settings/
│ │ └── page.js
│ └── profile/
│ └── page.js
└── page.js
app/(marketing)/about/page.js의 경로는 /about으로 매핑된다.app/(dashboard)/settings/page.js의 경로는 /settings으로 매핑된다.경로가 고정되지 않고, URL에 따라 변할 수 있는 경로를 설정할 수 있는 기능이다.
대괄호([])를 사용하여 파일이나 폴더 이름을 정의함으로써 생성된다.
예를 들어, app/[id]/page.js는 /123, /product, /my-page와 같은 동적인 URL을 처리할 수 있다.
params에는 대괄호 안에 적은 폴더의 이름을 키 값으로 하는 해당 url의 값이, searchParams에는 ? 형태로 들어온 쿼리 문이 객체로 들어온다.
Next.js의
App Router에서 데이터를 비동기로 처리하게끔 하기에params와searchParams는Promise객체로 만들어진다. await 등으로 Promise Pending 상태를 해제해주자.
export default async function Movie(props) {
const resolvedParams = await props.params; // Promise 해제
const resolvedSearchParams = await props.searchParams;
console.log("params:", resolvedParams);
console.log("searchParams:", resolvedSearchParams);
return (<div className="">Movie! Movie! </div>);
}
<a href=””>를 사용하지 않고, next 프레임워크가 제공하는 Link를 사용할 수 있다.import Link from "next/link";
export default function Navigation() {
return (
<nav>
<Link href="/">Home</Link>
<Link href="/test">Test</Link>
<Link href="/error">Error </Link>
</nav>
);
}
"use client";
import Navigation from "@/components/navigation";
import { usePathname } from "next/navigation";
export default function HoGGGme() {
const path = usePathname();
return (
<div className="grid grid-rows-[20px_1fr_20px] items-center justify-items-center min-h-screen p-8 pb-20 gap-16 sm:p-20 font-[family-name:var(--font-geist-sans)]">
<Navigation />
Hello, Nextjs!
<div>cur path : {path}</div>
</div>
);
}
페이지 틀을 담당하는 상위 컴포넌트이다.
중첩이 가능하기에 용도에 따라 다르게 중첩된 컴포넌트를 만들 수 있다.
metadata는 서버에서만 작동하는 API이기에use client와 동시에 사용할 수 없다. layout 컴포넌트에서 클라이언트 컴포넌트가 필요하다면, 자식 컴포넌트로 가지는 방법을 사용하는 것이 바람직하다.
import Navigation from "@/components/navigation";
import PathDisplay from "@/components/pathdisplay";
export const metadata = {
title: "Next.js",
description: "Generated by Next.js",
};
export default function RootLayout({ children }) {
return (
<html lang="en">
<body>
<Navigation />
<PathDisplay />
{children}
</body>
</html>
);
}
layout.js 혹은 page.js에서 metadata를 export하면 html의 head 안에 내용을 생성할 수 있다.
이 때 반드시 해당 컴포넌트는 서버 컴포넌트여야만 한다. (use client와 함께 쓸 수 없다.)
상위의 Metadata를 찾는 과정에서 하나의 Metadata를 여러 페이지(컴포넌트)가 공유하게 될 수 있다.
여러 개의 Metadata가 존재한다면 병합되며, 중복되는 속성의 경우 해당 url에서 가장 가까운 속성 값을 사용한다.
TS라면 템플릿을 사용해 동적인 값을 넣어줄 수 있다.
export const metadata: Metadata = {
title: {
template : "%s | Next.js",
default: "Loading...",
}
description: "Generated by Next.js",
};