[Next.js] getStaticProps, getStaticPaths, getServerSideProps 란?

jwhan·2021년 12월 20일
12

Next.js

목록 보기
2/2
post-thumbnail

Next.js 는 정적 사이트 생성(SSG)과 서버 사이드 렌더링(SSR) pre-rendering 웹사이트 생성을 도와주는 프레임워크라는 설명을 다른 글에서 소개했다.


Next.js에서는 SSG와 SSR을 위한 데이터 패칭 기능을 제공한다.
즉 사이트를 렌더링하기 전 어떤 데이터를 이용해서 페이지를 생성할 것인지에 대한 함수를 작성하는 기능을 말하는 것이다.

예를 들어 블로그 포스트에 대한 컴포넌트가 있다고 가정해보자.

function BlogPost() {
  return (
    <div>
      <h1> title </h1>
      <div> content </div>
    </div>
  )
}

위와 같이 포스트 컴포넌트는 제목내용 이 필요하다.

그리고 블로그 포스트는 데이터베이스에 따로 저장해두었고, 아래와 같은 형식이라고 가정해보자.

https://.../posts
[
  {
    id: 1,
    title: 'Next.js란?',
    content: 'Next.js란 ...'
  },
  {
    id: 2,
    title: 'SSG와 SSR',
    content: '정적 사이트 생성은 ...'
  }
  ...
]

그리고 우리는 SSG를 통해 빌드 시 이 데이터를 BlogPost 컴포넌트에 전달해서 렌더링하고 싶다.

그럴 때 어떻게 해야할까?

getStaticProps

이럴 때 사용할 수 있는 Next.js의 기본 함수가 바로 getStaticProps 이다.

static 에서 정적 사이트 생성, props 에서 컴포넌트의 인풋과 연관이 있다는 점을 눈치챘을 것이다.

getStaticProps는 빌드 시 데이터를 패치하는 함수이다.

Next.js 코드에 getStaticProps 가 있다면 Next.js가 빌드시 알아서 함수를 실행하고, 그 props를 컴포넌트에 전달한다.

기본틀은 아래와 같이 생겼다.

export async function getStaticProps(context) {
  return {
    props: {},
  }
}

위에서 들었던 블로그 포스트 예제로 돌아가서 내가 id값이 1인 Next.js란? 블로그 포스팅을 렌더링하고 싶다면 아래와 같이 코드를 작성할 수 있다.

function BlogPost({ post }) {
  return (
    <div>
      <h1> {post.title} </h1>
      <div> {post.content} </div>
    </div>
  )
}

export async function getStaticProps() {
  const res = await fetch('https://.../posts/1')
  const post = await res.json()
  return {
    props: {
      post,
    }
  }
}

export default BlogPost

getStaticProps에서 데이터베이스로부터 id 값이 1인 해당 포스트 데이터를 불러오고, 그 post 데이터를 props로 리턴한다. 그러면 컴포넌트가 props를 통해 렌더링을 할 수 있는 것이다.


getStaticPaths

이 쯤 되면 이런 의문도 생길 수 있다.

만약 블로그 포스팅이 100개가 있다면, 이런 경우에는 경로를 어떻게 설정해야될까? 매 포스팅마다 pages/ 폴더 아래 자바스크립트 파일을 만들어줘야할까?

당연히 아니다. Next.js에는 동적 라우팅(dynamic routes) 기능이 있고, getStaticPaths를 사용해 렌더링하기 위해 필요한 경로를 설정할 수 있다.
(동적 라우팅에 대한 설명은 다른 글에서 자세히 다루겠습니다)

getStaticPaths 는 데이터에 따라 pre-rendering할 페이지의 동적 경로를 지정하는 함수이다.

기본틀은 아래와 같다.

export async function getStaticPaths() {
  return {
    paths: [
      { params: { ... } }
    ],
    fallback: ...
  };
}

그리고 getStaticPathspathsgetStaticProps 로 리턴한다.


블로그 포스팅 예제로 돌아오자면, 각 포스팅을 위해
/pages/posts/1.js
/pages/posts/2.js
...
/pages/posts/100.js
각각 파일을 생성할 필요 없이, /pages/posts/[id].js 파일 하나만으로도 모든 페이지를 생성할 수 있다는 뜻이다.

function BlogPost({ post }) {
  return (
    <div>
      <h1> {post.title} </h1>
      <div> {post.content} </div>
    </div>
  )
}

export async function getStaticPaths() {
  const res = await fetch('http://.../posts')
  const posts = await res.json()
  
  const paths = posts.map((post) => ({
    params: { id: post.id },
  }))
  
  return { paths, fallback: false }

}

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

export default BlogPost

getStaticPaths 에서 /posts 에 저장된 모든 블로그 포스팅 데이터를 불러오고, id 값을 파라미터로 리턴한다.
그러면 getStaticProps 에서는 각 pathparams 값을 받아 id를 통해 블로그 포스트를 불러오고, 그 postprops로 컴포넌트에 전달한다.

한 눈에 정리하자면 이렇다.

그리고 fallback 에 대한 부분은 paths에서 리턴되지 않은 경로에 대해서 어떻게 처리할지를 정하는 것인데, 우선은 아래의 내용만 알고 넘어가도 무관하다.

  • false : 404 를 전달하겠다.
  • true : 404를 전달하지 않고, "fallback" 버전의 페이지를 첫 request에서 보여준 후, 페이지가 생성되고 나면 그 이후의 request부터는 생성된 페이지를 보여주겠다.
  • blocking : 서버 사이드 렌더링을 통해 HTML이 생성되기 까지 기다리겠다.

getServerSideProps

마지막으로 getServerSidePropsgetStaticProps 와 비슷하지만 서버 사이드 렌더링을 위한 함수이다.
getStaticProps 처럼 컴포넌트에 props를 넘겨준다는 공통점이 있지만, 빌드 시가 아닌 매 request마다 실행된다는 차이점이 있다.

getServerSideProps 는 매 request마다 데이터를 패치하는 함수이다.

export async function getServerSideProps(context) {
  return {
    props: {},
  }
}

또 하나 getStaticProps 와 다른 점은, 'req' 미들웨어가 제공된다. (client로 부터 request를 받을 때 마다 실행되므로)


정리

  • getStaticPropsgetStaticPaths는 정적 사이트 생성을 위해 사용된다.
  • getServerSideProps는 서버 사이드 렌더링을 위해 사용된다.
  • getStaticPropsgetServerSideProps는 데이터를 패치하는 함수이다.
  • getStaticPaths는 페이지의 동적 경로를 지정하는 함수이다.

1개의 댓글

comment-user-thumbnail
2024년 3월 5일

덕분에 도움이 되었습니다. 감사합니다

답글 달기