Next공식문서: 페이지(Page)

hwisaac·2023년 3월 11일
0

Next.js

목록 보기
5/29

참고: Next.js 13부터 새로운 디렉토리인 app/ (베타)가 추가되었습니다. 이 새 디렉토리는 레이아웃, 중첩 라우트 및 기본적으로 서버 컴포넌트를 사용합니다. app/ 안에서는 레이아웃 내에서 애플리케이션 전체의 데이터를 가져올 수 있으며, 더욱 세부적인 중첩 레이아웃(데이터 가져오기와 연결된)도 지원합니다.

app/ 에 대해 자세히 알아보세요.

Next.js에서 페이지는 pages 디렉토리에 있는 .js, .jsx, .ts 또는 .tsx 파일에서 내보낸 React 컴포넌트입니다. 각 페이지는 파일 이름을 기반으로 한 경로(route)와 연결됩니다.

예시: pages/about.js 라는 파일을 만들고 아래와 같은 React 컴포넌트를 내보내면, /about에서 접근 가능합니다.

export default function About() {
  return <div>About</div>
}

동적(Dynamic) 라우트를 가진 페이지

Next.js는 동적 라우트를 가진 페이지를 지원합니다. 예를 들어, pages/posts/[id].js라는 파일을 만들면 posts/1, posts/2 등에서 접근 가능합니다.

동적 라우팅에 대해 자세히 알아보세요(Dynamic Routing).

프리 렌더링

기본적으로 Next.js는 모든 페이지를 프리 렌더링합니다. 이는 클라이언트 측 JavaScript가 모든 작업을 처리하는 대신 미리 각 페이지의 HTML을 생성함으로써, 성능 및 검색 엔진 최적화(SEO) 측면에서 이점을 제공합니다.

각 생성된 HTML은 해당 페이지에 필요한 최소한의 JavaScript 코드와 연결됩니다. 페이지가 브라우저에 의해 로드될 때, 해당 JavaScript 코드가 실행되어 페이지가 완전히 대화형으로 만들어집니다. (이 과정을 하이드레이션(hydration)이라고 합니다.)

프리 렌더링의 두 가지 형태

Next.js에는 두 가지 프리 렌더링 형태가 있습니다: 정적 생성(Static Generation) 및 서버 사이드 렌더링(Server-side Rendering). 차이점은 페이지의 HTML을 생성하는 시점입니다.

  • 정적 생성(추천): HTML은 빌드 시간에 생성되며 각 요청에서 재사용됩니다.
  • 서버 사이드 렌더링: HTML은 각 요청에서 생성됩니다.

중요한 것은 Next.js에서는 각 페이지마다 어떤 프리 렌더링 형태를 사용할지 선택할 수 있다는 것입니다. 대부분의 페이지에 대해 정적 생성을 사용하고 일부 페이지에 대해서만 서버 사이드 렌더링을 사용하여 "하이브리드" Next.js 앱을 만들 수 있습니다.

성능 이유로 정적 생성을 서버 사이드 렌더링 대신 사용하는 것이 좋습니다. 정적 생성된 페이지는 CDN에서 캐시될 수 있으므로 성능 향상을 위해 추가 구성이 필요하지 않습니다. 그러나 일부 경우에는 서버 사이드 렌더링이 유일한 옵션일 수 있습니다.

정적 생성 또는 서버 사이드 렌더링과 함께 클라이언트 측 데이터 가져오기도 사용할 수 있습니다. 이는 페이지의 일부를 클라이언트 측 JavaScript로 완전히 렌더링할 수 있음을 의미합니다. 자세한 내용은 데이터 가져오기(Data Fetching) 문서를 참조하세요.

정적 생성

정적 생성을 사용하는 경우, 페이지 HTML은 빌드 시간에 생성됩니다. 이는 프로덕션 환경에서 next build를 실행할 때 페이지 HTML이 생성됩니다. 이 HTML은 각 요청에서 재사용됩니다. CDN에 의해 캐시될 수 있습니다.

Next.js에서 데이터가 있는지 없는지에 따라 정적 생성을 사용하여 페이지를 생성할 수 있습니다. 각각의 경우를 살펴보겠습니다.

데이터 없이 정적 생성

기본적으로 Next.js는 데이터를 가져오지 않고 정적 생성을 사용하여 페이지를 프리 렌더링합니다.

예시:

function About() {
  return <div>About</div>
}
export default About

