[Next.js] Pre-Rendering의 개념과 종류

YUKI KIM·2022년 3월 5일
1

Next.js 공식 문서를 따라가는데 확실하게 이해가 안되는 부분이 있어 알아보기로 했다. 모른다고 그냥 넘어가기엔... Next.js에서 가장 중요한 부분 중 하나라고 생각돼서 정리까지 하기로 함. 아자자. 💨


Pre-Rendering

기본적으로 Next.js는 모든 페이지를 Pre-Rendering 한다. 이 방식 덕에 Next.js가 더 나은 성능과 SEO를 가능하게 된 것이다.

개념

Next.js는 Client-side의 JavaScript에 의해 실행하는 것 대신 사전에 각 페이지의 HTML을 생성한다. 이러한 방식을 Pre-Rendering이라고 한다. 그러니까 한마디로 Pre-Rendering이란? 미리 HTML을 만드는 방식 쯤으로 이해해두면 된다!

기존 방식과의 차이

차이 알아보기 전에 단어 하나 알고 가자. Hydration이라는 단어는 직역하면 수분 공급인데, 브라우저에서 하나의 페이지가 로드될 때 그 페이지의 JavaScript code가 실행(로드)되고 페이지를 interacitve 있게 만드는 것을 뜻한다.

기존의 퓨어한 React에서는 초기 로드 시 빈 화면이 나온다. 그래서 퓨어한 React로 제작한 App은 초기에 들어갈 때 페이지가 모두 로드되는 속도가 느린 편이다.

Next.js에서의 Pre-Rendering은 미리 생성한 HTML 파일을 초기 로드 시에도 표시한다. 그래서 브라우저 버전이 낮아서 React를 실행시킬 수 없는 사용자도 Next.js가 미리 생성한 HTML 화면을 볼 수 있다.

두 가지 방식

Next.js는 Static GenerationServer-side Rendering이라는 두가지 방식의 Pre-Rendering 방식을 가지고 있다. 이 둘의 가장 큰 차이점으로 페이지의 HTML이 생성되는 방식이 있다.

그리고 중요하게도, Next.js는 각 페이지에 사용하고자 하는 pre-rendering 방식을 선택할 수 있게 해준다. 즉 Static Generation과 Server-side Rendering의 두 가지 방식을 혼용한 "Hybrid" Next.js 앱을 만들 수 있게 해준다.

  • Static Generation : HTML은 build-time에 생성되며 모든 요청에서 미리 생성된 HTML을 재사용 (Next.js's recommand)
  • Server-side Rendering : HTML은 각각의 요청마다 생성. 즉, 재사용은 하지 않음

Next.js에서는 성능상의 이유로 Static Generation 방식을 추천한다. Static Generation 페이지는 CDN에서 캐싱을 하여 미리 생성해 놓은 HTML을 재사용한다. 그러나 페이지에서 최신의 데이터를 fetching 해야 하는 경우, Server-side Rendering 방식이 유일한 선택일 수 있다.


Static Generation

Static Generation의 HTML은 build-time에 생성된다고 했다. 하지만 외부 데이터를 가져오는 경우와 아닌 경우 Static Generation은 조금 다르게 사용된다.

Static Generation without data

function ErrorPage() {
  return <div>404 Page</div>;
}

데이터가 없는 Static Generation은 매우 심플하다. 이 경우는 당연히 build-time에 HTML을 생성한다.

Static Generation with data

Pre-Rendering을 위해 외부 데이터를 가져와야하는 경우가 있다. 두 가지 시나리오가 있으며 각각의 경우에 Next.js가 제공하는 다음 기능을 사용할 수 있다.

  1. page contents가 외부 데이터에 의존하는 경우: getStaticProps
  2. page path가 외부 데이터에 의존하는 경우: getStaticPaths (일반적으로 getStaticProps 와 함께 사용)

그럼 각각의 시나리오를 살펴보자.

1. getStaticProps

이 경우는 페이지의 contents가 외부 데이터에 따라 다른 경우이다. 아래는 블로그에 올라와 있는 모든 post들을 렌더링하는 예제이다.

function Blog({ posts }) { 
  // Blod의 post들 렌더링 하는 코드
} 

// build-time 시 실행
export async function getStaticProps() {
  const res = await fetch('BASE_URL/post');
  const posts = await res.json();
  return { 
    props: { posts, } 
  } 
} 

export default Blog;

데이터를 가져와 Pre-Rendering을 하기 위해서는 getStaticProps를 비동기 방식으로 export하여 사용한다. 이 함수는 build-time 시 호출되며 Pre-Rendering 시 가져온 데이터를 page의 contents로 전달한다.

2. getStaticPaths

이 경우는 페이지의 경로가 외부 데이터에 따라 다른 경우이다. 예를 들어 블로그에서 특정 post를 click하면 post/[id].js 파일을 로드하는 경우다.

function Post({ post }) {
  // post 렌더링 하는 코드
} 

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: false }는 다른 라우팅에 404를 발생하겠다는 의미 
  return { paths, fallback: false } 
}

export async function getStaticProps({ params }) {
  const res = await fetch(`BASE_URL/post/${params.id}`);
  const post = await res.json(); 
  return { props: { post } } 
} 

export default Post

id 값은 Pre-Rendering 시 외부 데이터에 따라 달라질 수 있다. 이것을 다루기 위해서 getStaticPaths를 비동기 방식으로 사용한다. 이 함수는 build-time에 실행되며 Pre-Rendering을 위해 원하는 path를 구체화한다.


Server-side Rendering

Server-side Rendering은 요청마다 HTML 페이지를 생성한다. 하나의 페이지를 Server-side Rendering 하기 위해서는 getServerSideProps 함수를 비동기 처리로 사용한다.

예를 들어, 외부 API로 부터 자주 업데이트되는 데이터를 Pre-Rendering하기 위한 페이지가 필요하다면, getServerSideProps 함수를 작성하여 아래와 같이 페이지에 전달할 수 있다.

function Page({ data }) { 
  // data 렌더링 하는 코드
} 

// 모든 요청마다 실행
export async function getServerSideProps() { 
  const res = await fetch(`https://.../data`); 
  const data = await res.json(); 
  return { props: { data } }; 

} 

export default Page;

언제 무엇을 사용할지

우선, Next.js 공식 문서에서는 성능 상의 이유로 Static Generation을 권장한다. 하지만 Static Generation은 자주 update되는 데이터를 보여주기에는 적합하지 않다. 이러한 경우는 성능은 저하될지라도, contents를 최신으로 유지할 수 있는 Server-side Rendering이 적합하다.

따라서, 각각의 Pre-Rendering 방식이 어느 상황에 적절한지 알고 있는 것이 더더욱 중요하다. Next.js 공식문서에도 기재되어 있듯이, 페이지마다 원하는 Pre-Rendering 방식을 선택할 수 있기 때문에 요구사항에 맞게 구성하는 것이 중요할 것이다.


레퍼런스

profile
유키링と 욘데 쿠다사이

0개의 댓글