Pre-Redering & Data Fetching

세나정·2023년 3월 21일
0

Next.js

목록 보기
7/9
배울 내용
- Next.js의 Pre-Rendering
- SSG와 SSR
- 데이터가 있는 SSG, 데이터가 없는 SSG
- getStaticProps를 활용하여 외부 블로그 데이터를 인덱스 페이지로 가져오는 방법

Pre-Rendering

기본적으로 Next는 모든 페이지를 Pre-Rendering함
즉, Next는 클라이언트 측의 JS에서 모든 작업을 수행하는 것이 아닌 미리 각 페이지에 대한 HTML을 생성

이렇게 하기 때문에 기업들의 SEO를 가져올 수 있음

이렇게 생성되는 HTML들은 최소한의 JS만 연동되기 때문에
페이지가 그려질 때 JS는 완벽한 인터랙션을 가짐 (이것을 hydration라고 함)

React와는 다르게, 브라우저에서 JS를 비활성화 하더라도 JS없이 렌더링이 되는 걸 볼 수 있음


두 가지 형태의 Pre-Rendering

  • SSG (스태틱 사이트 제네레이션) : 빌드시 HTML를 생성하는 렌더링 방법으로 미리 렌더링된 HTML이 각 요청에서 재사용

  • SSR (서버 사이드 렌더링) : 각 요청에 HTML을 생성하는 사전 렌더링 방법
npm run dev 개발 모드에서 페이지는 모든 요청에 대해 미리 렌더링 됨 Production으로 전환시에도 SSG는 모든 요청이 아닌 빌드시 한 번만 발생

각 페이지마다의 기준

중요한 것은 하이브리드적으로 어떤 페이지에서는 SSG를, 어떤 페이지에서는 SSR을 사용할 수 있다는 것

언제 SSG? 언제 SSR?

우리의 페이지가 CDN에 의해 한 번만 만들어질 때는 SSG를 사용하는 것을 추천 받는데 그 이유는 이렇게 해야 서버에서 모든 요청마다 페이지를 렌더하는 것보다 훨씬 빠르기 때문

예시
  • 마케팅 페이지
  • 블로그 게시물
  • 전자상거래 제품 목록
  • 도움말 및 설명서

사용자의 요청에 앞서, 이 페이지를 미리 렌더링 할 수 있습니까? 라고 스스로에게 묻고 그 대답이 예인 경우 SSG를 선택해야함

하지만, SSG는 사용자 요청보다 먼저 페이지를 렌더링 할 수 없는 경우에는 좋지 않음 (요청이 잦은 페이지)

페이지에서 자주 업데이트가 되는 데이터에서는 SSR을 사용할 수 있음 속도는 더 느리지만 미리 렌더링된 페이지는 항상 최신 상태이기 때문

혹은 Pre-Rendering없이 클라이언트의 JS를 사용하여 자주 업데이트 되는 데이터를 채울 수 있음

SSG (with or without data)

SSG는 데이터 유무에 관계없이 수행할 수 있음

여태 실습한 페이지는 외부 데이터를 가져올 필요가 없었기에 이런 페이지는 앱이 프로덕션용으로 빌드될 때 자동으로 생성

하지만 일부 페이지는 외부 데이터를 가져오지 않고는 HTML을 그릴 수 없기 때문에 파일 시스템에 엑세스 하거나 외부 API를 가져오거나 빌드시 데이터베이스 쿼리를 해야만 함

Next는 이 경우 (SSG with data)를 즉시 지원

SSG (with data) getStaticProps

구성 요소를 내보낼 때 async함수도 함께 내보내어

  • getStaticProps 프로덕션에서 빌드시간에 실행되고
  • 함수 내에서 외부 데이터를 가져와 바로 넣어줄 수 있음
참고 : 개발 단계에서, getStaticProps는 각 요청 대신에 돌아감

마크다운 활용 데이터 삽입

루트폴더에 posts를 만든 후 여러 .md 파일을 생성
마크다운에 존재하는 메타데이터를 분석할 수 있는 gray-matter를 npm으로 설치

파일시스템을 읽기 위한 유틸리티 함수를 만들 것임
lib 라는 최상위 디렉토리 생성 후
안에 lib라는 파일을 만든 후에 posts.js 의 코드를 복사

