getStaticProps와 getServerSideProps

Sheryl Yun·2022년 8월 23일
0

Next.js

목록 보기
4/6
post-thumbnail

이번에 채용 과제를 하다가 드디어 Next.js의 두 props에 대해 조금은 이해하게 되어 추가 공부를 위해 글을 쓴다. 독일어를 배울 때도 그랬지만 나는 일단 단어가 길어지면 어렵게 느껴지고 머리가 하얘지는(?) 편인데 이 두 props를 처음 마주쳤을 때도 같은 기분이 들었던 것 같다.

우선 공식 문서를 보기 전에 블로그를 이곳저곳 둘러보면서 듬성듬성 배경지식을 쌓고 이 배경지식을 바탕으로 (제일 믿을 만한 출처인) 공식 문서를 탐독하려 한다. 아는 지식이 있는 상태에서 영어(!)를 읽으면 그나마 눈에 좀 잘 들어오기도 하고, 기존에 블로그로 얻은 배경지식과 비교해 보면서 다른 부분이 있다면 더 숙지해야 할 부분인 공식 문서 내용이 머리에 더 잘 들어오는 효과도 있기 때문이다.


Next.js는 사전 렌더링(pre-rendering)이 가능하다는 특징을 갖고 있는 React 프레임워크이다.

pre-rendering을 위한 data fetching을 위해 기존에는 getInitialProps를 사용했지만, Next.js 9.3 버전부터는 getInitialProps가 getStaticProps, getServerSideProps, getStaticPaths로 분리되었다.

모두 pre-render가 필요한 경우에만 사용하는 것이 좋다.

이 중 많이 사용되는 getStaticProps와 getServerSideProps의 차이와 활용에 대해 알아보자.

두 props는 왜 등장했을까?

getStaticProps와 getServerSideProps는 React의 useEffect의 단점을 보완하는 효과가 있다.

useEffect의 의존성 배열에 빈 대괄호를 넣을 경우 최초 렌더링 시에만 1회 실행된다고 알고 있었다. 보통 useEffect 안에는 상태값을 바꿔 렌더링시키기 위한 useState의 setter 함수가 들어간다.
그러나 실제로 이 함수에 바로 값이 저장되지 않고 최초 렌더링 시에는 useState 상태가 초기값으로 렌더링이 되었다가 useEffect가 실행되어 내부 함수가 실행되는 과정 이후 한 번의 렌더링이 더 있은 후에야 해당 useEffect가 적용되는 형태였던 것이다.
이러한 과정은 페이지 깜박임을 유발하여 사용자 경험을 감소시킨다고 한다.

예시

import { useState, useEffect } from 'react';

const SampleComponent = () => {
  const DUMMY_DATA = [
    {
      id: 1,
      title: 'first data'
    },
    {
      id: 2,
      title: 'second data'
    }
  ]

  const [sampleState, setSampleState] = useState([]);
  
  useEffect(() => {
    setSampleState(DUMMY_DATA);
  }, []);
  
  return (
    <>
      {sampleState.map((data) => <h1 key={data.id}>{data.title}</h1>)}
    </>  
  )
};

export default SampleComponent;

최초 렌더링 시 useState의 상태값 sampleState는 초기값인 빈 배열의 상태를 가진다.
최초 렌더링 이후 useEffect가 실행되어 setter 함수를 통해 값이 채워지게 되면, 두 번째 렌더링을 통해 채워진 상태값이 보여진다. 이 과정에서 화면 깜박임이 생기게 되는 것이다.

pre-rendering

위와 같은 문제를 Next.js에서는 pre-rendering으로 해결했다. 렌더링 이전에 미리 값을 지정해두어 최초 렌더링 때 바로 값이 보이게끔 하는 것이다.

이러한 pre-rendering을 위한 data fetching을 할 수 있는 기능으로 getStaticPropsgetServerSideProps가 있다.

getStaticProps

  • 빌드 시에 딱 한 번만 호출되고, 바로 static file로 빌드된다.

  • 이후에는 수정이 불가능하다.

  • 즉, SSG (Static Site Generation) 개념이다.

  • 최초 빌드 시 빌드되는 값이 추후에 수정될 일이 없는 경우에 사용하기 좋다.

  • 원칙적으로는 호출할 때 데이터 fetch를 하지 않으므로 성능면에서는 getServerSideProps보다 더 좋다. (But revalidate로 조절 가능)

  • 예시: 모든 정적인 페이지의 form

  • 앞에 나온 예시에 적용해보자.

    // 이번에는 DUMMY_DATA를 컴포넌트 밖으로 뺐다.
    const DUMMY_DATA = [
      {
        id: 1,
        title: "first data",
      },
      {
        id: 2,
        title: "second data",
      },
    ];
    
    const SampleComponent = (props) => { // 여기 props가 getStaticProps에서 반환한 props!
      return (
        <>
          {props.data.map((data) => (
            <h1 key={data.id}>{data.title}</h1>
          ))}
        </>
      );
    };
    
    export async function getStaticProps() {
      return {
        props: {
          data: DUMMY_DATA,
        },
        // revalidate: 10,
      };
    }
    
    export default SampleComponent;

    getStaticProps을 사용하면 컴포넌트가 렌더링 되기 전에 getStaticProps에서 반환되는 값을 미리 컴포넌트에 props로 넣어주기 때문에 useEffect, useState와 같은 번거로운 hook 사용이 필요가 없다..!

추가: revalidate 적용

getStaticProps의 경우에도 요청이 들어올 때마다 주기적으로 업데이트되도록 해주는 장치가 있다. 바로 revalidate이다. 위 코드블럭에서 주석처리한 부분을 적용하면 10초마다 새로 업데이트 된다.

getServerSideProps

  • page가 요청받을 때마다 호출되어 pre-rendering을 진행한다.
  • 즉, SSR (Server Side Rendering) 개념이다.
  • 빌드 이후 자주 바뀌게 될 동적 데이터가 들어갈 때 사용하기 좋다.
  • pre-render가 꼭 필요한 동적 데이터가 있는 페이지에 사용하면 된다.
  • 매 요청마다 호출되므로 성능은 getStaticProps에 뒤지지만, 내용을 언제든 동적으로 수정이 가능하다.
  • 마찬가지로 같은 예시에 적용해보자.
const DUMMY_DATA = [
  {
    id: 1,
    title: "first data",
  },
  {
    id: 2,
    title: "second data",
  },
];

const SampleComponent = (props) => {
  return (
    <>
      {props.data.map((data) => (
        <h1 key={data.id}>{data.title}</h1>
      ))}
    </>
  );
};

export async function getServerSideProps(context) {
  const req = context.req;
  const res = context.res;

  return {
    props: {
      data: DUMMY_DATA,
    },
  };
}

export default SampleComponent;

getServerSideProps는 서버 쪽에서 렌더링하는 것이므로 파라미터로 context를 받아 서버의 요청 및 응답을 저장하는 req, res 변수를 저장해둬야 한다.

따로 revalitdate로 주기를 정하지 않는 이상 다시 업데이트하지 않는 getStaticProps와 달리, 요청이 들어올 때마다 호출하기 때문에 getServerSideProps는 getStaticProps에 비해 성능상으로는 안 좋지만 내용을 언제든지 수정할 수 있다는 장점이 있다.

상황에 따라 더 적절한 것을 선택하면 될 것 같다.

참고 링크

[Next.js] getStaticProps vs getServerSideProps

Next.js - getStaticProps vs. getServerSideProps, 차이와 활용

profile
데이터 분석가 준비 중입니다 (티스토리에 기록: https://cherylog.tistory.com/)

0개의 댓글