이 페이지는 프리 렌더링을 위해 외부 데이터를 가져올 필요가 없습니다. 이와 같은 경우, Next.js는 각 페이지에 대해 빌드 시간에 단일 HTML 파일을 생성합니다.

데이터와 함께 정적생성

일부 페이지는 프리 렌더링을 위해 외부 데이터를 가져와야 합니다. 두 가지 시나리오가 있으며, 각각 또는 모두에 적용할 수 있는 Next.js가 제공하는 함수가 있습니다.

  1. 페이지 콘텐츠가 외부 데이터에 따라 달라지는 경우: getStaticProps를 사용하세요.
  2. 페이지 경로가 외부 데이터에 따라 달라지는 경우: getStaticPaths를 사용하세요 (대개 getStaticProps와 함께 사용).

시나리오 1: 페이지 콘텐츠가 외부 데이터에 따라 달라지는 경우

예제: 블로그 페이지는 CMS(콘텐츠 관리 시스템)에서 블로그 글 목록을 가져와야 합니다.

// 이 페이지는 프리 렌더링을 위해 `posts`를 가져와야 합니다. (어떤 API 엔드포인트를 호출하는 등)
export default function Blog({ posts }) {
  return (
    <ul>
      {posts.map((post) => (
        <li>{post.title}</li>
      ))}
    </ul>
  )
}

이 데이터를 프리 렌더링할 때, Next.js는 동일한 파일에서 getStaticProps라는 async 함수를 익스포트하도록 허용합니다. 이 함수는 빌드 시간에 호출되며, 프리 렌더링 중에 페이지의 props에 가져온 데이터를 전달할 수 있습니다.

export default function Blog({ posts }) {
  // 글 목록을 렌더링합니다...
}

// 이 함수는 빌드 시간에 호출됩니다.
export async function getStaticProps() {
  // API 엔드포인트를 호출하여 글 목록(posts)을 가져옵니다.
  const res = await fetch('https://.../posts')
  const posts = await res.json()

  // `props: { posts }`를 반환함으로써, Blog 컴포넌트는 빌드 시간에 `posts`를 props로 받게 됩니다.
  return {
    props: {
      posts,
    },
  }
}

시나리오 2: 페이지 경로가 외부 데이터에 따라 달라지는 경우

Next.js는 동적 경로를 가진 페이지를 만들 수 있도록 허용합니다. 예를 들어, pages/posts/[id].js라는 파일을 만들어 id에 따라 단일 블로그 글을 보여줄 수 있습니다. 이렇게 하면 posts/1에 액세스할 때 id: 1인 블로그 글을 표시할 수 있습니다.

동적 라우팅에 대해 자세히 알아보려면 동적 라우팅(Dynamic Routing) 문서를 확인하세요.

그러나 어떤 id를 프리 렌더링할 것인지는 외부 데이터에 따라 달라질 수 있습니다.

예제: 데이터베이스에 블로그 글(id: 1) 하나만 추가한 경우, 빌드 시간에 posts/1만 프리 렌더링하려고 할 수 있습니다.

나중에 두 번째 글(id: 2)을 추가할 수 있습니다. 이 경우 두 번째 글인 posts/2도 프리 렌더링하려고 할 것입니다.

즉, 프리 렌더링할 페이지 경로는 외부 데이터에 따라 달라집니다. 이 문제를 처리하려면 Next.js에서 동적 페이지(pages/posts/[id].js이 경우)에서 getStaticPaths라는 async 함수를 익스포트할 수 있습니다. 이 함수는 빌드 시간에 호출되며, 어떤 경로를 프리 렌더링할 것인지 지정할 수 있습니다.

// 이 함수는 빌드 시간에 호출됩니다.
export async function getStaticPaths() {
  // API 엔드포인트를 호출하여 글 목록(posts)을 가져옵니다.
  const res = await fetch('https://.../posts')
  const posts = await res.json()

  // posts를 기반으로 프리 렌더링할 경로를 가져옵니다.
  const paths = posts.map((post) => ({
    params: { id: post.id },
  }))

  // 빌드 시간에 이 경로만 프리 렌더링합니다.
  // { fallback: false }는 다른 경로는 404를 반환하도록 지정합니다.
  return { paths, fallback: false }
}

또한 pages/posts/[id].js에서는 getStaticProps를 익스포트하여 이 id에 대한 글 데이터를 가져와 프리 렌더링하는 데 사용할 수 있습니다.

export default function Post({ post }) {
  // 글 데이터를 렌더링합니다...
}

export async function getStaticPaths() {
  // ...
}

