ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Next.js] ISR(Incremental Static Regeneration) 적용기
    Next.js 2023. 1. 30. 22:16

    상황

    상황은 이랬다(이 글은 뒤늦은 회고이다.)

    22년 8월경 우리는 react.js로 운영중인 서비스를 next.js로 대대적인 마이그레이션 작업을 진행 후 배포했다.

    프론트팀이 모두 달라 붙어 약 2달 간의 리소스를 투입한 개발팀 입장에서 정말 중요하고 큰 프로젝트였다. (물론 중간에 다른 프로젝트와 병행했기에 시간이 더 소요된 측면이 있다).

     

    문제

    대망의 프로젝트 배포 날이 되었는데,

    아니 이게 무슨 일인가? 

    nextjs의 이점 중 더 빠른 렌더링 및 로드 속도도 분명 있었는데.... 상세페이지 진입 시 오히려 더 느려진 것이 아닌가? 

     

     

    고백하자면 개발 중에도 느림을 체감했으나 dev환경에서는 서버가 코드를 먼저 컴파일하기에 느리고 production 환경에서는 더 빨라진다는 안일한 생각도 있었다. 

    느려졌다는 것이 체감될 정도로 로드 속도가 느려졌기 때문에 빨리 수정하지 않으면 next 마이그레이션 이전으로 원복해야 할 위험에 쳐했다.

    원인

    next가 사용하는 SSR(sever-side-rendering)은 getServerSideProps함수를 사용해 서버사이드에서 데이터를 페치후 미리 페이지를 만들어(pre-rendering)하여 브라우저에 뿌려주는데,

    export const getServerSideProps = wrapper.getServerSideProps(store => async context => {
      const response = await store.dispatch(getProduct(context.query.productId));
      let metaTags = {};
      if (!response.error) {
        const { name, subtext, thumbnail } = response.payload.result;
    
        metaTags = {
          title: name,
          description: subtext,
          url: thumbnail,
        };
    
        return {
          props: {
            metaTags,
          },
        };
      } else {
        return {
          notFound: true,
        };
      }
    });

    우리 서비스와 같이 상세 페이지의 정보를 받는 api에 많은 정보가 담겨 있어 무거운 경우 더 시간이 소요되는 것 같다. 

    해결

    해결 방법을 찾던 중 next의 공식문서 에서 ISR(Incremental Static Regeneration)이라는 함수를 발견했는데, 정적으로 페이지들을 생성해서 성능상의 이점을 가져가면서 변화된 내용을 업데이트 할 수 있다고 하는 것이 아닌가?  오호!

     

     
    Next.js allows you to create or update static pages after you’ve built your site. Incremental Static Regeneration (ISR) enables you to use static-generation on a per-page basis, without needing to rebuild the entire site. With ISR, you can retain the benefits of static while scaling to millions of pages.
     

    공식 문서를 위와 같이 ISR를 설명한다. Next는 사이트를 빌드한 후에도 정적인 페이지를 생성 혹은 업데이트 할 수 있게 한다. 즉 ISR을 통해 다시 모든 파일을 빌드할 필요 없이 필요한 정적인 페이지만 빌드할 수 있다. 즉 이것은 정적페이지 생성의 장점은 취하되 단점을 보완하는 것이다. 

     

    해결내용

    export async function getStaticPaths() {
      const res = await API.get('/product');
      const products = res.result.rows;
      const paths = products
        .filter((product: any) => product.status === 'active' || product.status === 'sold_out')
        .map((product: any) => ({
          params: { productId: product.id.toString() },
        }));
      return { paths, fallback: 'blocking' };

    getStaticPaths 함수는 빌드시 동작하는 함수로 상세페이지와 같이 다이나믹 라우트(pages/1, page/2... page/1000)의 경우 

    정적으로 생성할 paths를 정의하는 역할을 한다. 

    이때 쇼핑몰에서는 활성화된 (active) 상품과 품절 상품(sold_out)만 페이지를 만들 것이므로 status가 active, sold_out로 필터를 걸어주고 리턴한다. 

     

    그리고 옵션 중에 fallback이 있는데, fallback: 'blocking'은 빌드 시 존재하지 않았던 path(새 상품)가 생길 시 SSR로 정보를 가져오는 설정이다.(false인 경우 404 페이지를 보여주고 'true'일 경우 재빌드 시킨다)

    export const getStaticProps = wrapper.getStaticProps(store => async context => {
      const response = await store.dispatch(getProduct(context.params?.productId));
      let metaTags = {};
      if (!response.error) {
        return {
          props: {
            metaTags,
          },
          revalidate: 30,
    // 요청이 들어온다면(트래픽 발생 시) 페이지를 재생성 시키는 빈도이다
        };
      } else {
        return {
          notFound: true,
        };
      }
    });

    getStaticPaths가 정정생성할 경로 id를 만들었다면, getStaticProps로 해당 경로들을 정적 생성을 시켜준다. 

    이 함수는 빌드 타임에 서버 사이드에서 한번 실행된다. 

     

    이때 revalidate 이라는 옵션이 있는데 이는 사용자가 진입한 이후 revalidate 타임 후에 해당 페이지에 대해 정적 생성을 진행한다. 

    즉 위와 같이 revalidate 타임을 30초로 설정 시 첫 유저가 진입 후 30초 동안은 어느 유저가 들어오더라도 미리 생성 해두었던 정적 페이지를 보여주고 30초 이후에 갱신된다는 의미이다.

    When a request is made to a page that was pre-rendered at build time, it will initially show the cached page.

    주의할 점은 30초마다 매번 페이지가 갱신(생성)되는 것이 아니라 요청이 들어 왔을때 (트래픽 발생) 페이지를 갱신한다는 것이다. 

     

    하지만 ISR로 급한 불을 껐지만 위 함수도 단점이 존재했는데... 이 내용은 다음 포스팅에 

     

    요약

    1.  next 마이그레이션 후 로드속도가 오히려 느려짐
    2.  해결책으로 ISR(정적 증분 생성) 함수의 존재를 알게됐고 적용해봄 
    3.  ISR을 이용하면 SSG와 같이 성능상의 이점을 챙기면서 SSR와 같이 변경된 내용에 대한 업데이트까지 두 마리의 토끼를 잡을 수 있다.
    4. 하지만 이 또한 단점이 존재한다. 

    댓글

Designed by Tistory.