[Next.js] Pages와 Pre-rendering

juyeong-s·2023년 3월 19일
1

Next.js

목록 보기
1/1

Pages

Next.js에서 page는 pages 디렉터리의 .js, .jsx, .ts, .tsx 파일로부터 생성된 리액트 컴포넌트다. 각 page는 pages 디렉터리 안의 파일 이름을 기반으로 라우팅이 된다.

만약, pages/home.tsx 파일의 경우 /home path로 접근 가능하다.

Pages의 동적 라우팅

Next.js는 pages의 동적 라우팅을 지원한다. 만약, pages/posts/[id].jsx 파일을 생성한다면, posts/1, posts/2 path로 접근 가능하다.

Pre-rendering

기본적으로 Next.js가 모든 페이지를 pre-rendering 한다. 이것은 client-side의 자바스크립트로 실행하는 대신, 각 페이지의 HTML을 사전에 미리 생성한다는 것이다. pre-rendering은 SEO와 성능에 더 좋다.

생성된 각 HTML은 해당 페이지에 필요한 최소한의 자바스크립트 코드와 연결된다.

Pre-rendering의 두가지 방식

SSG(Static Site Generation), SSR(Server Side Rendering) 두가지 방식이 있는데, 다른 점은 HTML을 생성하는 시점이다.

  • SSG(Static Site Generation): HTML이 빌드 타임에 생성되며 생성된 HTML은 모든 요청에서 재사용된다.
  • SSR(Server Side Rendering): HTML이 각 요청마다 생성된다.

우리는 페이지별로 사용하고자 하는 Pre-rendering 방식을 선택할 수 있다.

Next.js는 성능 상의 이유로 SSG를 사용하는 것을 추천한다. 정적으로 생성된 페이지는 CDN에 의해 캐싱될 수 있다.

CDN(Content Delivery Network): 지리적으로 분산된 여러 개의 서버
CDN은 (HTML이나 이미지 파일같은) 정적 컨텐츠를 전세계의 여러 장소에 저장한다. 서버와 사용자 사이의 물리적인 거리를 줄여 콘텐츠 로딩에 소요되는 시간을 최소화한다.
각 지역에 캐시 서버(PoP, Points of presence)를 분산 배치해, 근접한 사용자의 요청에 원본 서버가 아닌 캐시 서버가 콘텐츠를 전달하게 된다.
새 요청이 들어오면, 유저로부터 가장 가까운 CDN이 캐싱된 결과와 함께 응답한다. 사용자의 물리적 위치와 가장 가까운 서버에서 전송되는 콘텐츠는 더 빠른 고성능 웹 경험을 제공해준다.
https://www.akamai.com/ko/our-thinking/cdn/what-is-a-cdn

데이터없는 Static Generation

기본적으로 Next.js는 데이터를 가져오지 않고 정적 생성을 사용하여 페이지를 pre-rendering한다.

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

export default About

데이터를 사용한 Static Generation

어떤 페이지는 pre-rendering을 위해 외부 데이터를 가지고 와야한다. 두 가지 시나리오가 있다.

  • getStaticProps: 페이지 콘텐츠가 외부 데이터에 따라 달라질 경우 사용
  • getStaticPaths: 페이지 경로가 외부 데이터에 따라 달라질 경우 사용

getStaticProps

다음 블로그 페이지는 블로그 게시물 목록을 가져와야 렌더링 할 수 있다.

export default function Blog({ posts }) {
  return (
    <ul>
      {posts.map((post) => (
        <li>{post.title}</li>
      ))}
    </ul>
  )
}

데이터를 가져와 pre-rendering하기 위해서 getStaticProps 함수를 비동기 방식으로 export 하여 사용한다. 이 함수는 build-time에 호출된다.

export default function Blog({ posts }) {
  // Render posts...
}

export async function getStaticProps() {
  const res = await fetch('https://.../posts')
  const posts = await res.json()

  // By returning { props: { posts } }를 리턴하면, Blog 컴포넌트는 빌드 타임에 posts prop을 받는다.
  return {
    props: {
      posts,
    },
  }
}

getStaticProps 문서

getStaticPaths

posts/1와 같은 path에 접근해서 1번 게시물을 보기 위해서는 게시물 id값이 path에 필요하다. 이때 getStaticPaths 함수를 사용한다.
이 함수는 build-time에 실행되며 pre-rendering할 path를 지정할 수 있다. 마찬가지로 비동기 처리하여 export 하여 사용한다.

export async function getStaticPaths() {
  const res = await fetch('https://.../posts')
  const posts = await res.json()

  const paths = posts.map((post) => ({
    params: { id: post.id },  // params의 id를 각 post의 id로 지정하는 것.
  }))

  // { fallback: false }는 다른 라우팅 시 404가 발생한다는 의미
  return { paths, fallback: false }
}

그리고 여기서 특정 id값을 가진 게시물 데이터를 가져와 페이지를 pre-rendering하는데 getStaticProps를 사용할 수 있다.

export default function Post({ post }) {
  // Render post...
}

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

export async function getStaticProps({ params }) {
  // params는 post `id`를 가지고 있음.
  const res = await fetch(`https://.../posts/${params.id}`)
  const post = await res.json()
  return { props: { post } }
}

getStaticPaths 문서

언제 Static Generation을 사용해야 할까?

Next.js는 가능한 정적 생성을 사용하는 것을 권장한다. 요청마다 서버에서 페이지를 렌더링하는 것보다 훨씬 빠르기 때문이다.

다음 페이지 예시에 정적 생성을 사용할 수 있다.

  • 마케팅 페이지
  • 블로그 게시물
  • 제품 목록
  • 도움말 및 설명서

하지만 사용자 요청보다 먼저 페이지를 렌더링 할 수 없는 경우 SSG는 좋은 선택이 아니다. 만약 페이지의 데이터가 자주 업데이트된다면, 페이지 콘텐츠가 매 요청마다 변경되기 때문이다.

이 경우 다음과 같은 방법을 사용할 수 있다.

  • Client-side와 SSG 사용하기: 페이지 일부를 pre-rendering 하지 않고 클라이언트의 자바스크립트를 콘텐츠를 채운다.
  • SSR 사용하기: CDN에서 페이지를 캐싱할 수 없기 때문에 속도는 느려지지만 pre-rendering된 페이지는 항상 최신 상태이다.

SSR(Server-side Rendering)

SSR방식은 각 요청마다 페이지 HTML이 생성된다. 페이지를 SSR하기 위해서는 getServerSideProps 함수를 비동기 처리하여 export 해야 한다.

export default function Page({ data }) {
  // Render data...
}

export async function getServerSideProps() {
  const res = await fetch(`https://.../data`)
  const data = await res.json()

  return { props: { data } }
}

getServerSidePropsgetStaticProps와 비슷하다. 하지만 다른 점은 getServerSideProps는 빌드 타임에 실행되지 않고 매 요청마다 실행된다.

getServerSideProps 문서

참고

profile
frontend developer

0개의 댓글