Next.js 13 버전 - Data Fetching

moontag·2023년 2월 8일
11

Next.js

목록 보기
4/4
post-custom-banner

pre-rendering

  • 미리 각 페이지의 html을 생성하여 SEO 적용할 수 있게 하는 것
    공식문서 참고
  • 페이지마다 2가지 렌더링 방법을 선택적으로 사용가능
    1. SSG(Static-Site Generation)
    2. SSR(Server-Side Rendering)





1. SSG

Static-Site Generation 정적사이트 생성

  • 빌드 시 html 생성해두고 요청이 오면 생성해둔 html 재사용
  • 빈번한 업데이트 필요 없는 정적 페이지 만들 때 사용
    • 예시) 마케팅, 블로그 게시글, 설명서, 제품 목록 페이지
  • Next.js, Gatsby, Jekyll 등으로 만들 수 있음

2. SSR

Server-Side Rendering 서버사이드 렌더링

  • 사용자 각 요청마다 새 html 생성
  • 요청마다 데이터를 최신상태로 업데이트해야 될 경우 사용
  • SEO 성능 향상시켜줌







Next.js 13 버전 Data Fetching

fetch() 사용

async/await을 사용한 fetch() API 사용으로 변경

  • app 폴더 사용 시 getStaticProps, getInitialProps, getServerSideProps 등 이전방법은 해당폴더에선 지원안됨 참고
    (app 폴더는 베타버전으로 배포에서는 사용안하는 것이 권장됨)

  • fetch 옵션을 통해 getServerSideProps, getStaticProps 처럼 사용 가능

  • 예시

    export default funciton Home(){
      const a = use(fetchData())
      return <>{/* ... */} </>
    }
    export async function fetchData() {
      const res = await fetch(`https://.../data`)
      const data = await res.json()
      return data
    }

fetch 옵션

fetch('https://url', option)

export default async function Page() {
  // This request should be cached until manually invalidated.
  // Similar to `getStaticProps`.
  // `force-cache` is the default and can be omitted.
  const staticData = await fetch(`https://...`, { cache: 'force-cache' });

  // This request should be refetched on every request.
  // Similar to `getServerSideProps`.
  const dynamicData = await fetch(`https://...`, { cache: 'no-store' });

  // This request should be cached with a lifetime of 10 seconds.
  // Similar to `getStaticProps` with the `revalidate` option.
  const revalidatedData = await fetch(`https://...`, {
    next: { revalidate: 10 },
  });

  return <div>...</div>;
}
  • { cache: 'force-cache' } - 기본값으로 생략가능(getStaticProps와 유사)
  • { cache: 'no-store' } - 모든 요청에서 최신 데이터 받아오기 (getServerSideProps와 유사)
  • { next: { revalidate: 10 } } - 10초 후 새 요청오면 페이지 새로 생성 (revalidate옵션이 있는 getStaticProps와 유사)





Server and Client Components

Server Component

  • fetch data
  • 백엔드 리소스에 접근 시
  • 중요한 정보 서버에 보관 시(API key, access token ..)
  • 클라이언트 측 JS 코드 줄여야 할 때

Client Component

  • fetch data - SWR, React Query 등 라이브러리 사용시
  • 이벤트 리스너 추가시(onClick, onChange ..)
  • State, Lifecycle Effects 사용시(useState, useEffect, useReducer ..)
  • 브라우저 Web API 사용시(localStorage, sessionStorage, Cookie)
  • State, Effect, 브라우저 API에 의존하는 커스텀 Hook 사용시
  • React Class Component 사용시










13 버전 이전 방식

  • SSG - getStaticProps, getStaticPaths
  • SSR - getServerSideProps

1. SSG

1) getStaticProps

  • 외부 데이터(file system, API, DB..)를 미리 가져와야 하는 경우 사용
  • 페이지가 아니거나 _app, _document, _error 파일에서 사용불가

getStaticProps함수 내부에서 API 호출 생성하면 성능이 저하됨

export default function Home({ posts }) { ... }

// 서버에서 빌드 시 해당함수가 호출된다
export async function getStaticProps() {
  // 외부 데이터를 받기 (file system, API, DB, etc)
  // 하지만 이 함수 내부에서 호출하면 성능이 저하됨
  const data = await fetch('https://.../posts')
  const posts = await res.json()

  //  props는 빌드시 Home 컴포넌트에 전달된다
  return {
    props: { posts }
  }
}

✅ 따라서 lib/폴더에 파일생성해서 api경로를 분리시킨다.

// lib/load-posts.js 로 분리
export async function loadPosts() {
  const res = await fetch('https://.../posts/')
  const data = await res.json()
  return data
}

// pages/blog.js
import { loadPosts } from '../lib/load-posts'

export async function getStaticProps() {
  const posts = await loadPosts()

  return { props: { posts } }
}

2) getStaticPaths

  • 페이지의 경로가 외부데이터에 따라 다를 때 사용
    ex)/pages/외부데이터제목

  • 동적 경로를 통해 getStaticProps할 때 경로 목록을 정의해줘야함
    pages/**/[id].tsx파일로 빌드시에 정적 생성할 페이지 정함

  • paths.params를 getStaticProps 로 리턴해줌

  • params에 빌드할 페이지를 넣어야함
    pages/posts/[id].tsx 파일존재하고 /posts/123 경로면
    params는 {id: "123"} 이어야 함

예시

function Post({ post }) {
  const router = useRouter()
  //  getStaticProps() 끝나면 실행
  if (router.isFallback) {
    return <div>Loading...</div>
  }
  // Render post...
}
// id로 동적경로 만드는 예시- posts/1652
export async function getStaticPaths() {
  const res = await fetch('https://.../posts/')
  const posts = await res.json()
  const paths = posts.map((post) => ({
    params: { id: post.id },
  }))
  return {
    paths,
    fallback: true, // false or "blocking" 
  };
}
export async function getStaticProps({ params }) {
  // params contains the post `id`.
  // If the route is like /posts/1, then params.id is 1
  const res = await fetch(`https://.../posts/${params.id}`)
  const post = await res.json()

  // Pass post data to the page via props
  return { props: { post } }
}
  // 블로그 글 제목으로 동적경로 생성하는 예시- /posts/nextjs-start
  export async function getStaticPaths() {
  const posts = getAllPosts(['slug'])
  return {
    paths: posts.map((post) => {
      return {
        params: {
          slug: post.slug,
        },
      }
    }),
    fallback: false, //다른 routes는 404
  }
}



2. SSR

1) getServerSideProps

  • 자주 변경된 최신 데이터를 페이지에 업데이트시킬 때 사용
  • 해당 함수는 클라이언트측에서 import안되고
    직접 서버 측 코드를 작성할 수 있음(ex. db에서 fetch하는 작업..)
export async function getServerSideProps(context) {
  const res = await fetch(`https://.../data`)
  const data = await res.json()

  return {
    props: { data }, 
  }
}





profile
터벅터벅 나의 개발 일상
post-custom-banner

0개의 댓글