// 이 함수는 빌드 시간에도 호출됩니다.
export async function getStaticProps({ params }) {
  // params에는 글 `id`가 포함됩니다.
  // 루트가 /posts/1인 경우 params.id는 1입니다.
  const res = await fetch(`https://.../posts/${params.id}`)
  const post = await res.json()

  // 글 데이터를 페이지로 전달합니다.
  return { props: { post } }
}

getStaticPaths가 작동하는 방식에 대해 자세히 알아보려면 데이터 가져오기(Data Fetching) 문서를 확인하세요.

언제 Static Generation을 사용해야 할까요?
사용 가능한 경우 Static Generation(데이터와 함께 또는 데이터 없이)을 사용하는 것이 좋습니다. 페이지를 한 번 빌드하고 CDN에서 제공할 수 있기 때문에 서버에서 페이지를 매번 렌더링하는 것보다 훨씬 빠릅니다.

Static Generation은 다음과 같은 종류의 페이지에 사용할 수 있습니다.

  • 마케팅 페이지
  • 블로그 게시물 및 포트폴리오
  • 전자 상거래 제품 목록
  • 도움말 및 문서

자문하자면 이 페이지를 사용자 요청보다 먼저 프리 렌더링할 수 있는지를 스스로에게 물어봐야 합니다. 가능하다면 Static Generation을 선택해야 합니다.

반면, 페이지가 자주 업데이트되는 데이터를 표시하거나, 페이지 내용이 매번 요청마다 변경되는 경우 Static Generation은 좋은 선택이 아닙니다.

이러한 경우 다음 중 하나를 수행할 수 있습니다.

  • Client-side data fetchingStatic Generation 함께 사용: 페이지의 일부를 프리 렌더링하지 않고 클라이언트 측 JavaScript를 사용하여 채울 수 있습니다. 이 방법에 대해 자세히 알아보려면 데이터 가져오기(Data Fetching) 문서를 확인하세요.
  • Server-Side Rendering 사용: Next.js는 매번 요청마다 페이지를 프리 렌더링합니다. CDN에서 캐시할 수 없으므로 느리지만, 프리 렌더링된 페이지는 항상 최신 상태입니다. 이 방법에 대해 나중에 논의하겠습니다.

Server-side Rendering

SSR(Server-side Rendering) 또는 동적 렌더링이라고도 함.

페이지가 Server-side Rendering을 사용하면, 페이지 HTML은 매번 요청마다 생성됩니다.

페이지를 Server-side Rendering으로 사용하려면, getServerSideProps라는 async 함수를 익스포트해야 합니다. 이 함수는 서버에서 매번 요청됩니다.

예를 들어, 페이지가 외부 API에서 가져온 자주 업데이트되는 데이터를 프리 렌더링해야 할 경우 getServerSideProps를 작성하고 아래와 같이 데이터를 가져와 페이지의 props로 전달할 수 있습니다.

export default function Page({ data }) {
  // 데이터를 렌더링합니다...
}

// 이 함수는 모든 요청마다 호출됩니다.
export async function getServerSideProps() {
  // 외부 API에서 데이터를 가져옵니다.
  const res = await fetch(`https://.../data`)
  const data = await res.json()

  // 데이터를 페이지를 통해 props로 전달합니다.
  return { props: { data } }
}

getServerSidePropsgetStaticProps와 유사하지만, getServerSideProps는 빌드 시간이 아닌 매번 요청마다 실행된다는 점이 다릅니다.

getServerSideProps가 작동하는 방식에 대해 자세히 알아보려면 데이터 가져오기(Data Fetching) 문서를 확인하세요.

요약

Next.js에서 두 가지 유형의 프리 렌더링인 Static GenerationServer-side Rendering에 대해 논의했습니다.

  • 정적 생성(권장): HTML은 빌드 시점에 생성되며, 각 요청에서 재사용됩니다. 페이지에 정적 생성을 사용하려면 페이지 컴포넌트를 내보내거나, getStaticProps(필요한 경우 getStaticPaths도)를 내보내면 됩니다. 사용자 요청 전에 프리 렌더링할 수 있는 페이지에 적합합니다. 클라이언트 측 렌더링과 함께 사용하여 추가 데이터를 가져올 수도 있습니다.
  • 서버 사이드 렌더링: HTML은 각 요청에서 생성됩니다. 서버 사이드 렌더링을 사용하려면 getServerSideProps를 내보내면 됩니다. 정적 생성보다 성능이 느리기 때문에 절대적으로 필요한 경우에만 사용하세요.

0개의 댓글