본문 바로가기
코딩 - 프로젝트, 만들기/코딩 - My small trip

[솔로프로젝트] My small trip(3) - Next.js의 렌더링(SSR, SSG, ISR)

by sky211b 2024. 1. 4.

 

React는 기본적으로 CSR(client side rendering)기반으로 동작한다.

유저가 요청을 보내면 CSR방식은 일단 HTML과 Javascript파일을 받아와 렌더링 하는데, 이 후 필요한 파일들을 한번에 받아오기 때문에 이 후 요청을 비교적 빠르게 실행시켜줄 수 있다는 장점이 있다. 하지만 처음에 렌더링을 하는 시간이 오래 걸릴 수 있으므로, 유저가 요청을 보낸 후 렌더링이 완료 될 때까지 빈 화면을 보는 시간이 길어 질 수 있다. 

 

이와 대비대는 개념은 SSR(server side rendering)방식인데, 서버에서 완성된 HTML을 보내주어 바로 렌더링 할 수 있도록 한다. 이 방식은 CSR에 비해 첫 화면 렌더링이 빠르나, 유저의 요청마다 서버에서 완성된 HTML을 보내주어야 하므로 서버에 부하가 커질 수 있다. 

 

Next.js를 사용하면 PreRendering 기능을 활용할 수 있는데, 이는 서버쪽에서 html파일을 미리 렌더링하고 이후 요청이 오면 필요한 JavsScript파일을 받아 이벤트가 작동할 수 있도록 하는 방식이다. 미리 html을 만들어 두었기 때문에 렌더링을 위한 시간이 적게 걸리므로 유저가 빈 화면을 봐야하는 시간이 줄어든다. 
이 PreRendering을 구현하는 방법은 Next.js에서 3가지가 있다.


1.SSR(Server-Side-Rendering)
위에서 정리한 것과 같이 유저의 요청마다 서버에서 완성된 HTML을 전송하여 렌더링 하는 방식이다. 
NEXT.JS는 getServerSideProps, getStaticProps, getStaticPaths 함수를 사용하여 이를 구현한다. 이 방식을 통하면 요청마다 서버에선 최신의 데이터를 포함한 HTML을 만들어서 전송한다.
동적으로 다른 데이터를 받아와야 하는 경우에 알맞는 방식이다. 예를 들어 최신 정보나 차트등을 보여줄 때 사용한다.

export async function getServerSideProps(context) {
  const res = await fetch(`https://.../data`);
  const data = await res.json();

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

const Main = ({ listData }) => {
  <ul>
    {listData.map((item) => (
      <li key={item.id}>{item.title}</li>
    ))}
  </ul>;
};

 


2.SSG(Static-Site-Generation)
SSR처럼 서버에서 HTML을 받아 렌더링 하지만, 요청마다 새로운 HTML을 만들지 않고, 빌드 시에 만든 HTML을 재사용한다. 공지글 블로그 글 같은 정적인 페이지를 만들때 사용한다. 이런 경우는 유저의 요청마다 최신의 데이터를 가지고 다시 HTML을 만들 필요가 없기 때문에 빌드 시에 만든 HTML을 재사용하는 것이다. 
이 방식을 사용하면 SSR보다 서버에 주는 부담이 적어지게 된다. 
getStaticProps함수를 사용하여 구현 할 수 있다. 

export async function getStaticProps() {
  const res = await fetch(`https://.../data`);
  const data = await res.json();

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

const Main = ({ listData }) => {
  <ul>
    {listData.map((item) => (
      <li key={item.id}>{item.title}</li>
    ))}
  </ul>;
};

 


3.ISR (Incremental-Static-Regeneration)
SSG처럼 미리 만든 HTML을 사용하고 싶은데, 데이터가 너무 오래 된 상태로 유지되지 않을까 걱정이 될 수 있다. 이때 사용할 수 있는 방식은 ISR이다. 이는 설정한 시간 마다 서버에 새로 요청을 해 HTML을 다시 만든다. SSG는 빌드마다 새로 HTML을 만들지만 ISR방식은 설정된 시간마다 특정 페이지를 다시 빌드하여 업데이트 해 줄 수 있다는 장점이 있다.

아래 코드에서 보면 revalidate부분이 있는데 이 부분이 html재빌드 설정 시간을 조절하는 부분이다. SSG와 getStaticProps 사용 방법은 같지만 revalidate에 명시된 숫자(초)마다 페이지가 새로 렌더링 되는 차이가 있다.

export const getStaticProps = async ({ params }) => {
  const id = params.id;
  const res = await axios.get(`https://url/${id}`);

  return {
    props: {
      list: res.data,
    },
    revalidate: 20,
  };
};

const Detail = ({ list }) => {
  <ul>
    {list.map((item) => (
      <li key={item.id}>{item.title}</li>
    ))}
  </ul>;
};