Next.js - 서버로부터 데이터 불러오기

carrot·2021년 10월 19일
0

Nextjs

목록 보기
6/15
post-thumbnail

next 렌더링

기본적으로 next는 모든 페이지를 미리 렌더링 합니다. 미리 렌더링을 하여 html을 생성하게 되면 더 나은 성능과 SEO 이점을 얻을 수 있습니다.

next에는 두 가지 형태의 사전 렌더링이 존재합니다.

    1. 정적 생성
      빌드 시에 페이지를 HTML로 만들어 요청시 제공합니다.
    1. 서버 사이드 렌더링
      페이지 요청시 서버 사이드 렌더링을 통하여 HTML을 제공합니다.

외부 데이터를 필요로 하지 않는다면 next는 빌드 시에 페이지를 렌더링하여 요청시마다 제공하게 됩니다.

외부 데이터를 필요로 한다면 서버 사이드 렌더링을 통하여 외부 데이터를 이용하여 렌더링을 한 후 HTML을 제공합니다.
이때 서버 사이드 렌더링에 대하여 next에서 제공하는 옵션이 있습니다. 이를 통해 서버 사이드 렌더링시 외부 데이터를 불러오는 법을 알아보고 효율적인 HTML을 제공하는 방법을 배워 봅시다.

github api를 활용하여 유저 정보와 레파지토리 데이터들을 불러온 후 github 레파지토리를 따라 만들어 보면서 next 라우팅을 다시 한 번 해보고, 다양한 방법으로 데이터를 받아보는 실습을 해볼 예정입니다.

1. getServerSideProps

next는 getServerSideProps는 페이지의 데이터를 서버로부터 제공받는 기본 API를 가지고 있습니다. 이는 서버에서 데이터를 패치하여 초기 데이터를 전달하도록 구성이 되어 있습니다.

우선 서버에서 데이터를 패치하기 위해 isomophic-unfetch 모듈을 설치합니다.

yarn add isomophic-unfetch

github에서 제공하는 api 중에서 유저의 정보를 받아오는 api를 활용합니다. api의 경로는 다음과 같습니다.

https://api.github.com/users/username

서버에서 데이터를 받아오는 코드를 작성합니다.

// index.js

import fetch from "isomorphic-unfetch";

const index = ({ user }) => {
  const username = user && user.name;

  return <div>{username}</div>;
};

export const getServerSideProps = async () => {
  try {
    const res = await fetch("https://api.github.com/users/yourcarrot0214");
    if (res.status === 200) {
      const user = await res.json();
      return { props: { user } };
    }
    return { props: {} };
  } catch (error) {
    console.log(error);
    return { props: {} };
  }
};

export default index;
  • getServerSideProps는 서버측에서 props를 받아오는 기능을 합니다.
  • 페이지를 요청 시마다 실행되며, getServerSideProps에서 페이지로 전달해준 데이터를 서버에서 렌더링을 하게 됩니다.
  • 서버에서 실행되기 때문에, 앞의 코드를 새로고침을 하여 실행해 본다면 콘솔 출력이 브라우저가 아닌 터미널에서 되는 것을 확인할 수 있습니다.
  • fecth를 이용하여 gethub api의 유저 정보를 불러옵니다.
    • 데이터 요청은 에러가 발생할 수 있기 때문에 항상 try-catch를 이용하여 에러 발생으로부터 스크립트가 죽는 것을 방지하도록 합니다.
  • getServerSideProps에서 리턴한 props 값들은 페이지의 props로 전달됩니다.

getServerSideProps와 동적 라우팅을 이용하여 원하는 유저의 정보를 서버에서 불러오는 기능을 구현해 봅시다.

유저명을 입력받기 위해서 index.js파일을 수정합니다.

> index.js

import React, { useState } from "react";
import Link from "next/link";

const App = () => {
  const [username, setUsername] = useState("");
  return (
    <div>
      <label>
        username
        <input value={username} onChange={(e) => setUsername(e.target.value)} />
      </label>
      <p>{username} github 검색하기</p>
      <Link href={`/users/${username}`}>
        <a>검색하기</a>
      </Link>
    </div>
  );
};

export default App;
  • 검색하기를 클릭하게 되면 입력된 텍스트를 쿼리로 전달하며 /users/[name] 페이지로 이동하게 됩니다.

/users/[name] 페이지를 불러올 때 외부 데이터인 깃허브 유저의 정보를 불러오도록 합니다.

> pages/users/[name].jsx

import fetch from "isomorphic-unfetch";

const name = ({ user }) => {
  const username = user && user.name;
  return <div>{username}</div>;
};

export const getServerSideProps = async ({ query }) => {
  const { name } = query;
  try {
    const res = await fetch(`https://api.github.com/users/${name}`);
    if (res.status === 200) {
      const user = await res.json();
      console.log("username : ", user.name);
      return { props: { user } };
    }
    return { props: {} };
  } catch (error) {
    console.log(error);
    return { props: {} };
  }
};

export default name;
  • 파일명의 [name]값은 getServerSideProps의 매개변수 값인 query로 받아올 수 있습니다.
  • query로 얻은 name값을 github api의 파라미터로 전달하여 원하는 유저의 정보를 불러올 수 있습니다.

