Next.js #3. 넥스트의 사전 렌더링

김동욱·2022년 1월 26일
0

넥스트

목록 보기
3/3
post-thumbnail

넥스트는 기본적으로 모든 페이지를 사전 렌더링합니다. 그리하여 더 좋은 퍼포먼스와 검색엔진최적화가 잘됩니다.

사전 렌더링(pre rendering)은 넥스트의 가장 큰 장점입니다. 사전 렌더링에는 두가지 유형이 존재합니다.

  • 정적 생성(Static Generation)
  • 서버 사이드 생성(server side rendering)

이 두개의 차이점은 언제 html을 생성하는가입니다.


정적 생성(Static Generation)

정적 생성의 특징은 다음과 같습니다

  • 프로젝트가 빌드하는 시점에 html을 생성
  • 모든 요청을 빌드한 html을 재 사용
  • 정적 생성된 페이지들은 cdn에 캐시됨

    퍼포먼스상의 이유로 넥스트는 최대한 정적 생성을 권고합니다. 왜냐하면 페이지가 한번 빌드되어 CDN에 의해 제공이 될 수 있으며 매번 페이지 요청을 하는 것보다 렌더링하는 속도가 빠르기 때문입니다.

이런 정적 생성된 페이지는 서버에서 데이터를 자주 받아올 일이 없는 페이지(소개, 포스트ㅡ 각종 문서등)에 주로 사용됩니다. 반대로, 데이터의 업데이트가 많거나 사용자의 요청마다 매번 바뀌는 페이지라면 별로 좋은 선택이 아닐 것입니다.

그러나 몇몇의 페이지들에서 외부에서 데이터를 fetching 해오지 않으면, 렌더링이 안되는 경우가 있습니다. 예를 들어 파일 시스템에 접근하거나, 외부 API를 사용하거나, 데이터베이스에 쿼리를 날릴 때입니다. 넥스트는 이러한 경우(데이터를 사용한 정적 생성)도 지원하고 있습니다.

getStaticProps

export default function Home({posts}) {
  return (
    <div>
        {posts}
    </div>
  )
}

export const getStaticProps = async(context) => {
  const id = context.params.id
  const res = await fetch('api...');
  const posts = await res.json();

  return {
    props: {
      posts
    }
  }
}

getStaticProps는 정적 생성을 도와주는 함수입니다. 컴포넌트의 마지막에 작성해줍니다.

파라미터로 들어온 변수에는 여러가지 값들이 들어있는데 그중엔 url쿼리도 있습니다. 그리고 속성이 들어간 props를 리턴하면 그 속성값들은 컴포넌트의 props로 전달됩니다.

이 코드는 빌드 타임에 동작을 하며 함수 내에서 외부 데이터를 가져와 페이지 컴포넌트에 넘겨줄 수 있습니다.
이처럼 api를 호출하여 html을 구성하는 컴포넌트는 getStaticProps를 사용하면 됩니다. 만일 getStaticProps를 사용 안하고 기존의 리액트처럼 api를 호출했다면 빈 껍데기만 보일 것입니다.

빌드된 파일을 보면 json파일과 같이 있는걸 볼 수 있습니다. json파일은 빌드시 getStaticProps에서 불러온 api 정보들이 들어있습니다. 그리하여 html파일과 json파일이 같이 열리는걸 볼 수 있습니다.

하지만 정적 생성이더라도 데이터가 바뀌는 일이 있습니다. 그럴땐

export const getStaticProps = async(context) => {
  const id = context.params.id
  const res = await fetch('api...');
  const posts = await res.json();

  return {
    props: {
      posts
    },
    revalidate:10//10초뒤 재 갱신
  }
}

revalidate를 사용하면 페이지가 지정된 초마다 재 갱신이 됩니다. (그냥 이럴바엔 서버 사이드 생성을 사용하는게 좋을듯 합니다.)

getStaticPath

