웹공부

Next.js 튜토리얼 따라하기 - 2 (사전렌더링, 데이터 가져오기)

syom 2022. 3. 21. 13:13

기본적으로 Next.js 는 모든 페이지를 미리 렌더링한다.

즉, Next.js 는 클라이언트 측 JavaScript 로 모든 작업을 수행하는 대신 각 페이지에 대해 미리 HTML을 생성한다.

생성된 HTML은 해당 페이지에 필요한 최소한의 JavaScript 코드와 연결된다. 브라우저에서 페이지를 로드하면 해당 JavaScript 코드가 실행되고 페이지가 완전히 대화식으로 만들어진다 (이 과정을 hydration, 수화 라고 함)

사전 렌더링이 진행중인지 확인하는 방법

  1. 브라우저에서 JavaScript 를 비활성화한다
  2. (개발자도구 → 커맨드+Shift+P → 자바스크립트 검색 후 사용중지)
  3. 다음 페이지에 액세스 → https://next-learn-starter.vercel.app/
  4. 앱 UI 가 제대로 되어있는지 확인

(localhost 에선 제대로 확인 못함)

→ React 로 시도할 경우에는 앱을 아예 볼 수 없음

렌더링

Next.js 에서는 정적 생성(Static Generation)과 서버측 렌더링(Server-side Rendering)의 두가지 사전 렌더링 형식이 있다. 이 둘의 차이점은 HTML을 생성할 때.

  • 정적 생성 : 빌드시 HTML 을 생성하는 사전 렌더링 방식, 사전 렌더링된 HTML 은 각 요청에서 재사용됨

  • 서버측 렌더링 : 각 요청에 대해 HTML 을 생성하는 사전 렌더링 방식

⇒ npm run dev 의 개발모드에서는 모든 페이지는 정적 생성을 사용하는 페이지의 경우에도 각 요청에서 미리 렌더링 된다.

페이지별 설정 가능

Next.js 를 사용하면 각 페이지에 사용할 사전 렌더링 양식을 선택할 수 있다!!

⇒ 정적생성 + 서버측 렌더링 둘다 사용하는 하이브리드 Next.js 앱을 만들 수 있음

정적생성 vs 서버측 렌더링

정적생성

  • 정적생성이 더 빠르기 때문에 가능하면 정적생성(데이터 포함 및 미포함)을 사용하는 것이 좋다!
  • 정적생성 쓰는게 좋은 페이지 예제
    • 마케팅 페이지, 블로그 게시물, 인터넷 쇼핑몰 제품 목록, 도움말 및 문서
  • 사용자의 요청이 있기 전에 페이지를 미리 렌더링할 수 있을까? 했을 때 답이 예 라면 정적 생성을 선택해야 한다.
  • 반면에 사용자의 요청보다 미리 렌더링 할 수 없다면 서버측 렌더링을 이용하자.

서버측 렌더링

  • 속도는 느리지만 미리 렌더링된 페이지는 항상 최신 상태로 유지된다.
  • 또는 사전 렌더링을 건너 뛰고 클라이언트 측 JS 를 사용해서 자주 업데이트 되는 데이터를 채울 수 있다.

데이터가 있거나 없는 정적 생성

데이터가 없는 경우엔 그냥 정적으로 생성하면 되니까 문제가 없다. 하지만 외부 데이터가 필요한 경우에는 외부데이터를 가져오지 않고는 HTML을 렌더링하지 못할 수도 있다. Next.js 는 이런 데이터를 사용한 정적 생성을 즉시 지원한다.

getStaticProps

Next.js 에서는 getStaticProps 페이지 컴포넌트를 내보낼때 async 와 함께 쓸 수도 있다

  • getStaticProps 는 프로덕션 빌드 시간에 실행된다.
  • 함수 내에서 외부 데이터를 가져와 페이지에 props 로 보낼 수 있다.
export default function Home(props) { ... }

export async function getStaticProps() {
  // Get external data from the file system, API, DB, etc.
  const data = ...

  // The value of the `props` key will be
  //  passed to the `Home` component
  return {
    props: ...
  }
}

→ getStaticProps 는 Next.js 에게 이 페이지에는 일부 데이터를 불러와야해서 빌드시 이 페이지를 미리 렌더링해야 한다고 말해주는 셈이다.

  • 개발모드에서는 getStaticProps 대신 각 요청에 대해 실행된다.

getStaticProps 사용해보기

getStaticProps 구현

  1. 설치
npm install gray-matter

https://www.npmjs.com/package/gray-matter

  1. 최상위 루트에 lib 디렉토리 생성
  2. lib 디렉토리 내 posts.js 파일 생성
  3. posts.js 파일 내에서 가져올 데이터 생성
  4. pages/index.js 에서 getStaticProps 함수 생성 후 posts.js 에서 만든 함수 가져와 넣기
  5. index.js 내의 Home 컴포넌트의 props 에 받아온 데이터 추가

getStaticProps 세부 사항

  • 외부 API 가져오기 가능
    • Next.js 에서 fetch 는 클라이언트, 서버 측 둘다 polyfill 할수있음
  • 개발 모드에서는 getStaticProps 의 모든 요청에 대해 실행 됨
  • 프로덕션에서는 getStaticProps 는 빌드시 실행 됨 (이후에 반환되는 fallback, getStaticPaths 도 이용 가능)
  • 페이지에서만 허용됨(페이지가 아닌 파일에서는 내보낼 수 없음)

요청시 데이터 가져오기 (서버측 렌더링)

getStaticProps 대신 getServerSideProps 사용해야함

getServerSideProps

export async function getServerSideProps(context) {
  return {
    props: {
      // props for your component
    }
  }
}

클라이언트 측 렌더링

데이터를 미리 렌더링할 필요가 없는 경우 클라이언트 측 렌더링을 사용할 수 있다.

(사용자 대시보드 페이지에 적합)

SWR

Next.js 에서 swr 을 이용하면 클라이언트 측 렌더링이 가능하다.

import useSWR from 'swr'

function Profile() {
  const { data, error } = useSWR('/api/user', fetch)

  if (error) return <div>failed to load</div>
  if (!data) return <div>loading...</div>
  return <div>hello {data.name}!</div>
}

즉, Next.js 는 클라이언트 측 JavaScript 로 모든 작업을 수행하는 대신 각 페이지에 대해 미리 HTML을 생성한다.

생성된 HTML은 해당 페이지에 필요한 최소한의 JavaScript 코드와 연결된다. 브라우저에서 페이지를 로드하면 해당 JavaScript 코드가 실행되고 페이지가 완전히 대화식으로 만들어진다 (이 과정을 hydration, 수화 라고 함)