next.js getInitialProps (getStaticProps, getStaticPaths,getServerSideProps)

이명진·2022년 12월 27일
0

Next.js

목록 보기
3/6

왜 사용하는가

nextJS는 서버사이드 렌더링을 하는데 각 페이지마다 사전에 불러와야할 데이터가 있다.
react나 vue에서는 useEffect 나 created 를 이용하여 페이지에 접근하기 전에 데이터를 받아온다. next는 getInitialProps를 이용하여 fetching 작업을 진행한다.

사용 이점

  1. 속도가 빨라진다.
    서버는 fetcing작업만, 브라우저는 렌더링만 함으로 각자 연산을 나누어서 하기 때문에 속도가 빨라진다.
  2. 로직 파악이 쉬워진다.
    함수가 분리되기 때문에 로직 파악이 쉬워진다.

사용법

사용 하고 싶은 컴포넌트 외부에 getInitialProps 함수를 선언하여 사용한다.

import { useRouter } from "next/router";
import posts from "../posts.json";

const Posts = (props: { post: { title: string; content: string } }) => {
  const router = useRouter();

  return (
    <>
      <h1>{props.post.title}</h1>
      <h1>{props.post.content}</h1>
    </>
  );
};

Posts.getInitialProps = context => {

  return {
    post: posts[context.query.id]
  };
};

export default Posts;

getInitialProps 내부에는 context, component등 여러 객체들이 있다.
위의 예시는 query.id에 접근하여 담아주는 것을 하였다.

주의사항

하나의 페이지에서는 하나의 getInitialProps만 실행된다.

렌더링때 거치는 순서는 _app => page component이다.
만약 _app에 getInitialProps를 정의했다면, 하위 컴포넌트에서는 getInitialProps는가 실행되지 않는다.

하위 컴포넌트에서도 사용하려면 추가 작업이 필요하다.

// src/_app.tsx
import "./globals.css";

function MyApp({ Component, pageProps }) {
  return <Component ponent {...pageProps} />;
}

MyApp.getInitialProps = async ({ Component, ctx }) => {
  let pageProps = {};
  // 하위 컴포넌트에 getInitialProps가 있다면 추가 (각 개별 컴포넌트에서 사용할 값 추가)
  if (Component.getInitialProps) {
    pageProps = await Component.getInitialProps(ctx);
  }

  // _app에서 props 추가 (모든 컴포넌트에서 공통적으로 사용할 값 추가)
  pageProps = { ...pageProps, posttt: { title: 11111, content: 3333 } };

  return { pageProps };
};

export default MyApp;

브라우저 api는 실행하면 안된다.

서버에서 실행되기 때문에 브ㅏㄹ우저 api (setTimeout, window.xx ,document.xx)는 실행하면 안된다.

getStaticProps, getStaticPaths,getServerSideProps

Next v9 이상에서는 getInitialProps 대신 getStaticProps, getStaticPaths, getServerSideProps을 사용하도록 가이드 한다.

좀더 상세하게 함수들을 나눈것 같다.

getStaticProps

getStaticProps는 빌드 시 데이터를 패치하는 함수이다.

function BlogPost({ post }) {
  return (
    <div>
      <h1> {post.title} </h1>
      <div> {post.content} </div>
    </div>
  )
}

export async function getStaticProps() {
  const res = await fetch('https://.../posts/1')
  const post = await res.json()
  return {
    props: {
      post,
    }
  }
}

export default BlogPost

이런식으로 사용하는데 바로 함수를 생성하면서 사용하는 것 같다.
props로 post값을 내려주었고 blogPost 컴포넌트에서 post값을 받아서 사용했다.

getStaticPaths

데이터에 따라 pre-rendering할 페이지의 동적경로를 지정하는 함수이다.

export async function getStaticPaths() {
  return {
    paths: [
      { params: { ... } }
    ],
    fallback: ...
  };
}

이런 형태로 사용되는데 paths 값을 getStaticProps로 리턴해준다.

이전에 설명했던 것처럼 pages에 각각 동적 컴포넌트를 생성할수 있다.
동적 경로마다 패스를 지정해서 넘겨주는 것이다.

동적 컴포넌트에서 getStaticPaths, getStaticProps로 같이 쓰인다.

getStaticPaths 함수로 동적 컴포넌트 명으로 값을 내려주고
getStaticProps 에서 받은 값으로 props를 사용해주는 것이다.

Fallback

paths에서 리턴되지 않은 경로에 대해서 어떻게 처리할지 정하는 옵션이다.

  • false: 404를 전달한다.
  • True: 404를 전달하지 않고, "fallback" 버전의 페이지를 첫 request에서 보여준 후, 페이지가 생성되고 나면 그 이후의 request부터는 생성된 페이지를 보여주겠다.
  • blocking : 서버 사이드 렌더링을 통해 HTML이 생성되기 까지 기다리겠다.

function BlogPost({ post }) {
  return (
    <div>
      <h1> {post.title} </h1>
      <div> {post.content} </div>
    </div>
  )
}

export async function getStaticPaths() {
  const res = await fetch('http://.../posts')
  const posts = await res.json()
  
  const paths = posts.map((post) => ({
    params: { id: post.id },
  }))
  
  return { paths, fallback: false }

}

export async function getStaticProps({ params }) {
  const res = await fetch(`https://.../posts/${params.id}`)
  const post = await res.json()
  return {
    props: {
      post,
    }
  }
}

export default BlogPost

위의 예시처럼 getStaticPaths 에서 각 값들을 다 받은다음에 map함수로 params별로 나눠주었다 그리고 각 path에 맞는 데이터들을 getStaticProps를 통해서 뿌려주는 것이다.

getServerSideProps

이름만 봐도 알듯이 서버 사이드 렌더링을 위한 함수이다.
getStaticProps 처럼 컴포넌트에 props를 넘겨준다는 공통점이 있지만, 빌드 시가 아닌 매 request마다 실행된다는 차이점이 있다.

export async function getServerSideProps(context) {
  return {
    props: {},
  }
}

이렇게 사용하며 추가적으로 미들웨어인 ‘req’가 제공된다.

profile
프론트엔드 개발자 초보에서 고수까지!

0개의 댓글