React/Next.js

[Next.js] Next.js의 프리 렌더링(SSR, SSG, ISR)

Eater 2023. 2. 8. 20:03

1. Next.js란?

React에서 사용가능한 오픈소스 자바스크립트 웹 프레임워크이며 리액트에서 서버 사이드 렌더링(SSR), 정적 사이트 생성(SSG)나 증분 정적 재생성(ISR)을 쉽게 구현할 수 있도록 도와준다.

 

2.1 Pre-rendering

Next.js는 기본적으로 클라이언트 사이드 자바스크립트로 모든 작업을 수행하는 대신 각 페이지의 HTML을 미리 만들어주는 Pre-rendering 방식 클라이언트 사이드 렌더링(CSR)을 혼용하는 하이브리드 방식이며, Pre-rendering을 사용할 경우 검색엔진최적화(SEO)에 유리하다.

https://nextjs.org/learn/basics/data-fetching/pre-rendering
https://nextjs.org/learn/basics/data-fetching/pre-rendering

프리 렌더링을 사용할 경우와 사용하지 않을 경우

 

2.2 Static Generation(SSG)

Next.js의 프리렌더링은 Static Generation과 Server-Side Rendering 두가지로 나뉜다.

https://nextjs.org/learn/basics/data-fetching/two-forms

Static Generation은 빌드 시 HTML을 생성한다. Pre-rendering된 HTML은 그 다음 각 요청에서 재사용 된다.

 

서버로부터 받는 데이터가 없는 경우 설정이 없어도 SSG가 생성되기에 그냥 사용하면 되지만, 서버로부터 받는 데이터가 있을 경우 getStaticProps를 사용해야한다. 하지만 빌드할 때 페이지가 미리 생성되기 때문에 fetch시 데이터가 변경되더라도 다시 빌드하지 않는 이상 반영되지 않는다. 그렇기에 유저의 요청 이전에 페이지를 띄워야 하는(업데이트가 없는) 블로그같은 페이지에 자주 사용된다.

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

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

  return {
    props: {
      posts,
    },
  }
}

export default Blog

 

2.3 Server-Side Rendering(SSR)

https://nextjs.org/learn/basics/data-fetching/two-forms

Server-Side Rendering은 각 요청이 일어났을 때 HTML을 생성하는 방법이다. 그렇기때문에 주로 데이터가 자주 업데이트 돼야 하는 페이지에 사용된다.

 

업데이트가 일어날 때 마다 서버에 요청을 하기 때문에 서버에 부담을 줄 가능성이 있고, 서버의 네트워크 상태에 따라 사용자 경험이 안좋아질 가능성이 있다. 하지만 페이지가 사전에 렌더링 되기 때문에 HTML에 대한 정보가 처음부터 포함되어 있어 검색엔진이 데이터 수집할 때 유리하다. 즉, meta태그가 미리 정의되는 등의 이유로 SEO에 유리하다.

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

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

  return { props: { data } }
}

export default Page

 

Incremental Static Regeneration(ISR)

ISR은 SSG의 단점을 보완한 방식으로, 정적으로 생성된 페이지도 필요에 따라 업데이트가 가능하게 해준다. 설정한 특정 시간이 경과되면 자동으로 리빌드가 되는 방식이다.

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

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

  return {
    props: {
      posts,
    },
    revalidate: 10, // In seconds
  }
}

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

  // Get the paths we want to pre-render based on posts
  const paths = posts.map((post) => ({
    params: { id: post.id },
  }))

  return { paths, fallback: 'blocking' }
}

export default Blog