hmk run dev

Next.js 정적 생성(Static Generation) - getStaticProps, getStaticPaths 본문

React

Next.js 정적 생성(Static Generation) - getStaticProps, getStaticPaths

hmk run dev 2022. 3. 1. 15:53

Pre-rendering

- 기본적으로 모든 페이지 프리 렌더링

- 사전에 HTML 파일을 만든다는 의미

- 퍼포먼스 향상, SEO 

 

 

next.js에서 자바스크립트를 껐을때 보여지는 화면을 관찰해보자!

끄는 방법 > F12 > F1 > Debugger > Disable Javascript

 

왼쪽이 끄기 전 오른쪽이 끈 후입니다.

 

메인페이지

 

 

 

상세페이지

 

서버사이드 렌더링으로 만든 상세 페이지는 CSS차이 정도 밖에 없는 것 같습니다 :)

> 서버에서 이미 데이터를 가져와 HTML로 만든다음에 내려줘서!

 

no Pre-render &  Pre-render 

 

no Pre-render - 아무것도 없다가 JS가 로드 된 이후에 화면을 그리기 시작함

Pre-render - 사전에 만들어진 HTML 메타데이터 포함 요소들이 나온다 이후 JS가 로드된 이후 JS 기능들이 작동을함

> Hydration 정적이 요소들에 생기를 불어넣는? 것을 의미함

 

Pre-render는 두 가지 방식으로 생성될 수 있는데

 

Static Generaion(정적생성), Server side Renderring(서버 사이드 렌더링)

차이점은 언제 html 파일을 만드냐 입니다.

 

Static Generaion(정적생성)

빌드 시 html 파일을 만듦

 

Server side Renderring(서버 사이드 렌더링)

요청 시 html 파일을 만듦

 

Next.js는 정적 생성을할지 SSR을 할지 페이지마다 개발자가 정할 수 있음!

 

Nextjs에선 아래 페이지들을 정적생성 할 것을 권고하고 있습니다.

 

- 마케팅 페이지

- 블로그 게시물

- 제품 목록

- 도움말, 문서

 

SSR 권고 페이지

 

- 항상 최신 상태가 필요한 페이지

- 관리자 페이지

- 분석 차트

 


그렇다면 기존 정적생선 변경 전 후 코드를 비교해보자

 

useEffect를 통해 서버와 통신하고 데이터를 가져와서 뿌려준다.

export default function Home() {
  const [list, setList] = useState([]);
  const [isLoading, setLoading] = useState(true);

  const API_URL = process.env.NEXT_PUBLIC_API_URL;

  function getData() {
    Axios.get(API_URL).then((res) => {
      console.log(res.data);
      setLoading(false);
      setList(res.data);
    });
  }

  useEffect(() => {
    getData();
  }, []);

  return (
    <div>
      <Head>
        <title>HOME | hmk1022</title>
      </Head>
      {isLoading && (
        <div style={{ padding: "300px 0" }}>
          <Loader inline="centered">Loading...</Loader>
        </div>
      )}

      {!isLoading && (
        <>
          <Header as="h3" style={{ paddingTop: 40 }}>
            베스트 상품
          </Header>
          <Divider />
          <ItemList list={list.slice(0, 9)} />
          <Header as="h3" style={{ paddingTop: 40 }}>
            신상품
          </Header>
          <Divider />
          <ItemList list={list.slice(9)} />
        </>
      )}
    </div>
  );
}

 

getStaticProps를 통해 데이터를 받아와 props로 넘기고 화면에 뿌려준다!

export default function Home({ list }) {
  return (
    <div>
      <Head>
        <title>HOME | hmk1022</title>
      </Head>

      <>
        <Header as="h3" style={{ paddingTop: 40 }}>
          베스트 상품
        </Header>
        <Divider />
        <ItemList list={list.slice(0, 9)} />
        <Header as="h3" style={{ paddingTop: 40 }}>
          신상품
        </Header>
        <Divider />
        <ItemList list={list.slice(9)} />
      </>
    </div>
  );
}

// 정적 생성
export async function getStaticProps(context) {
  const apiUrl = process.env.apiUrl;
  const res = await Axios.get(apiUrl);
  const data = res.data;

  return {
    props: {
      list: data,
      name: process.env.name,
    },
  };
}

 

빈 화면을 그린후 api 호출을 통해 화면을 채우는것이 아닌

미리 만들어진 static 파일을 보여준다!

 

이상태로 build를 하고 build 파일 안을 보게되면

빌드 시점 만들어진 html 파일들이 엄청나게 긴 코드로 생성되어 있습니다..!

 

 

그렇다면 다이나믹 라우트를 사용하는 페이지는 정적으로 생성할 순 없을까??

 

갯수가 한정적이라면 가능합니다.

 

getStaticPath

 

정적 생성할 페이지를 한정적으로 만들었습니다.

const Post = ({ item, name }) => {
  return (
    <>
      <Head>
        <title>{item.name}</title>
        <meta name="description" content={item.description}></meta>
      </Head>
      {name}환경입니다.
      {item && <Item item={item} />}
    </>
  );
};

export default Post;

// 정적 생성
export async function getStaticPaths(context) {
  return {
    paths: [
      { param: { id: "740" } },
      { param: { id: "730" } },
      { param: { id: "729" } },
    ],
    // true로 변경시
    // 최초 접속시 props가 빈 상태면 이후에 백그라운드에서 정적으로 html 생성
    // 두번째 접속 시 정적생성된 페이지 사용
    // fallback: true,
    fallback: false,
  };
}

export async function getStaticProps(context) {
  // context는 params나 요청 응답 쿼리 등이 담겨서 온다
  const id = context.params.id;
  const apiUrl = `http://makeup-api.herokuapp.com/api/v1/products/${id}.json`;
  const res = await Axios.get(apiUrl);
  const data = res.data;

  return {
    props: {
      item: data,
      name: process.env.name,
    },
  };
}

 

아래 세개의 상품상세보기는 정적생성으로 빌드시 만들어진 html 파일을 보여줍니다.

만들어진 파일을 보여주니까 클릭시 체감상 속도가 매우 빠릅니다.

물론 위 세개 상품말고 다른 상품 클릭시 404 페이지를 보여주겠죠..? ^^

상세페이지와 빌드 시 만들어진 정적 페이지

 

getStaticPaths의  fallback

이 옵션을 true로 바꿔주면 미리 정적 생성한 상세 페이지 외에 다른 게시물을 클릭 시

흰 화면이 잠시 보여졌다가 상세페이지를 보여준다.

 

이는 nextjs가 클릭한 상품페이지를 정적페이지로 직접 생성해 주는 것으로

최초 클릭 시 생성을 한 번하고 다음 부턴 만들어진 페이지를 보여준다는 옵션입니다.

 

페이지가 많다면 쓸 수 있는 방법입니다.!

'React' 카테고리의 다른 글

리액트 성능 측정 & 개선하기 (feat. memo & React DevTools)  (0) 2024.04.20
useMemo와 useCallback  (0) 2022.03.22
next.js의 SSR  (0) 2022.03.01
Next.js의 장점과 프로젝트 구조  (0) 2022.03.01
async, await  (0) 2021.05.20
Comments