Next.js 렌더링 기법 소개 ( CSR, SSR , SSG, ISR )

김재한·2024년 3월 12일
1

Next 14

목록 보기
5/5
post-thumbnail

서론

라우팅 방식이 page Router 에서 app Router 로 전환되면서

렌더링 종류에 따라 구현하는 방법이 변경되어 정리해보고자 한다.

각 렌더링에 대한 자세한 설명보다는 변경점 위주로 작성할 것이다.

Next.js 렌더링 기법 😃

렌더링 종류에는 크게 CSR | SSR | SSG | ISR 4가지 종류가 있다.

page Router 에서는 getServerSideProps | getStaticProps | getStaticPaths 등의 함수를 사용해 이를 구현해 왔지만

app Router 에서는 기본이 되는 컴포넌트가 서버 컴포넌트 라는 점에 따라 데이터 Cache를 활용해 구현한다.

Pre-Rendering

시작하기에 앞서, 다른 게시물에서 많이 사용한 단어인 Pre-Rendering 에 대해 간단하게 짚고 넘어가보자 👨🏻‍🔬

그림에서 보는것과 같이 (프론트)서버에서 DOM 요소들을 빌드하여 HTML 문서로 사전에 렌더링 하는 것을 말한다.

Pre-Rendering 이 일어나는 시점에 따라 SSG | SSR 을 나눌 수 있다.

  • SSG : 빌드 시점에 이루어져 완성된 정적 파일을 생성한다.
  • SSR : 사용자의 요청(url 진입 등)이 있을 때마다 이루어진다.

SSG 의 경우에는 빌드 시점의 데이터들로 화면이 구성되어, 실제로 데이터가 변경되더라도 화면에 반영되지 않는다.

SSR 은 서버로부터 html 파일 을 전달받아 화면에 빠르게 보여주고 함께 다운로드한 JS 번들hydration 작업을 걸쳐 최종적으로 보여준다.

💡 Hydrate 란?
클라이언트가 서버에서 랜더링된 html 파일JS 번들을 다운로드 완료하면, html 파일에 JS 코드를 매칭 시키는 작업이다.
이 과정을 통해 이벤트가 매핑되고 스타일이 적용된다.

SSG 의 경우에는 빌드타임에 query가 없기 때문에 런타임에서 query에 대한 Hydrate 가 일어난다.

💡 SSG 테스트 환경
SSG 페이지를 확인하려면 npm run dev 가 아닌 npm run buildnpm run start 로 실행해야 한다.

Client-Side Rendering (CSR)

SEO (Search Engine Optimization, 검색 엔진 최적화) 가 필요없는 화면이나 데이터 업데이트가 빈번하게 일어나는 화면인 경우 CSR로 구성한다.

SSR 의 경우 데이터 업데이트가 자주 발생하게 되면 프론트 서버의 피로도가 높아질 수 있기 때문이다.

작동하는 방식은 위와 같으며

  • page Router 의 경우 평소대로 스크립트 영역에서 데이터를 호출하면 된다.

  • app Router 의 경우 컴포넌트를 client component 로 만들어주면 된다.

Server-Side Rendersing (SSR)

SEO (Search Engine Optimization, 검색 엔진 최적화) 가 적용되며 실시간 데이터가 반영된 화면을 볼 수 있다.

또한, Pre-RenderingHTML 파일 을 내려받기 때문에 CSR 보다 빠르게 화면이 생성되어 사용자 경험을 향상시킬 수 있다.

✅ 알아두기
사실, Server Component 라는 개념이 생기면서 app Router 에서 SSR 을 잘 사용하지 않는다. ( 주관적인 생각.. )

Pre-RenderingHTML 파일이 아닌 직렬화된 Stream을 내려줘
JS 번들이 포함되지 않아 용량이 적은 Server Component를 사용한다.

서버 컴포넌트 정리 글을 참고하면 좋을 것 같다.

작동하는 방식은 위와 같으며

  • page Router 의 경우 getServerSideProps() 함수를 사용한다.

    function SsrPage({ data }) {
     // 파라미터로 데이터를 받아 화면을 구성한다.
    
     return ...
    }
    
    export async function getServerSideProps() {
     // 가장 먼저 실행되어 데이터를 받아온다. ( 매 요청마다 실행된다.)
     const res = await fetch(`https://.../data`)
     const data = await res.json()
     
     // 받아온 데이터를 컴포넌트에 전달한다.
     return { props: { data } }
    }
    
    export default SsrPage
  • app Router 의 경우 Server Component 에서 데이터 Cache 옵션으로 구현한다.

    fetch('https://...', { cache: 'no-store' }

    데이터를 받아올 때 no-store 옵션을 주게되면 매 요청마다 서버에서 실시간 데이터를 받아온다.

Static-Site Rendering (SSG)

SSR 과 마찬가지로 SEO가 적용되며 빌드 시점의 최신 데이터를 가지고 정적 화면을 만들어 캐시에 저장한다.

Client 에서 요청이 있더라도 캐시된 정적 페이지를 제공해 실시간 데이터를 확인할 수 없지만, 가장 빠르게 화면을 사용자에게 노출시켜준다.

작동하는 방식은 위와 같으며

  • page Router 의 경우 getStaticProps() 함수를 사용한다.
function SsgPage({ data }) {
  // 파라미터로 데이터를 받아 화면을 구성한다.
  return (
    <ul>
      {data.map((item) => (
        <li>{item.title}</li>
      ))}
    </ul>
  )
}


export async function getStaticProps() {
  // build 시점에 가장 먼저 실행된다.
  const res = await fetch('https://.../posts')
  const posts = await res.json()

  // 받아온 데이터를 컴포넌트에 전달한다.
  return { props: {posts} }
}

export default SsgPage
  • app Router 의 경우 Server Component 에서 데이터 Cache 옵션으로 구현한다.
    fetch('https://...', { cache: 'force-cache' }
    fetch 에서 force-cachedefault option 이므로 생략이 가능하다.

Incremental-Static Regeneration) ISR

ISR 렌더링 방식은 SSG와 동일하지만 설정한 시간 단위로 데이터를 최신화 시킨다.

  • page Router 의 경우 getStaticProps() 함수와 revalidate 옵션을 사용한다.

    function IsrPage({ data }) {
     // 파라미터로 데이터를 받아 화면을 구성한다.
    
     return ...
    }
    
    export async function getStaticProps() {
     const res = await fetch('https://.../posts')
     const posts = await res.json()
    
     return {
       props: { posts },
       revalidate: 10, // 초 단위
     }
    }
    
    export default IsrPage
  • app Router 의 경우 Server Component 에서 데이터 revalidate 옵션으로 구현한다.

    fetch('https://...', { next: { revalidate: 10} })

    데이터를 받아올 때 next: { revalidate: 10} 옵션을 주게되면 설정한 시간 단위로 최신 데이터로 정적 페이지를 생성한다.

참고
@sj_dev_js
@minw0_o

0개의 댓글