페이지가 만약에 동적 라우팅 api에 의존하고 있다면 어떻게 될까요, 예들들어 /page/photos같은 페이지는 photo list
api를 한번 빌드하면 데이터를 교체하기 전까진 변경할 필요가 없습니다. 하지만 /page/photos/[id].js처럼 동적 라우팅으로 쿼리를 받아와 api가 그때마다 다른 페이지는 어떻게 할까요 그때는 getStaticPath를 사용하면 됩니다. 하지만 getStaticPath는 getStaticProps와 함께 사용해야합니다.

export const getStaticPaths = async () => {
  const res = await fetch('https://.../photos')
  const photos = await res.json()

  // pre-render할 Path를 얻음 (posts를 통해서)
  const paths = photos.map((photo) => ({
    params: { id: photo.id },
  }))

  // 우리는 오로지 이 path들만 빌드타임에 프리렌더 함 
  // { fallback: false } 는 다른 routes들은 404임을 의미
  // true이면 만들어지지 않은 것도 추후 요청이 들어오면 만들어 줄 거라는 뜻
  return { paths, fallback: false }
}

export const getStaticProps = async(context) => {
  const id = context.params.id
  const res = await fetch(`https://.../photos/${id}`);
  const posts = await res.json();

  return {
    props: {
      posts
    }
  }
}

getStaticPaths로 리턴하는 객체안의 path속성은 배열이며 그안엔 params라는 이름의 객체가 정렬되있다. 그 객체에 원하는 경로의 쿼리명(ex) id)과 값으로 원하는 값(원하는 페이지명)을 리턴해준다. 즉 빌드타임에 pre-rendering할 경로들이 들어갑니다. 예를 들어

  return { 
    paths : [
    	params :{id: "1"},
        params :{id: "2"},
        params :{id: "3"},
    ]
    fallback: false 
  }
}

이런 식으로 리턴을 해면

  • /page/photos/1.js
  • /page/photos/2.js
  • /page/photos/3.js
    이 페이지들은 정적 생성이 된채로 api에 의존적일 필요가 없이 미리 빌드가 됩니다.

하지만 사진은 한두개가 아니고 수백가가 될탠데 그것들을 미리 생성하면 엄청난 용량의 낭비가 될것입니다. 그럴때 사용하는것이 fallback옵션입니다.
fallback은 paths 이외의 경로들에 대해 추후 요청이 들어오면 만들어 줄지 말지. 만다면 404를 리턴합니다. 예를들어 fallback true로 지정하면 /page/photos/4.js 처럼 paths로 지정안한 경로로 들어가면 실시간으로 html로 정적 생성을 실행합니다. flase는 그 반대입니다.


서버 사이드 생성(server side rendering)

서버 사이드 생성은 항상 최신 상태를 유지할 수 있습니다. php나 jsp처럼 html과 같이 파싱하여 보여주는 홈페이지와 비슷한 능력을 보입니다.

이런 정적 생성된 페이지는 서버에서 데이터를 변경해야하는 페이지(뉴스피드, sns, api를 호출하여 보여주는 상세 페이지)에 주로 사용됩니다. getServerSideProps는 빌드와 상관없이, 매 페이지 요청마다 데이터를 서버로부터 가져옵니다.

getServerSideProps


export default function Home({posts}) {
  return (
    <div>
        {posts}
    </div>
  )
}

export const getServerSideProps = async(context) => {
  const id = context.params.id
  const res = await fetch('api...');
  const posts = await res.json();

  return {
    props: {
      posts
    }
  }
}

getServerSideProps는 서버사이드렌더링을 도와주는 함수입니다. getStaticProps와 다르게 호출 될때마다 cdn에서 불러오는게 아닌 서버에서 정보를 불러옵니다. 그만큼 용량은 커졌지만 항상 최신 정보를 받을 수 있습니다.

profile
안녕하세요. 부산에서 근무하고 있는 프론트엔드 개발자 김동욱입니다. 영어 공부 겸 개발 공부를 위해서 글을 작성하고있습니다.

0개의 댓글