Next.js의 Data Fetching을 알아보자!✨

pre-rendering

Next.js는 pre-rendering을 지원한다.
이는 클라이언트 사이드에서 Javascript로 모든 작업을 수행하는 대신에 각 페이지의 HTML을 미리 생성하는 것을 의미한다.

HTML이 생성된 시점에 Javascript 파일이 로드되지 않았기 때문에 Javascript와 관련한 코드들은 동작하지 않는다.
로드된 Javascript 파일과 HTML을 연결하는 작업을 hydration이라고 한다.

만약 pre-rendeirng이 없다면 Javascript 전체가 로드될때까지 기다려야하므로 사용자는 빈 화면을 보는 시간이 늘어나고, 성능 면에서도 좋은 평가를 받기 힘들 것이다.

또한, 검색 엔진은 기본적으로 HTML을 읽어가는데 자바스크립트를 해석할 수 없는 검색 엔진이라면 해당 웹 페이지에서 읽어갈 것이 없다.
자바스크립트가 로드되기 전까지 빈 화면일 것이기 때문이다.
예를 들어, 리액트는 자바스크립트가 로드되기 전까지 HTML이 빈 껍데기로 보여지고, HTML 파일도 단 1개이다.
pre-rendering은 이러한 불편함을 해소할 수 있다.

따라서, Next.js의 pre-rendering은 보다 나은 성능을 구축할 수 있고, pre-render된 HTML을 SEO봇에게 전달하여 SEO를 최적화할 수 있는 장점이 있다.

그렇다면 어떻게 pre-rendering을 적용할 수 있을까?

SSR(Server Side Redering)

SSR은 사용자의 요청이 있을때마다 HTML을 생성한다.

getServerSideProps 함수를 사용하면 SSR을 구현할 수 있다.
간단하게 아래 예제 코드를 살펴보자! 👀

export async function getServerSideProps() {
    console.log('server side')
    return {
        props: {time: new Date().toISOString()}
    }
}

export default function Home({time}) {
  return <h1>{time}</h1>;
}

코드를 실행해보면 새로고침이 될때마다 시간이 변경되고, IDE의 터미널에 ‘server-side’ 가 찍히는걸 확인할 수 있었다.
즉, getServerSideProps 로 구현한 SSR은 페이지에 대한 요청이 있을때마다 서버 사이드에서 실행되며, 해당 페이지의 HTML을 생성한다는 것을 알 수 있었다.

SSG (Static-Site Generation)

SSG는 빌드 타임에 HTML을 생성한다.

단, 개발 환경에서는 SSG로 데이터 패칭을 하더라도 매 요청마다 pre-rendering이 발생한다.

getStaticProps, getStaticPaths 함수를 사용하여 SSG를 구현한다.
(다이나믹 라우팅을 사용하는 경우 HTML을 미리 생성해야 할 페이지의 path를 알아야 하기 때문에 getStaticPaths 함수를 사용해서 path를 리턴해주고, getStaticProps 함수에 넘겨주는 형태로 함께 사용해야 한다.)

export async function getStaticProps() {
    console.log('server side')
    return {
        props: {time: new Date().toISOString()}
    }
}

export default function Home({time}) {
  return <h1>{time}</h1>;
}

해당 코드를 yarn dev로 개발 환경에서 확인하는 경우 브라우저를 새로고침할 때마다 시간이 바뀌고, IDE 터미널에 ‘server-side’ 라고 기록된다.
마치 SSR처럼 동작한다.
SSG가 제대로 동작하는지 확인하기 위해서는 빌드를 해야 한다.
SSG가 pre-rendering 할때 HTML을 생성하는 시점이 빌드 타임이기 때문이다.

빌드 후 다시 실행해보면 브라우저를 아무리 새로고침해도 시간이 변경되지 않는걸 확인할 수 있다.
빌드 타임때 생성한 HTML을 pre-rendering해서 정적으로 보여주기 때문이다.

SSR은 매 요청마다 새로운 HTML을 생성하기 때문에 서버에 과부하가 발생할 수 있는 리스크가 있지만, SSG를 활용하면 pre-rendering도 하면서 데이터 패칭이 많이 일어나더라도 SSR보다는 서버의 부하를 줄일 수 있다.
블로그 게시물처럼 정적으로 제공될 수 있는 웹 사이트는 SSG로 구현하는 것이 좋겠다.

ISR (Incremental Static Regeneration)

특정 주기로 정적 사이트를 재생산한다.

getStaticProps 함수에 revalidate라는 옵션을 추가해서 사용하면 된다.

export async function getStaticProps() {
    console.log('server side')
    return {
        props: {time: new Date().toISOString()},
        revalidate: 1,
    }
}

export default function Home({time}) {
  return <h1>{time}</h1>;
}

앞서 SSG 예제에서 살펴본 것과 차이점은 1초 주기로 시간이 업데이트된다.
IDE 터미널에도 ‘server-side’ 라고 1초 주기로 찍힌다.
즉, getStaticProps 함수에 revalidate를 리턴해주면 지정해준 시간의 주기만큼 데이터 패칭을 새로 한다. SSR과 SSG의 장점을 취해서 사용할 수 있다!

번외: CSR (Client Side Rendering)

Next.js에서 기존의 리액트 방식처럼 CSR을 사용할 수도 있다.

import { useEffect, useState } from 'react';

export default function Home() {
    const [time, setTime] = useState();
    useEffect(() => {
        console.log('client side')
        setTime(new Date().toISOString())
    }, [])
  return (
          <>
       {time}
      </>
  )
}

위 코드를 실행하면 브라우저를 새로고침할 때마다 시간이 업데이트 되고, 브라우저의 콘솔창에 ‘client-side’라고 기록되는걸 볼 수 있다.
즉, 클라이언트 사이드에서 데이터 패칭을할 수도 있다.

Next.js의 pre-rendering 및 데이터 패칭에 대해 알아보았다.
필요에 따라 SSR, SSG, ISR, CSR 중 선택하면 되겠다!

Next.js 완전 정복 : 확장성 높은 커머스 서비스 구축하기, 최지민 님의 강의를 보고 정리한 내용입니다.

댓글남기기