Web/React

[React] Next JS Pre-rendering / Static Generation(getStaticProps ) / SSR(getServerSideProps)

서상혁 2021. 3. 8. 01:27

-----

기본 개념

  • Next JS 는 모든 페이지를 pre-rendering 한다.
    • 즉, Client-side JS 로딩 방식으로 하지 않고 HTML 을 미리 만든다.
    • 성능개선, SEO 최적화
  • Static GenerationServer-side Rendering 방식으로 나뉜다.
    • 성능상의 차이로 인해 Static Generation 방식이 권장된다.
    • 각각의 방식중 하나만 골라야되는 것이 아니라, 페이지 마다 선택이 가능하다.

     

Static Generation

 

📖
HTML 이 빌드시에 미리 생성되고, 각 request 마다 이를 재사용하는 방식
  • 좀 더 자세히 말하자면 next build 명령어 입력 시에 HTML이 생성된다는 것을 의미한다.
    • 이는 CDN을 통해 캐싱될 수 있다.

 

Static Generation 은 언제 사용될까?

📖
유저의 request 보다 앞서서 렌더링이 가능한 페이지에!!

예시

  • 마케팅용 페이지 (Marketing pages)
  • 블로그 포스트들 (Blog posts)
  • 이커머스 프로덕트 나열 (E-commerce product listings)
  • 도움말 (Help and documentation)
  • etc...

 

External Data 가 없는 경우

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

export default About
  • 다음과 같은 경우는 다른 외부 data가 없다.
  • 따라서 자동으로 HTML 이 생성된다.

 

External Data 가 존재하는 경우

  • getStaticProps 를 이용한다.

 

예시

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

// This function gets called at build time
export async function getStaticProps() {
  // Call an external API endpoint to get posts
  const res = await fetch('https://.../posts')
  const posts = await res.json()

  // By returning { props: { posts } }, the Blog component
  // will receive `posts` as a prop at build time
  return {
    props: {
      posts,
    },
  }
}

export default Blog
  • 외부 api 를 통해 posts 데이터를 가져오고, 인자로 넘겨준다.
  • getStaticProps 를 통해 구현됐으므로 빌드 시에 실행되어 HTML 화 된다.

 

페이지가 External Data에 종속되는 경우

  • getStaticPaths 를 이용해 해당 경로 페이지들을 미리 생성

 

Fallback

  • getStaticPaths 는 fallback 키가 반드시 필요하다.
    • fallback 키가 false인경우, getStaticPaths 에 없는 경로는 404 page 를 반환한다.
      • (미리 렌더링할 페이지가 적을 경우, 업데이트가 적을 경우에 주로 사용)
    • fallback 키가 true인경우, getStaticPaths 에 없는 경로는 설정된 FallbackPage 를 반환하고, getStaticProps 를 통해 해당 url 에 필요한 data 를 요청한다. 이후의 동일한 요청에 대해서는 방금 작업을 이용해서 미리 렌더링된 페이지가 제공된다.
  • fallback 이 true 인 경우는, 동적 라우팅을 통해 미리 렌더링을 할 페이지가 너무 많아서 전부다 getStaticPaths 를 통해 pre-rendering 하기에 버거울 때 사용하면 좋다.

 

예시

// pages/posts/[id].js
import { useRouter } from 'next/router'

function Post({ post }) {
  const router = useRouter()

  // If the page is not yet generated, this will be displayed
  // initially until getStaticProps() finishes running
  if (router.isFallback) {
    return <div>Loading...</div>
  }

  // Render post...
}

// This function gets called at build time
export async function getStaticPaths() {
  return {
    // Only `/posts/1` and `/posts/2` are generated at build time
    paths: [{ params: { id: '1' } }, { params: { id: '2' } }],
    // Enable statically generating additional pages
    // For example: `/posts/3`
    fallback: true,
  }
}

// This also gets called at build time
export async function getStaticProps({ params }) {
  // params contains the post `id`.
  // If the route is like /posts/1, then params.id is 1
  const res = await fetch(`https://.../posts/${params.id}`)
  const post = await res.json()

  // Pass post data to the page via props
  return {
    props: { post },
    // Re-generate the post at most once per second
    // if a request comes in
    revalidate: 1,
  }
}

export default Post

getStaticPaths

  • api 에서 fetch 해온 결과 posts 의 id 들을 이용해 /posts/[id] 페이지들을 미리 생성
    • paths 예시 : /posts/1 /posts/2 /posts/3

getStaticProps

  • getStaticPaths 를 통해 지정된 path 들의 데이터들을 fetch 후 HTML 미리 생성

 

기타

  • 타입스크립트에서의 사용
import { GetStaticPaths } from 'next'

export const getStaticPaths: GetStaticPaths = async () => {
  // ...
}

 

 

Server-side Rendering

 

📖
매 request 마다 HTML 이 server-side로 새로 생성되는 방식!

 

  • Static Generation 이 매 빌드시에 pre-rendering 하는 방식이라면, Server-side Rendering 은 매 요청마다 HTML 을 생성한다.
  • getServerSideProps 를 이용한다. (getInitalProps 는 deprecated됨)
  • getServerSideProps 의 사용 방법은 getStaticProps 와 매우매우 유사하다.
    • 단지 차이는 언제 rendering을 하느냐의 차이!

 

예시

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

// This gets called on every request
export async function getServerSideProps() {
  // Fetch data from external API
  const res = await fetch(`https://.../data`)
  const data = await res.json()

  // Pass data to the page via props
  return { props: { data } }
}

export default Page
  • 앞선 형태랑 다를바가 없다.
  • 다만 거듭 강조하지만 매 요청마다 해당 fetch 가 실행된다.

 


참고

 

728x90