ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [toy blog service] Intro Page와 Index 페이지를 통해서 살펴보는 Static Generation과 Incremental Static Regeneration차이
    Web Dev/5. Projects 2021. 4. 13. 12:52
    728x90

    - Intro page: Static 하게 고정될거라 Static Generation이 맞다고 판단

    - Index page: 최신글과 트렌딩을 보여줘야하는데, 그렇기 때문에 업데이트는 필요하지만 Incremenatl Static Regeneration으로도 충분할 것으로 판단(일정시간지나고 나서 regeneration 하도록)

     

     

     Static Generation

    nextjs.org/docs/basic-features/data-fetching#getstaticprops-static-generation

     

    Basic Features: Data Fetching | Next.js

    Next.js has 2 pre-rendering modes: Static Generation and Server-side rendering. Learn how they work here.

    nextjs.org

    가장 기본적인 Static Generation with Data Fetching은 DB든 파일이든 읽어서 Static하게 html 파일을 생성하는 것이다. 

    import Head from "next/head";
    import React from "react";
    import { GetStaticProps } from "next";
    import testDB from "../utils/testDB.json";
    import { IntroType } from "../utils/types";
    
    export const getStaticProps: GetStaticProps = async (context) => {
      const introData: IntroType[] = testDB["intro"];
    
      return {
        props: {
          introData,
        }, // will be passed to the page component as props
      };
    };
    
    interface Props {
      introData: IntroType[];
    }
    
    // Static Generation
    const Intro: React.FC<Props> = ({ introData }) => {
      console.log(introData);
      return (
        <div>
          <Head>
            <title>Introducting ToyBlog</title>
            <link rel="icon" href="/favicon.ico" />
          </Head>
          <h1>Introducting ToyBlog</h1>
          {introData.map((d, index) => {
            return (
              <div key={index}>
                <h2>{d.question}</h2>
                <h5>{d.answer}</h5>
              </div>
            );
          })}
        </div>
      );
    };
    
    export default Intro;
    

    위의 Intro 페이지는 Intro 관련 데이터를 가져와서 빌드하고나면 변경사항이 없는 것을 가정한 페이지이다. Next.js에서는 이런 경우 GetStaticProps를 통해서 데이터를 가져와서 build time때 화면을 생성할 수 있다. 

     

    실제 화면

    이렇게 생성된 페이지는 Static하기 때문에 변경사항이 반영되기 위해서는 Rebuild해야한다. 

     

     

     

    가짜 Trending 페이지 만들어보기(Incremenatl Static Regeneration)

    Trending페이지 같은 것이 실제로 구현이 어떻게 되는지는 아직 잘 몰라서 이번에는 아주 간단하게 JSON 객체를 가지고, 해당 글이 얼마나 조회되었는지 파일입출력으로 아주 간단하게(이렇게 실제로 절대 안할거란걸 안다!) 흉내를 한번 내보고자 한다. 

     

    Incremeantal Static Regeneration이란 Static Build와 Server Side Rendering의 장점을 오묘하게 결합한 형태이다. 

     

    위의 Intro 페이지같은 경우 Dynamic Contents가 아니라 거의 변동되지 않는데, 경우에 따라 종종은 업데이트가 되어야하는 경우가 있다. 그래서 Next.js는 사용자의 요청이 들어왔을때는 stale version, 즉 기존에 이미 있는 html을 제공하고(static generation처럼), background에서 일정 조건에 따라 페이지를 새로 생성한다. 그리고 이 background page regeneration이 완료되고난 후 사용자의 요청에 이 새로운 페이지를 제공한다. 그리고 이 페이지는 이제 Stale한 버전이 되는 것이다. 

     

    사용은 getStaticProps를 사용하되, revalidate 옵션을 사용한다. 

     

    나는 Index페이지에서 각 포스트의 viewCount를 기준으로 정렬을 해서 보여주고자 한다(효율은 전혀 고려하지 않았으니, 이 포스트를 보는 사람들은 절대로 무언가를 이렇게 구현하면 안된다는 것을 명심 또 명심해야한다고 말씀드립니다)

     

    "contents": {
        "hayoung": [
          {
            "id": 0,
            "title": "hayoung-1",
            "contents": "something something Contents",
            "viewCount": 1
          },
          {
            "id": 1,
            "title": "hayoung-1",
            "contents": "something something Contents",
            "viewCount": 2
          },
          {
            "id": 2,
            "title": "hayoung-1",
            "contents": "something something Contents",
            "viewCount": 2
          }
        ],
        "jiyeon": [
          {
            "id": 0,
            "title": "jiyeon-1",
            "contents": "something something Contents",
            "viewCount": 5
          },
          {
            "id": 1,
            "title": "jiyeon-1",
            "contents": "something something Contents",
            "viewCount": 1
          },
          {
            "id": 2,
            "title": "jiyeon-1",
            "contents": "something something Contents",
            "viewCount": 2
          }
        ]
      },

     

    이런식의 Data가 있다고 하자. Index 페이지는 기본적으로는 Static하게 빌드 할것이다(사용자의 요청마다 새로 정렬해서 보여주려면 오버헤드가 만만치 않을 것이라고 생각했고, 초단위로 trending 페이지를 바꿔서 보여줘야할 것 같지않다고 판단했기 때문이다)

     

    효율은 없지만 getStaicProps에서 데이터를 읽어와서 정렬을 하고 revalidate 옵션을 통해서 incremental static regeneration이 될수있도록 하고 있다. 

    import Head from "next/head";
    import React from "react";
    import CardViewer from "../components/CardViewer";
    import { PostType, ContentsType } from "../utils/types";
    import { GetStaticProps } from "next";
    
    const getOnlyContentsAndSort = (data: ContentsType): PostType[] => {
      let result: PostType[] = [];
    
      // console.log(Object.entries(data));
      for (const [author, post] of Object.entries(data)) {
        // console.log(author, post);
        result = [...result, ...post];
      }
    
      result.sort(function (a: PostType, b: PostType) {
        return -(a.viewCount - b.viewCount); // 내림차순
      });
    
      return result;
    };
    
    // Incremental Static Regeneration
    export const getStaticProps: GetStaticProps = async (context) => {
      const fs = require("fs").promises; // 파일 입출력 처리
      const jsonFile = await fs.readFile("./utils/testDB.json");
      const jsonData = JSON.parse(jsonFile);
    
      console.log(jsonData);
    
      const data: PostType[] = getOnlyContentsAndSort(jsonData["contents"]);
    
      return {
        props: {
          data,
        }, // will be passed to the page component as props
        revalidate: 1,
      };
    };
    
    interface Props {
      data: PostType[];
    }
    
    const Home: React.FC<Props> = ({ data }) => {
      return (
        <div>
          <Head>
            <title>ToyBlog Home</title>
            <link rel="icon" href="/favicon.ico" />
          </Head>
          <h1>Blog Main - trending, latest</h1>
          <CardViewer data={data} />
        </div>
      );
    };
    
    export default Home;
    

     

    이때파일을 testDB를 그냥 import안하고 fs 모듈로 읽어온 이유는 import하면 그냥 번들링 되어버리기 때문. 

     

    아래는 next build 후 next start했을때 보이는 화면이다. 상세하게 각페이지가 어떻게 빌드되어있는지를 보여주는데 가장위에 ISR이부분이 index.js가 Incremental Static Regeneration이 되었다고 보여주고 있다. 그리고 1초마다 regeneration이 되었다고 보여준다

     

     

    실제 화면은 아래와 같다. 초기화면에서 내가 Json 파일 내용을 변경하고 요청을 하면 그때는 기존의 파일 내용을 보여주고, background에서 새로운 페이지를 생성하고, 다시한번 요청을 하면 새로운 페이지 생성이 완료된 경우 업데이트 된 내용을 보여준다. 이를 통해 Static build처럼 빠른 응답을 할 수 있으면서도 컨텐츠 업데이트에도 대응할 수 있는 것이다. 

     

     

     

    후기

    Static Generation과 Incremental Static Regeneration에 대해서 배울수 있는 시간이었고, 특히 fs 모듈을 통해서 data에 접근할 수 있도록 구성해보았다. 

    댓글

Designed by Tistory.