2. getStaticProps

getStaticProps는 빌드 시에 데이터를 불러와 결과를 json으로 저장하여 사용합니다. 따라서 일관된 데이터를 보여주게 됩니다.

> pages/static.jsx

const staticPage = ({ time }) => {
  return <div>{time}</div>;
};

export const getStaticProps = async () => {
  return { props: { time: new Date().toISOString() } };
};

export default staticPage;

  • getStaticProps에서 props로 현재 시간을 time 값으로 전달합니다.
  • yarn build를 통해 애플리케이션을 빌드하면 위 이미지와 같은 결과를 얻을 수 있습니다.
  • yarn start로 빌드된 애플리케이션을 실행하여 /static 페이지로 접속하면은 전달된 time값이 출력되며 이는 새로고침을 해도 데이터가 변경되지 않습니다.
    • 이는 빌드시 생성된 정적인 데이터가 변경되지 않음을 의미합니다.

때로는 props 데이터가 변경되기를 원할수도 있습니다. 로그인 이후 주기적인 로그인 상태 확인이라던가 말이죠. next는 9.5버전부터 만들어진 정적 데이터가 갱신될 수 있도록 옵션을 제공합니다.

export const getStaticProps = async () => {
  return { props: { time: new Date().toISOString() }, revalidate: 3 };
};
  • 옵션으로 revalidate값을 number 타입으로 설정하면 해당 초 마다 데이터가 갱신됩니다.
  • 다시 빌드 후 실행해 보면 3초마다 달라진 time 데이터를 출력하는 것을 확인할 수 있습니다.

이번에는 동적 페이지에서 getStaticProps를 사용해보도록 하겠습니다.
> pages/static/[name].jsx

import fetch from "isomorphic-unfetch";

const name = ({ user, time }) => {
  const username = user && user.name;
  return (
    <div>
      {username}
      {time}
    </div>
  );
};

export const getStaticProps = async ({ params }) => {
  try {
    const res = await fetch(`https://api.github.com/users/${params.name}`);

    if (res.status === 200) {
      const user = await res.json();
      return { props: { user, time: new Date().toString() } };
    }
    return { props: { time: new Date().toString() } };
  } catch (error) {
    console.log(error);
    return { props: { time: new Date().toString() } };
  }
};

export async function getStaticPaths() {
  return {
    paths: [{ params: { name: "yourcarrot0214" } }],
    fallback: true,
  };
}

export default name;
  • getServerSideProps와는 다르게 query 대신 params를 사용합니다.
  • getStaticPaths를 통해 params를 미리 정의해야 합니다.
  • fallback 값은 지정한 경로 외의 경로에 대한 설정으로 false면 이외의 경로는 모두 404 에러 페이지로 연결 됩니다.
  • getStaticpaths페이지의 경로가 외부 데이터에 의존할 때 사용합니다.
    • params에 미리 정의된 name값을 통해 static/yourcarrot0214페이지를 getStaticProps를 사용하여 데이터를 저장하고 static/yourcarrot0214에 접속할 때마다 미리 렌더링된 HTML을 제공합니다.

      yarn build를 하게 되면 터미널에서 결과를 확인할 수 있습니다.

3. getInitialProps

getInitialProps는 9.3버전 이전부터 서버 사이드 데이터 패치를 위해 사용되던 함수입니다. next는 9.3버전 이상부터 getServerSidePropsgetStaticProps를 사용하는것을 권장하고 있습니다.

getInitialProps를 예제를 통해 알아봅시다.

> pages/users/[name].jsx

import fetch from "isomorphic-unfetch";

const name = ({ user }) => {
  const username = user && user.name;
  return <div>{username}</div>;
};

name.getInitialProps = async ({ query }) => {
  const { name } = query;
  try {
    const res = await fetch(`https://api.github.com/users/${name}`);
    if (res.status === 200) {
      const user = await res.json();
      console.log("username : ", user.name);
      return { props: { user } };
    }
    return { props: {} };
  } catch (error) {
    console.log(error);
    return { props: {} };
  }
};

export default name;

독립된 함수가 아닌 컴포넌트의 함수에 getInitialProps를 추가하는 방식으로 사용합니다.

빌드 후 '/'에 접속하여 유저 아이디를 검색하게 되면 users/[name]페이지로 이동하게 됩니다. 이때 유저의 이름이 브라우저의 콘솔에 출력되는 것을 확인할 수 있고, 이후 새로고침시 값은 브라우저가 아닌 터미널에서 출력됩니다.
이는 getInitialProps를 사용하게 되면 초기 렌더링 시에는 서버에서 데이터를 불러오지만 클라이언트측 네비게이션을 사용하게 되면 클라이언트측에서 데이터를 불러오는것을 의미합니다.

외부 데이터를 사용하는지에 따라 getServerSidePropsgetStaticProps를 구분해서 사용하고, 초기 데이터를 외부에서 불러온 뒤 이후 클라이언트측 데이터를 불러오려면 getInitialProps를 사용하여 페이지를 렌더링 합니다.

profile
당근같은사람

0개의 댓글