Next.js Rendering

bongbong·2024년 6월 16일
0

Next.js

목록 보기
2/6
post-thumbnail

이 포스팅은 Next.js 문서 번역 및 정리한 내용입니다.

기본적으로 Next.js는 모든 페이지를 pre-render한다. React를 단독으로 사용할 때 클라이언트측에서 JavaScript로 렌더링하는 대신 각 페이지에 대해 미리 HTML을 생성한다. pre-rendering을 사용하면 성능과 SEO가 향상될 수 있다.

생성된 각 HTML은 페이지를 위해 필요한 최소한의 JavaScript로 결합하게 되는데 이것을 Hydration이라고 부른다. 브라우저에서 페이지가 로드될 때, JavaScript가 실행되고 페이지를 인터렉티브하게 만든다. Hydration이 완료되어야 이벤트나 로직이 실행될 수 있다.

Pre-rendering

Next.js에는 정적 생성과 서버 측 렌더링이라는 두 가지 형태의 pre-rendering이 있다. 차이점은 페이지의 HTML을 생성하는 시점에 있다.

  • Static Generation : HTML은 빌드 시 생성되며 각 요청에서 재사용된다.
  • Server-side Rendering : 각 요청마다 HTML이 생성된다.

Next.js는 각 페이지마다 사용할 pre-rendering 방식을 선택할 수 있다. 그래서 대부분의 페이지에서 Static Generation을 사용하고 다른 페이지는 Server-side Rendering을 사용해서 하이브리드 Next.js 앱을 만들 수 있다.

성능상의 이유로 Server-side Rendering 보다 Static Generation을 사용하는 것이 좋으며 성능을 높이기 위해 정적으로 생성된 페이지를 CDN으로 캐시할 수 있다. 하지만 몇몇 케이스에서 Server-side Rendering이 유리한 선택일 수 있다.

📎Next.js는 useEffect나 서버사이드 함수를 사용하지 않는 이상 기본적으로 SSG로 렌더링한다.

📎next.js는 기본적으로 pre-rendering을 지원한다. 프리렌더링은 정적 생성, 동적 생성 두 가지로 나뉘는데 정적 생성은 빌드 타임에 HTML을 생성하는 것이고 후자는 서버단에서 HTML을 생성하는 것이다. 브라우저에서 페이지를 로드할 때 js 파일을 받아와 실행시키고 pre-rendering된 HTML과 js 파일을 결합해서 사용자와 상호작용가능하도록 만드는 작업을 Hydration이라고 부르는데 마치 마른 대지에 물을 뿔려주는것같은 단어이다.

SSR(Server Side Rendering)

사용자가 요청할 때마다 서버에서 HTML을 생성하여 반환하는 방식이다. 사용자가 페이지를 요청할 때마다 최신 데이터를 기반으로 HTML을 생성하여 클라이언트에 보내기 때문에, 초기 페이지 로드 시점에 최신 콘텐츠를 제공할 수 있다.

SSG(Static Site Generation)

Static Generation without data

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

위와 같은 외부 데이터를 가져올 필요없는 페이지는 빌드 타임에 HTML을 생성한다.

Static Generation with data

외부 데이터를 fetching 해야하는 경우 두 가지 방법이 있다.
1. data에 따라 페이지 컨텐츠가 달라진다 -> getStaticProps
2. data에 따라 페이지 경로가 달리진다. -> getStaticPaths + getStaticProps

언제 Static Generation을 사용하나?

빌드 시점에 pre-rendering을 해도 되는 페이지라면 SSG를 사용하는 것이 성능적으로 좋다.

CSR(Client side Rendering)

브라우저가 로드된 후 Javascript 파일을 실행시켜서 HTML을 만드는 방식이다. 초기 실행시 사용자가 페이지를 보기까지 시간이 걸릴 수 있다는 단점이 있으나 그 뒤부터는 페이지 이동시 깜빡임 없는 부드러운 화면전환을 제공한다는 장점이 있다.

next.js에서 CSR을 사용하는 방법은
1. useEffect()
2. SWR or TanStack Query와 같은 라이브러리

CSR로만 렌더링을 하게 되면 SEO에 불리하다는 단점이 있고 초기 사용자가 페이지를 보기까지 시간이 걸리기 때문에 CSR과 SSR을 결합하여 하이브리드로 사용하기를 장려하고 있다.

ISR(Incremental Static Regeneration)

사이트를 빌드한 후에도 정적 페이지를 생성하거나 업데이트할 수 있게 해준다.

  • Good to know : edge runtime은 ISR과 호환되지 않는다. 캐싱이 필요하면 직접 cache-control 헤더를 설정하여 stale-while-revalidate를 사용해야 한다.

ISR을 사용하려면 getStaticProps에 revalidate props를 추가한다.

function Blog({ posts }) {
  return (
    <ul>
      {posts.map((post) => (
        <li key={post.id}>{post.title}</li>
      ))}
    </ul>
  )
}
 
// 이 함수는 서버 측에서 빌드 시에 호출.
// 새 요청이 들어오면 revalidate가 활성화된 경우 서버리스 함수에서 다시 호출될 수 있다.
export async function getStaticProps() {
  const res = await fetch('https://.../posts')
  const posts = await res.json()
 
  return {
    props: {
      posts,
    },
    revalidate: 10,
  }
}
 
export async function getStaticPaths() {
  const res = await fetch('https://.../posts')
  const posts = await res.json()
 
  // 포스트를 기반으로 사전 렌더링할 경로를 가져온다.
  const paths = posts.map((post) => ({
    params: { id: post.id },
  }))
 
  // 이 경로들만 빌드 시에 사전 렌더링.
  // { fallback: 'blocking' }은 경로가 존재하지 않는 경우 요청 시에 페이지를 서버 렌더링한다.
  return { paths, fallback: 'blocking' }
}
 
export default Blog
  • 초기 요청 후 10초 이내의 모든 요청은 즉시 캐시된다.
  • 10초가 지난 후 다음 요청도 캐시된 페이지가 표시된다.
  • Next.js는 백그라운드에서 페이지를 다시 생성한다.
  • 페이지 생성에 성공하면 캐시를 무효화하고 업데이트된 페이지를 표시한다.
  • 백그라운드에서 재생성에 실패하면 여전히 이전 페이지를 보여준다.

Good to know : CDN 캐싱이 활성화되어있는지 확인해야한다.

Reference

0개의 댓글