import fs from 'fs';
import path from 'path';
import matter from 'gray-matter';

const postsDirectory = path.join(process.cwd(), 'posts');

export function getSortedPostsData() {
  // Get file names under /posts
  const fileNames = fs.readdirSync(postsDirectory);
  const allPostsData = fileNames.map((fileName) => {
    // Remove ".md" from file name to get id
    const id = fileName.replace(/\.md$/, '');

    // Read markdown file as string
    const fullPath = path.join(postsDirectory, fileName);
    const fileContents = fs.readFileSync(fullPath, 'utf8');

    // Use gray-matter to parse the post metadata section
    const matterResult = matter(fileContents);

    // Combine the data with the id
    return {
      id,
      ...matterResult.data,
    };
  });
  // Sort posts by date
  return allPostsData.sort((a, b) => {
    if (a.date < b.date) {
      return 1;
    } else {
      return -1;
    }
  });
}

Next에서 lib 폴더에는 pages, styles 폴더와 같이 할당될 이름이 없으므로 보통 lib 그 자체나 utils라는 파일명을 사용

이제 마크다운 파일들을 읽고 index.js에다가 넣어줄 것임

getStaticProps 구현

두 가지 Pre-Redering에서 각 페이지마다 렌더링 방법을 선택할 수 있기 때문에 hybrid로 구성 가능

SSG에서 getStaticProps() 활용

아까 작성했던 코드를 마무리 해주고

Props를 정상적으로 넣어줌 (index.js)

그러면 우리가 md 파일에 넣었던 정보들을 확인할 수 있음

원리

외부 API Fetch or Database 쿼리

또한 우리는 Fetch와 데이터베이스의 Query도 사용 가능

서버에나 활용되는 이러한 것들이 가능한 이유는 getStaticProps는 SSR기반이기 때문에 가능, 이런 것들은 CSR에서는 절대 불가함

심지어 브라우저의 JS 번들을 활용하지 않기에 우리가 데이터베이스에 바로 코드를 적을 수 있다는 것

development vs. production

개발 단계에서는 모든 요청마다 getStaticProps에서 실행
프로덕션 단계에서는 빌드시 한번만 getStaticProps에 의해 실행됨

getStaticProps는 페이지에서만 내보내질 수 있음 왜냐하면 페이지가 렌더링 되기 전에 React에 필요한 모든 데이터가 있어야 하기 때문

그렇다면 요청을 할 때마다 데이터를 가져와야 하는 경우엔?

앞서 누누이 말한대로, SSG는 빌드시 한번만 발생하므로 자주 업데이트 되거나 요청마다 변경되는 데이터에는 적합하지 않아서 이럴 땐 SSR을 사용해야함

요청시간에 Fetching Data

SSR을 활용한다면

getStaticProps대신 getServerSideProps를 사용하면 됨

getServerSideProps 사용하기


getServerSideProps는 요청시마다 호출되기 때문에 해당 매개변수 (context)에서는 요청별 매개변수가 포함됨

하지만 getServerSideProps 요청시마다 데이터를 가져와야하는 페이지를 미리 렌더링 하는 경우에만 사용 해야만함

서버가 모든 요청에 대해 결과를 계산해야하고 추가 구성없인 CDN에서 결과를 캐시할 수 없기에 느림

CSR

데이터를 미리 렌더링할 필요가 없을 땐 그냥 CSR을 활용

  • 외부데이터가 필요하지 않을 땐 그냥 Pre-Rendering
  • 페이지가 로드되면 JS를 활용하여 클라이언트에서 외부 데이터를 가져온 후 나머지를 채움

이런 접근 방식은 사용자 대시보드 페이지에 적합, 대시보드는 비공개의 사용자별 페이지이므로 요청이 많고 SEO와 관련이 없고 페이지를 미리 로드할 필요가 없기 때문

useSWR (Next.js)

Next에서는 SWR을 제공하여 데이터를 쉽게 가져옴
caching, revalidation, focus tracking, refetching on interval등을 제공

profile
압도적인 인풋을 넣는다면 불가능한 것은 없다. 🔥

0개의 댓글