• Next

[Next.JS] Next 기초 개념 Pre-rendering (CSR/SSR)

man_on 2022. 2. 26. 15:15
반응형

2022.02.15 - [REACT] - [Next.JS] Dynamic Routes

 

[Next.JS] Dynamic Routes

Next.js Next.js = React framework - Production을 위한 framework - A fullstack framework for ReactJS - NextJS solves common problems and makes building React apps easier. - React 성능을 향상시켜서 대..

manon-kim.tistory.com

https://nextjs.org/

 

Next.js by Vercel - The React Framework

Production grade React applications that scale. The world’s leading companies use Next.js by Vercel to build static and dynamic websites and web applications.

nextjs.org

 

     


     

     

     

     

    SPA / CSR / SSR

     

     

     

    [Website]

      - Static Website : 정적인 웹사이트, 서버에 저장된 html 파일 그대로 브라우저에 보이는 것

      - Dynamic Website : 동적으로 html 파일이 만들어 지는 것

     

     

    🔻 SPA ( Single Page Application )

       - 하나의 파일로 전체 사이트 ( = 여러 페이지)를 구현 ( html 파일이 한개 )

     

       - HTML 태그 자체를 자바스크립트가 동적으로 생성하는데

         동적생성 만들어지는 곳이 client side 라면 CSR / sever side 라면 SSR

     

       - CRA ( Create React App ) - Only CSR

          : 별도의 초기 설정 없이도 CRA를 통해 React 기반의 SPA 를 구현할 수 있게 되었다.

            하지만, CRA로 build한 프로젝트는 CSR로 실행되어 검색 노출이 잘 되지않았다.

     

     

     

     

    🔻 CSR ( Client Side Rendering )

         - 웹 페이지의 렌더링이 클라이언트 = 브라우저 측에서 일어나는 것을 의미한다.

            브라우저는 최초 요청에서 html, js, css 확장자 파일을 차례로 다운로드하는데

            최초로 불러온 html파일은 비어있게 된다.

            그 후, 빈 html 파일에 js파일이 다운로드가 완료되면 dom을 빈 html위에 그리시 시작한다.

     

            장점 : 웹서버 호출을 최소화 할 수 있다.

                 최초 호출 때만 html, js, css를 요청하고, 이후에는 화면에서 변화가 일어나는 만큼의 데이터만 요청한다. (AJAX/JSON)

                 라우팅(새로운 페이지로 이동)하더라도 html 자체가 바뀌는 것이 아니라 JS차원에서 새로운 화면을 그려내는 것이다.

     

     

     

     

     

    🔻 SSR ( Server Side Rendering )

       - 서버에서 첫 페이지의 렌더링을 처리해주는 방식이다.

     

       - 장점 : CSR과 비교해서

         1. SEO(Search Engine Optimization) 측면에서 유리하다. 

             CSR의 단점인 첫 페이지 깡통 사태를 극복할 수 있다.

         2. UX측면에서 유리하다.

             CSR에 비해 페이지 구성속도는 늦지만, 전체적으로 보여지는 콘텐츠 구성완료 시점은 빠르다.

            (but 페이지를 잘못 구성할 경우 CSR에 비해 부하가 커지거나, 첫 로딩이 느려질 수 있다.)

     

        - SSR의 구조

           : node.js로 구성된 (서버사이드 렌더링 해주는) FE서버

           : python, django로 되어있는 (데이터 주고받는) BE서버

     

        - SSR의 진행과정

     

     

     

     

     

    CSR + SSR = Next.js

     

     

     

     

     


     

     

     

     

     

     

     

    Pre-rendering

     

     

     

     

    기본적으로 Next.js는 모든 페이지를 pre-render한다.

    이는 next.js가 client-side javascript로 모든 작업을 수행하는 대신 미리 각 페이지에 대해서 html을 만들어 두는 것을 의미한다.

    pre-rendering은 SEO에서 더 나은 퍼포먼스를 보여줄 수 있다.

     

     

    이렇게 만들어진 html은 페이지가 브라우저에 로드될 때,

    해당 자바스크립트 코드가 작동하고 완전한 interactive page가 되도록 만드는데 이를 Hydration이라고 한다.

     

     

     

     

     

     

    Pre-rendering   VS  No Pre-rendering

     

     

     

     

     

     

    ✔️  Two Forms of Pre-rendering

     

        Next.js의 pre-rendering에는 두가지 종류가 있다.

        이 둘의 차이는 언제 페이지를 위한 html을 만드는지에 있다.

     

    •   Server-side Rendering : html을 각 request가 일어날 때 생성한다.
    •   Static Generation : html을 build타임에 생성한다. 생성된 html은 각 request에 재사용된다.

     

        가능한 static generation을 추천한다고 공식 next.js 홈페이지에 나와있다.

        이유는, 페이지가 한번에 build될 수 있고, 각 요청에 따라 페이지를 렌더하는 속도가 빨라지기 때문이다.

      

        유저의 요청보다 먼저 페이지가 렌더링되는 것이 좋지않은 경우

        ( 자주 데이터를 업데이트, 매 요청마다 콘텐츠가 달라지는 경우)

        이러한 경우에는 SSR을 사용하는 것이 좋다. 렌더시간은 좀 더 걸리겠지만, 페이지는 항상 업데이트 될 것이다.

     

     

     

     

     

     

     

    Per-page Basis

    next.js에서는 각 페이지에 어떤 종류의 pre-rendering을 할지 선택할 수 있다.

     

     

     

     

     

     

     


     

     

     

     

     

     

    getStaticProps

     

     

     

    Static-Generation

     

    export async function getStaticProps() {
      // fetch data from an API
      return {
        //props 프로퍼티를 설정하고 page component함수에 넘겨준다.
        props: {      
          meetups: DATA,
        },
        //페이지 주기적으로 업데이트 할 시간
        revalidate: 1,
      };
    }
    // props로 받아준다.
    export default function HomePage(props) {
      return <MeetupList meetups={props.meetups} />;
    }

     

     

     

    데이터를 props에서 받기때문에, state 관리나 useEffect는 필요없어진다.

    //기존
    export default function HomePage( ) {
      const [state, setState] = useState([]);
      
      useEffect(()=> {
        setState(DATA);
      },[]);
      
      return <MeetupList meetups={DATA} />;
    }

     

     

     

    • Next.js가 getStaticProps를 발견하면, pre-rendering 과정동안 이 함수를 실행하게 된다.
    • 페이지를 위해 props를 준비시킨다. 따라서 이 props들은 페이지가 필요로 하는 데이터를 포함한다.
    • getStaticProps는 비동기를 허용하며, promise를 return 한다.
    •  Next.js는 promise가 해결되길 기다린다. (데이터가 로드될 때까지)
    • 그리고 component 함수에 props를 return하면 data를 로드할 수 있다. (component 함수가 실행되기 전에)
    • getStaticprops의 코드는 build과정에서만 실행된다. (client X)

     

     

     

     

    getStaticProps 적용 전 ( 비어있는 리스트 존재 )
    getStaticProps 적용 후 (pre-rendering)

     

     

     

     

     

    When should I use getStaticProps?

     

    • The data required to render the page is available at build time ahead of a user’s request
    • The data comes from a headless CMS
    • The data can be publicly cached (not user-specific)
    • The page must be pre-rendered (for SEO) and be very fast — getStaticProps generates HTML and JSON files, both of which can be cached by a CDN for performance

     

     

    When does getStaticProps run

    getStaticProps always runs on the server and never on the client. You can validate code written inside getStaticProps is removed from the client-side bundle with this tool.

    • getStaticProps always runs during next build
    • getStaticProps runs in the background when using revalidate
    • getStaticProps runs on-demand in the background when using unstable_revalidate

    When combined with Incremental Static Regeneration, getStaticProps will run in the background while the stale page is being revalidated, and the fresh page served to the browser.

    getStaticProps does not have access to the incoming request (such as query parameters or HTTP headers) as it generates static HTML. If you need access to the request for your page, consider using Middleware in addition to getStaticProps.

     

     

     

     

     

    ✔️  npm run build

       : 배열하기 전에 실행하는 빌드 명령어

     

     

     

     

     

    ✔️  dynamic routes에서 next.js가 동적 페이지의 모든 버전의 pre-generated가 필요하다. (지원되는 모든 ID에서)

          동적이기 때문에 next.js는 어떤 id value가 pre-generated되는 지 알아야하는데

          이 때 getStaticPaths를 사용한다.

          (useRouter는 component함수에서만 쓸 수 있다.)

     

    getStaticProps에서 ID value 얻고싶을 때 context.params사용
    terminal에서만 콘솔이 찍힌다.(브라우저랑 개발자도구에서는 볼수없음) build타임에 돌아가는 거니까

     

     

     

     

     

     

     


     

     

     

     

     

     

     

    getServerSideProps

     

     

     

     

    Server-Side Rendering

     

     

    • getServerSideProps에 넣어주는 코드는 오직 server에서만 실행된다.
    • server side rendering시 NextJS가 백엔드에서 받아온 props를 return해서 reactJS로 넘겨준다.
    • server에서 받은 props로 프론트 페이지를 완성한다. (hydration)
    • api 처리가 완료되면, 전체화면이 한번에 생성된다. (그 전까지는 흰 텅빈화면, 로딩페이지X )
    • SEO측면에서 좋다.

     

    // page가 유저에게 보여지기 전에 props를 받아오는 function
    export async function getServerSideProps(context) {
      //fetch data from an API
      return {
        props: {},   // will be passed to the page component as props
      };
    }

     

     

     

     

     

    When does getServerSideProps run

    getServerSideProps only runs on server-side and never runs on the browser.

    If a page uses getServerSideProps, then:

    • When you request this page directly, getServerSideProps runs at request time, and this page will be pre-rendered with the returned props
    • When you request this page on client-side page transitions through next/link or next/router, Next.js sends an API request to the server, which runs getServerSideProps

     

     

     

    How to fetch data

    function Page({ data }) {
      // Render data...
    }
    
    // This gets called on every request
    export async function getServerSideProps() {
      // Fetch data from external API
      const res = await fetch(`https://.../data`)
      const data = await res.json()
    
      // Pass data to the page via props
      return { props: { data } }
    }
    
    export default Page

     

     

     

     

     

     

    serverSide의 흐름예시

     

    1. 사이트접속 시 app.js의 <Component>에 Home page가 호출된다.

    export default function _app({ Component, pageProps }) {
      return (
        <Layout>
          <Component {...pageProps} />
         /* <Home {...pageProps}/> */
        </Layout>
      );
    }

     

     

    2. Home.js의 getServerSideProps가 호출되고 fetch가 실행되어 props가 return 된다.

        props값은 상위의 _app의 pageProps로 전달되어 Home의 props로 들어온다. ({results})

    /* 3. props로 serverside에서 return한 값이 들어온다 */
    export default function Home({ results }) {
      return (
         ...
      );
    }
    
    /* 1. getSeverSideProps 실행 */
    export async function getServerSideProps() {
      const { results } = await (await fetch(`/api/movies`)).json();
      return {
        props: {
          results,
        },
      };
    }
    export default function _app({ Component, pageProps }) {
      return (
        <Layout>
          <Component {...pageProps} />
         /* 2. <Home {results}/> */
        </Layout>
      );
    }

     

     

     

     

     

     

     


     

     

     

     

     

     

     

    getStaticPaths

     

     

     

    Dynamic Routes에서는 getStaticProps와 getStaticPaths를 함께 사용해야 한다.

    동적이기 때문에 어떤 ID value가 pre-generated page가 되어야 하는지 알아야하기 때문이다.

     

     

    export async function getStaticPaths() {
      return {
        fallback: false,  //false이므로 m1, m2 입력시만 가능, m3입력시 404페이지
        paths: [
          {
            params: {
              meetupId: "m1",
            },
          },
          {
            params: {
              meetupId: "m2",
            },
          }, //dynamic page당  객체 하나
        ],
      };
    }

     

    • getServerSideProps와 함께 사용할 수 없다.
    • pages 파일에서만 사용할 수 있다.
    • 독립적으로 export해야한다.
    • fallback : 모든 paths를 지정할지(true), 특정 paths만 지정할 지 설정(false)

     

     

     

    When should I use getStaticPaths?

    You should use getStaticPaths if you’re statically pre-rendering pages that use dynamic routes and:

    • The data comes from a headless CMS
    • The data comes from a database
    • The data comes from the filesystem
    • The data can be publicly cached (not user-specific)
    • The page must be pre-rendered (for SEO) and be very fast — getStaticProps generates HTML and JSON files, both of which can be cached by a CDN for performance

     

     

    When does getStaticPaths run

    getStaticPaths will only run during build in production, it will not be called during runtime. You can validate code written inside getStaticPaths is removed from the client-side bundle with this tool.

    • getStaticProps runs during next build for any paths returned during build
    • getStaticProps runs in the background when using fallback: true
    • getStaticProps is called before initial render when using fallback: blocking

     

     

     

     

    반응형