Next.js 13.2
페이지와 레이아웃
페이지 생성하기(Pages)
nextjs13.2부터는 파일이 아닌 경로가 페이지 경로의 기준이 된다.
페이지의 경로는 app폴더 내의 디렉토리의 경로와 같다.
예를 들어 사이트(site.com/)에 접속 하면 최상위 페이지 app/page.js를 불러온다.
URL | 상대 경로 | 페이지 경로 |
site.com/ | / | app/page.js |
site.com/dashboard/ | /dashboard | app/dashboard/page.js |
site.com/dashboard/settings/ | /dashboard/settings/ | app/dashboard/settings/page.js |
export default function HomePage() {
return (
<>
<h1>
Home
</h1>
</>
);
}
페이지 이동하기(Link)
페이지 이동은 <Link> 태그를 사용한다.
<a> 대신 next.js의 <Link>를 사용
<a>태그는 자동으로 <Link>내에 삽입된다.
import Link from 'next/link';
export default function Page() {
return (
<>
<h1>
<Link href="/">home</Link>
</h1>
</>
);
}
레이아웃 적용하기(Layout)
레이아웃은 페이지를 감싸는 UI요소이다.
page.js와 같은 경로에 있으면 자동으로 레이아웃이 적용된다.
// app/post/layout.js
export default function Layout({ children }) {
return <article>{children}</article>;
}
// app/post/page.js
export default function FirstPost() {
return (
<h1>First Post</h1>
);
}
결과는 아래와 같다.
<article>
<h1>First Post</h1>
</article>
루트 레이아웃(Root Layout)
- `/app/layout.js`에서 작성
- `<html><body>`를 포함하여 필수로 정의
- `layout.js`는 `page.js`에 `import`하지 않아도 자동으로 적용된다.
- 라우트 그룹을 통해 루트 레이아웃을 여러 개로 만들 수 있다
import './globals.css';
export default function RootLayout({ children }) {
return (
<html lang="en">
<body>{children}</body>
</html>
)
}
에셋, 메타데이터, CSS
이미지(Image) 만들기
이미지,로고 파일와 같은 정적인 에셋은 /public 디렉토리에 넣어 사용한다.
<image>가 아닌 next.js의 <Image>를 사용
import Image from 'next/image';
import profile from '../public/profile.png';
export default function Page() {
return (
<Image src={profile} alt="profile"/>
);
}
메타데이터(metadata) 작성하기
SEO 지원을 위해 필수적인 메타데이터는 페이지의 제목이나 컨텐츠, 언어 등을 명시한다.
13.2 버전 이후에는 <head> 대신 아래와 같이 사용한다.
// Static metadata
export const metadata = {
title: '...',
};
// Dynamic metadata
export async function generateMetadata({ params, searchParams }) {
const product = await getProduct(params.id);
return { title: product.title };
}
서드파티 스크립트 사용하기(Script)
<script>가 아닌 next.js의 <Script>를 사용
import Script from 'next/script';
export default function ScriptPage() {
return (
<>
<Script src="https://example.com/script.js" />
</>
)
}
CSS 모듈 사용하기
CSS 모듈을 지원하여 고유한 클래스 이름을 가질 수 있다.
Tailwind CSS, sass 등도 당연히 지원한다.
import styles from './styles.module.css';
export default function DashboardLayout({ children }) {
return <section className={styles.dashboard}>{children}</section>;
}
전역스타일 사용하기(Global styles)
모든 페이지에서 사용되는 전역 스타일은 모든 페이지에서 사용되는 루트 레이아웃(app/layout.js)에서 임포트해 사용한다.
// /app/layout.js
import './global.css';
export default function RootLayout({ children }) {
return (
<html lang="ko">
<body>{children}</body>
</html>
);
}
사전 렌더링이란(Pre-Rendering)
- 일반적인 React 앱은 필요한 데이터를 다운로드 받아 클라이언트에서 페이지를 렌더링한다.
- 이러한 경우 봇은 사이트 내용을 제대로 볼 수 없고, SEO 최적화 또한 제대로 할 수 없다
- nextjs는 사전렌더링을 통해 미리 서버에서 완성본 페이지를 만들어 제공한다.
- 빌드 시에는 시간이 오래 걸리지만, 미리 만들어진 페이지를 로드할 때는 시간이 적게 걸리는 장점이 있다.
- 사전렌더링에서 javascript는 페이지를 만들지 않고 앱을 대화형으로 만드는데 사용된다.
정적 데이터 가져오기(Static Site Generation)
- 애플리케이션 빌드(배포) 시 페이지 전체를 만들어 CDN에 저장한다.
- 생성된 HTML은 각 요청 시 CDN을 통해 사용자에게 제공
- nextjs의 기본값은 정적 사이트 생성이다.
- 사용하는 경우: 마케팅 페이지, 설명서 등과 같이 사용자 요청과 관련없이 미리 렌더링이 가능한 페이지
- nextjs 13.2이전에는 getStaticProps()를 사용하였으나 이제는 함수 이름을 사용자 임의로 할 수 있다.
- nextjs 13.2부터 '정적 데이터 가져오기'로 이름이 변경되었다.
- async / await 구문을 사용
export default async function Page() {
const post = await getPostData();
return (
<>
<h1>{post.title}</h1>
<p>{post.content}</p>
</>
);
}
async function getPostData() {
const res = await fetch('https://api.example.com/...');
return res.json();
}
동적 데이터 가져오기(Server-Side Rendering)
- 각 요청에 대해 서버에서 그때 그때 최신의 데이터로 페이지 전체를 만들어 사용자에 제공
- 사용하는 경우:
- 페이지에 자주 업데이트되는 데이터가 포함되어 있는 경우(항상 최신 데이터가 필요할 때)
- 사용자 요청에 따라 데이터가 다를 수 있는 경우
- nextjs 13.2부터 '동적 데이터 가져오기'로 이름이 변경되었다.
- { cache: 'no-store' } 를 통해 항상 최신 데이터를 가져온다.
export default async function Page() {
const post = await getStaticData();
return (
<>
<h1>{post.title}</h1>
<p>{post.content}</p>
</>
);
}
async function getStaticData() {
const res = await fetch('https://api.example.com/...', { cache: 'no-store' });
return res.json();
}
동적 경로란
- 동적 경로는 정해진 경로가 아닌 외부 데이터에 의해 동적으로 변할 수 있는 경로이다.
- 예를 들어 게시물이나 제품의 상세페이지 경로일 경우 게시물이나 제품 아이디, 제목 등을 경로에 사용하여 페이지를 만들 수 있다.
동적 경로 생성하기(params)
- 외부 데이터에 의존하는 경로를 가지는 다른 페이지를 생성
- posts/[id]/page.js의 페이지는 [id]값을 params로 받는다.
- 이 params를 사용해 원하는 게시물의 데이터를 정적 데이터 가져오기로 가져온다
URL | 상대 경로 | 페이지 경로 |
site.com/ | / | app/page.js |
site.com/posts/ | /posts | app/posts/page.js |
site.com/posts/first-post site.com/posts/second-post site.com/posts/... ... |
/posts/[id] | app/posts/[id]/page.js // params: { id: first-post} app/posts/[id]/page.js // params: { id: second-post} app/posts/[id]/page.js // params: { id: ...} |
import { getPostData } from '@/lib/posts';
export default async function Post({ params }) {
const { id } = params;
const postData = await getStaticPost(id);
return (
<>
{postData.title}
<br />
{postData.id}
<br />
{postData.date}
</>
);
}
export async function getStaticPost(id) {
const postData = await getPostData(id);
return postData;
}
정적 경로 생성하기(generateStaticParams)
- 위와 같이 동적 경로는 들어오는 외부 데이터 값에 따라 무한히 많은 경로가 만들어진다.
- 하지만 제품이나 게시글을 동적 경로로 사용할 경우 이미 있는 제품이나 게시글에 대해서만 페이지에 접근하므로
미리 정적 경로를 만들어 둘 수 있다. - generateStaticParams()에 정적 경로로 가능한 리스트를 반환하여 생성한다.
import { getAllPostIds, getPostData } from "@/lib/posts";
export default async function Post({ params }) {
const { id } = params;
const postData = await getStaticPost(id);
return (
<>
{postData.title}
<br />
{postData.id}
<br />
{postData.date}
</>
);
}
export async function generateStaticParams() {
const paths = await getAllPostIds();
return paths; // path: [ { id: 'first-post' }, { id: 'second-post' } ]
}
export async function getStaticPost(id) {
const postData = await getPostData(id);
return postData;
}
만들지 않은 동적 경로 막기(dynamicParams)
- 위에서 본 것 처럼 동적 경로는 다양한 데이터가 세그먼트 값으로 들어와 다양한 동적 경로가 가능하다.
- 하지만 경로가 정적 경로로 만든 경로를 제외하고는 접근이 필요없는 경우도 있다.
- 예를 들어 위와 같이 게시판에 게시글이 'first-post', 'second-post' 두 개 뿐일 경우
나머지 모든 /post/[id] 경로는 접근할 이유가 없다. - 이렇게 생성된 정적 경로 외에 동적 경로가 필요없을 경우 dynamicParams를 사용할 수 있다.
- dynamicParams는 기본값으로 true이다.
- true일 경우 정적 경로(generateStaticParams)로 생성되지 않은 동적 경로를 요청시 생성한다.
- false 일 경우 정적 경로(generateStaticParams)로 생성되지 않은 동적 경로 요청시 404에러를 반환한다.
export const dynamicParams = false;
'JAVASCRIPT' 카테고리의 다른 글
브이월드 2D데이터 api react nextjs 사용법 (0) | 2023.05.04 |
---|---|
웹 페이지 meta 태그 한글 깨짐 외계어 해결 (0) | 2023.03.17 |
firebase web version 8에서 회원가입, 인증 구현하기. (0) | 2023.01.03 |
Error: [@RNC/AsyncStorage]: NativeModule: AsyncStorage is null. 해결법 (0) | 2022.12.24 |
styled-components 설치 시 unable to resolve dependency tree 오류 해결 (0) | 2022.12.23 |