ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Incremental Static Regenerate 렌더링 (feat: SSR,SSG,CSR)
    front-end/Next.js 2023. 7. 27. 12:08

    리액트나 Nextjs를 공부 하다보면 CSR , SSR , SSG 이렇게 3가지 렌더링 방식은 한번쯤은 들어봤을텐데요.

    ISR 렌더링 방식은 저에게 생소 했던거같아서 ISR 렌더링 방식을 알아보면서 , CSR , SSR , SSG 의 렌더링 방식도 직접 구현 해보면서 알아봤습니다.

     

    테스트 할 API 같은경우는 렌더링 방식의 차이를 명확히. 캐치하려면 데이터의 수정이 있어야 하므로 https://mockapi.io/projects 를 통해서 간단한 API를 구현하였습니다.

     

    우선 간단하게 위 4가지 렌더링 방식의 설명을 하자면,

    CSR

    일반적인 SPA 작동 방식이며 , 클라이언트 사이드 렌더링은 초기 페이지 로드 시에 빈 페이지를 받은 후, 클라이언트(브라우저)에서 JavaScript를 사용하여 동적으로 컨텐츠를 렌더링하는 방식입니다. 최초 로딩 시간이 오래 걸릴 수 있고 , seo가 좋지않습니다.

     

    SSR

    클라이언트에서 모든것을 처리하지않고 웹사이트에 접속하면 서버에서 필요한 데이터를 모두 가져와서 정적 HTML 파일을 만들게 되고 , 인터렉티브 한 JS파일은 나중에 보내게 되면서 hydrate 되는 방식 입니다. 서버에서 페이지를 렌더링 하기에 클라이언트 사이드렌더링에 비해 로딩속도 빠르고 , 빈 HTML이 아니기떄문에 SEO 최적화가 되어있습니다.

     

    SSG

    사이트의 내용이 자주 변경되지 않는 경우에 유용하며, 정적 사이트는 빠르게 로드되고 보안에도 좋은 특성을 가집니다.

    빌드시에 HTML 데이터를 담음 -> 미리 파일을 만듬 -> 접속하는 유저들에게 보여줌 이미 만들어진 페이지를 유저들에게 보여줌 (서버 부담이 적고 , 응답 속도 빠름 ) //블로그나 회사소개 페이지 같은 변화가 거의없는 static 페이지에 적합. 디비에 무언가 수정이 되고 변화가 생긴다면 빌드와 배포를 다시 해야함. 동적 컨텐츠를 보여줄떈 SSG 사용X

     

    ISR

    일반적인 정적 사이트 생성은 사이트의 모든 페이지를 미리 빌드하여 정적 파일로 저장하는 방식입니다. 이러한 정적 생성은 빠르고 안정적이지만, 컨텐츠가 자주 변하는 경우에는 문제가 발생할 수 있습니다. 예를 들어, 블로그 게시물이나 제품 목록이 자주 변경되는 경우에는 모든 페이지를 다시 빌드하여 배포하는 것이 번거로울 수 있습니다.  ISR은 기존 정적 사이트에 새로운 데이터를 동적으로 반영하는 방법을 제공합니다. 변화된 데이터나 콘텐츠가 있는 페이지들만을 업데이트하여 다시 빌드하는 것을 의미합니다. SSG의 장점은 살리면서 최신데이터를 반영하는 방법 이기도합니다.

    1.빌드 시점에 페이지 생성(SSG와 동일)

    2.일정 시간이 지난 후 페이지 새로 생성(최신 데이터로 업데이트)

     


     

    렌더링 예시 코드

    저는 아래 코드와 같이 Next.js 12로 예시 파일들을 하나씩 만들었습니다.

    CSR

    아래 코드는 리액트를 처음 접할때나 가장 무난한(?) 데이터 fetching 해오는 대표적인 방법이죠?
    useEffect dependency의 빈배열을 넣어줌으로서 ,  첫 렌더링시 비어있는 배열 data 에 fetch 해온 데이터를 생성 시킵니다.

    import React, { useEffect, useState } from 'react'
    
    export default function Csr() {
    
      const [data, setData] = useState([]);
    
      useEffect(() => {
        const getData = async () => {
          const res = await fetch('https://64c1be3bfa35860baea0c846.mockapi.io/api/v1/name');
          const json = await res.json();
          setData(json);
        }
        getData();
      }, [])
    
      return (
        <div style={{fontSize:'32px',width:'1200px',margin:'0 auto'}}>
          <h1>Client Side Rendering</h1>
          <ul>
            {data.map((item) => (
              <li key={item.key}>{item.name}</li>
            ))}
          </ul>
        </div>
      )
    }

     

    SSR

    getServerSideProps로 이용하여 user의 props로 전달한 값을 이용하여 서버사이드 렌더링을 합니다.

    import React from 'react'
    
    export default function Ssr({user}) {
      return (
        <div style={{ fontSize: '32px', width: '1200px', margin: '0 auto' }}>
          <h1>Server Side Rendering</h1>
          <ul>
            {user.map((item) => (
              <li key={item.key}>{item.name}</li>
            ))}
          </ul>
        </div>
      )
    }
    
    export async function getServerSideProps(){
      const res = await fetch('https://64c1be3bfa35860baea0c846.mockapi.io/api/v1/name');
      const user = await res.json();
    
      return{
        props:{
          user
        }
      }
    }

     

    SSG

    getStaticProps 이용하여 user의 props로 전달한 값을 이용하여 Static Site Generate 렌더링을 합니다.

    import React from 'react'
    
    export default function Ssg({user}) {
      return (
        <div style={{ fontSize: '32px', width: '1200px', margin: '0 auto' }}>
          <h1>Static Site Generate</h1>
          <ul>
            {user.map((item) => (
              <li key={item.key}>{item.name}</li>
            ))}
          </ul>
        </div>
      )
    }
    
    export async function getStaticProps(){
      const res = await fetch('https://64c1be3bfa35860baea0c846.mockapi.io/api/v1/name');
      const user = await res.json();
    
      return{
        props:{
          user
        }
      }
    }


    ISR

    SSG렌더링 방식과 거의 똑같지만 , getStaticProps의 revalidate로 통해 20초 후에 데이터를 다시 받아오는(Regenerate)한 ISR 렌더링을 합니다.

    import React from 'react'
    
    export default function Isr({user}) {
      return (
        <div style={{ fontSize: '32px', width: '1200px', margin: '0 auto' }}>
          <h1>Incremental Static Regenerate</h1>
          <ul>
            {user.map((item) => (
              <li key={item.key}>{item.name}</li>
            ))}
          </ul>
        </div>
      )
    }
    
    export async function getStaticProps(){
      const res = await fetch('https://64c1be3bfa35860baea0c846.mockapi.io/api/v1/name');
      const user = await res.json();
    
      return{
        props:{
          user
        },
        revalidate:20 // For ISR !
      }
    }

     


     

    npm run build 를 통해 빌드를 해보겠습니다.

    빌드를 해보면 아래와 같이 나올텐데요,

    𝜆 : 서버사이드 렌더링을 의미 / ssr 
    ◯ : 초기 props가 없는 static HTML , 클라이언트사이드 렌더링을 의미 /csr
    ● : SSG ,ISR을 의미 / ISR 쪽 빌드된 부분을 보면 (ISR: 20 seconds)를 볼 수 있는데 아까 revalidate의 선언 부분입니다.

     

     

    CSR , SSR , SSG ,ISR 순서로 렌더링 된 화면 

    npm run start로 확인해보면, 
    CSR은 새로고침 할시 데이터를 받아오기까지 깜빡임이 살짝 있죠? 이지가 로드되고 API를 호출 해서 그렇습니다. CSR은 제외하면 화면깜빡임 없이 모두 동일하게 렌더링 되고있습니다.

    이제 mock api에서 데이터를 지금 4개 보여주고있는데 총 8개로 추가 해보겠습니다.

     

    데이터가 바뀌고 나서의 화면 렌더링 방식

    CSR

    새로고침을 하면 , 화면 깜빡임이 있지만 추가된 데이터가 잘 불러와집니다.

     

    SSR

    SSR은 화면깜빡임 없이 리스트가 추가된걸 볼 수 있습니다.


    SSG

    SSG 는 새로고침을해도 static 한 파일은 반영하기 떄문에 리스트 데이터가 추가 되질 않습니다 . *빌드 배포전까지

     

    ISR


    ISR 또한 새로고침을 하면 당장은 추가된 최신 리스트가 없다가 , 코드에서 적용 시킨 revalidate: 20 을통해 20초 후 새로고침을 하면 추가된 데이터가 추가 된걸 볼 수있습니다.
    ( 20초 뒤 첫번째 호출은 이전 데이터의 페이저를 보여주고 , 이후 새로운 데이터가 적용된 페이지가 생성이 됩니다.)

     

     


    빌드된 파일 확인

    빌드된 파일을 확인하면 isr.html 과 isr.json만 빌드된 시간이 바뀐것을 볼 수 있습니다.

     

     

    총 4가지 렌더링 방식을 알아보았는데 , 어떤게 좋고 나쁘고를 따지기보다는 상황에 맞춰서 어떤 렌더링 방식이 최적화 일지 생각을 해본후

    렌더링을 어떤 방식을 할지 정하면 될것같습니다.

     

     

    Reference

    https://nextjs.org/docs/pages/building-your-application/data-fetching/incremental-static-regeneration
    https://www.youtube.com/watch?v=khcRPut9DMA 

     

    Data Fetching: Incremental Static Regeneration | Next.js

    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 ben

    nextjs.org

     

     

Designed by Tistory.