ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [toy blog service] Preview Mode 이해하기
    Web Dev/5. Projects 2021. 4. 13. 23:40
    728x90

    데이터를 fetching해올때 preview mode 라는 것이 있다. 오늘은 Static Generation(Incremental Static Regeneration)에서 preview mode를 통해 어떤 경우에 한해서만 build 타임이 아니라 request 타임에 파일을 생성하도록 해보았다. 

     

    Preview Mode가 필요했던 이유

    나는 블로그 서비스를 흉내내고 있기 때문에 글을 생성하거나, 수정했을때 사용자에게는 바로 즉각 반영된 글화면(글목록이 아니라)이 보이되, 다른 유저에게는 Incremental하게 보여주고 싶었다(Server Side Rendering까진 안해도 될것 같다고 판단했기 때문)

     

    하지만 문제는 Incremental Static Regeneration을 하자니 유저가 글을 작성/수정하고 첫번째 요청에서는 revalidate가 반영이 안되고, 그다음에 background에서 작업이 일어나기 때문에 내가원하는 결과를 얻을 수가 없었다. 그러다가 알게 된 것이 preview mode 이다. 

     

    Static Generation is useful when your pages fetch data from a headless CMS. However, it’s not ideal when you’re writing a draft on your headless CMS and want to preview the draft immediately on your page. You’d want Next.js to render these pages at request time instead of build time and fetch the draft content instead of the published content. You’d want Next.js to bypass Static Generation only for this specific case.

    Static Generation은 좋은데, 대신에 draft나 즉각적으로 사용자에게 보여주어야하는 경우에 다소 좀 부족한 면이 있다. 종종 Draft 등은 request time에 보여주고 싶은데(build time이 아니라), 어떤 특별한 경우에는 Static Generation을 건너뛸수 있도록 하는 기능이 preview mode 이다. 

     

     

    - 우선 preview api를 만들어야한다

    import type { NextApiRequest, NextApiResponse } from "next";
    import { openJsonFile } from "../../utils/common";
    
    // localhost:3000/api/preview?user=hayoung&id=1
    export default async function handler(
      req: NextApiRequest,
      res: NextApiResponse
    ) {
      const jsonData = await openJsonFile();
      const user = req.query.user as string;
      const id = +(req.query.id as string);
    
      const newOrUpdatedPost = jsonData.contents[user][id];
    
      if (!newOrUpdatedPost) {
        return res.status(401).json({ message: "Invalid user or id" });
      }
    
      res.setPreviewData(newOrUpdatedPost, { maxAge: 10 });
      res.redirect(`/${user}/${id}`);
    }
    

    preview

    위의 api는 preview 요청에 대해서 데이터를 읽고, previewMode로 설정해서 반환하는 api이다. 이때 res.redirect를 통해서 username/id 페이지로 리다이렉트 하고 있다. 

     

    Preview Mode는 쿠키로 설정이 되는데, 기본적으로 이 쿠키는 만료시간이 정해져있지 않고 브라우저가 종료될때까지 유효하다. 나는 처음 글을 수정하고 생성할때 정도까지만 preview Mode가 유지되면 되서 위에서 maxAge 옵션을 통해 10초 뒤에는 previewMode가 끝나도록 했다. 

     

    - 해당화면에서 getStaticProps를 수정하자

    If you request a page which has getStaticProps with the preview mode cookies set (via res.setPreviewData), then getStaticProps will be called at request time (instead of at build time).

    previewMode인 상태(setPreivewData 응답을 받은 뒤로, preview cookies가 설정이 되어있을때)로 getStaticProps가 있는 페이지를 request하면 getStaticProps는 request time에 호출이 된다. 

     

    그리고 props로 preview=false, 와 previewData로 setPreviewData로 설정한 값이 넘어온다. 

    export const getStaticProps: GetStaticProps = async ({
      params,
      preview,
      previewData,
    }) => {
      if (preview) {
        console.log("preview");
        return {
          props: {
            data: previewData,
          }, // will be passed to the page component as props
          // revalidate: 1,
        };
      }
    
      const jsonData = await openJsonFile();
      const username = params.username as string;
      const id = +(params.id as string);
      const data: PostType[] = jsonData.contents[username][id] || [];
    
      return {
        props: {
          data,
        }, // will be passed to the page component as props
        revalidate: 1,
      };
    };
    

    이를통해 previewMode일때는 api에서 처리해서 넘겨준값을 렌더링해주도록 했다! 이렇게 글을 수정하거나 생성한 경우에 대해서 업데이트 된 하면을 즉각적으로 보여줄 수 있도록 했다.

     

     

    이렇게 previewMode로 설정이 된 경우 다른 getStaticProps로 설정되는 페이지에서 다 previewMode가 동작한다. 

     

    후기

    백프로 완벽한 방법은 아니겠지만(보안적으로 원래는 신경을 더 써야한다!)previewMode의 성질을 파악할 수 있어서 좋았다. 그리고 즉각적으로 화면을 보여줄 수 있는 방법을 알게 되어서 기쁘다!

     

    댓글

Designed by Tistory.