✨ Next.js에서의 렌더링 방식 ⇒ CSR vs SSR vs SSG vs ISR

박민우·2023년 10월 10일
9

✨ Next.js 

목록 보기
4/4
post-thumbnail

지난 글에서 웹 애플리케이션의 페이지 구성 방식인 SPA, MPA와 이를 구현하는 렌더링 방식인 CSR, SSR에 대해서 알아보았다. 이번 글에서는 이러한 렌더링 방식을 Next.js에서 어떻게 구현하고 있는지, 이러한 렌더링 방식을 선택해서 사용하기 위해서는 어떤 작업을 해줘야 하는 지 자세히 알아보자.


📌 Next.js에서의 Pre-Rendering

Pre-Renderig이란?

일반적인 React를 사용한 웹 어플리케이션은 CSR 렌더링 방식을 사용하며, 이는 처음에 브라우저가 빈 HTML 파일을 받아 아무것도 보여주지 않다가, JavaScript가 다운로드 완료되 사용자의 기기에서 렌더링이 진행되어 한 번에 화면을 보여준다.

하지만 Next.js는 모든 페이지를 사용자에게 전해지기 전에 미리 렌더링 즉, Pre-Render 한다. 이는 Next.js가 모든 일을 클라이언트 측에서 모든 작업을 수행하는 것이 아니라, 각 페이지의 HTML을 미리 생성하는 것이다.

생성된 HTML은 해당 페이지에 필요한 최소한의 자바스크립트 코드와 연결된다. 그후 브라우저에 의해 페이지가 로드되면, 자바스크립트 코드가 실행되어 페이지와 유저가 상호작용할 수 있게 된다.

이러한 과정을 Hydration이라 한다.

Pre-rendering 과정

  • initial load ⇒ js 동작만 없는 HTML을 먼저 화면에 보여주는데, 아직 js 파일이 로드되기 전 이므로 <Link> 같은 컴포넌트는 동작하지 않는다.
  • hydration ⇒ initial load에서 HTML을 로드한 뒤 js 파일을 서버로부터 받아 HTML을 연결시키는 과정으로, 해당 과정에서 react 컴포넌트는 초기화되고 사용자와 상호작용할 준비를 마친다

하지만 일반적인 React 어플리케이션처럼 Pre-Rendering이 없다면 js 전체가 로드되어야 하기 때문에 최초 load에서 사용자에게 보여지지 않게 된다. 즉, 전체 페이지가 로드되기 전 사용자는 페이지를 볼 수 없다.


📌 SSG vs SSR

Next.js에서의 Pre-Rendering은 2가지 종류가 있다.

1) Static Generation (정적 생성)

2) Server-side Rendering (서버사이드 렌더링)

⇒ 둘의 차이는 웹 페이지를 위한 HTML을 언제 생성하느냐에 있다.

Static Generation

빌드 타임에 HTML을 생성하는 프리 렌더링 방법이다. 이렇게 프리 렌더링 된 HTML은 매 요청마다 재사용된다. next build 명령을 통해 웹 앱을 프로덕션 레벨로 빌드했을 경우, 이 시점에 HTML이 렌더링 되고, 각각의 클라이언트들이 요청할 때마다 이미 만들어진 해당 HTML이 재사용된다.

즉, Next.js에서의 SSG도 결국 서버에서 렌더링되므로 서버사이드 렌더링으로 볼 수 있다. 하지만 Next.js 안에서 렌더링된 파일을 생성하는 시점에 따라 렌더링 방식을 구분하기 위해 SSG와 SSR로 나눠서 부르는 것 같다.

Server-side Rendering

매 요청마다 HTML을 생성하는 프리 렌더링 방법이다. 그저 각각의 클라이언트들이 요청을 하는 시점에 매번 HTML을 생성한다. npm run dev 나 yarn dev를 통해 실행된 개발 환경에서는, 페이지들이 Static Generation을 사용하고 있더라도 모든 페이지들이 매 요청마다 프리렌더링 된다.


📌 Next.js에서의 렌더링 방식

next.js에서는 다음과 같이 총 4가지의 렌더링 방식을 제공한다.

  • CSR
  • SSR
  • SSG
  • ISR

Page Router에서의 렌더링 방식

Next.js 13 이전의 Page Router 방식에서는 다음 렌더링 방식들을 다음과 같은 방법으로 구현했다.

  • CSR : useEffect 사용
  • SSR : getServerSideProps api 사용
  • SSG : getStaticProps api 사용
  • ISR : getStaticProps + revalidate api 사용

Page Router 방식은 현재 별로 권장되지는 않는 방식이기 때문에 이 정도로만 간략하게 설명하고 넘어가겠다. 더 자세한 설명은 여기를 참고하면 좋을 것 같다.

✨ App Router에서의 렌더링 방식

App Router에서도 동일하게 SSR, SSG, CSR, ISR 총 4개의 렌더링 방식을 지원한다. 이를 각각 어떻게 사용할 수 있는지 알아보자.

SSR

  • JS 파일이 서버로 보내진다.
  • 유저가 브라우저에서 요청 시마다, 서버가 data를 받아와 html을 렌더링한다.
  • 렌더링 된 html 파일을 유저의 브라우저에 보내준다.
  • data를 받아올 때, fetch('https://...', { cache: 'no-store' } 옵션을 통해 이를 구현할 수 있다.

CSR

  • HTML 파일이 서버로 보내진다.
  • 유저의 요청이 있을 때, HTML 파일을 브라우저로 보내주고, 그 다음 client는 API server에 data를 요청한다.

    data 요청 중일 때, 브라우저는 loading-state가 될 것이다.

  • data가 다 받아지면, data를 화면에 업데이트 시켜준다.
  • jsx/tsx파일 상단에 'use client;'를 적어줌으로써 구현할 수 있다.

SSG

  • 유저의 요청 시에 data를 받아왔던 SSR과는 다르게, 빌드 타임 때 data를 받아온다.
  • HTML + JSON 파일이 빌드되고, 이 파일이 서버로 보내진다.
  • 유저가 페이지를 요청할 때마다, 빌드 때 만들어놓았던 HTML+JSON이 들어있는 완전한 페이지를 보내준다.
  • 기본적인 fetch 함수를 사용하면 구현이 가능하다.

    fetch 함수의 기본적인 옵션 값이 cache: force-cache 이기 때문에 아무런 옵션을 주지 않는다면 SSG 방식으로 동작한다.


ISR

  • 기본적으로는 SSG 처럼 동작하지만, 특정 시간이 지나면 data가 업데이트 되었는지 확인하고 만약 업데이트 되었다면 새로운 data를 가진 페이지를 생성해 이를 보내준다.
  • fetch('https://...', { next: { revalidate: 10} })옵션을 줌으로써 구현이 가능하다.

정리

각 렌더링 방식을 살펴보면,

  • 기본적인 HTML 파일은 모두 서버 측에서 생성이 되고,
  • data를 client 쪽에서 fetch 할지, server 쪽에서 fetch 할지에 따라 CSR / SSR, SSG, ISR 방식이 나뉘는 것 같다.

각 렌더링 방식을 어떻게 사용할 수 있는지만 정리해보면, 다음과 같이 요약할 수 잇다.

  • SSG : 기본 fetch 사용
  • ISR : fetch('https://...', { next: { revalidate: 10} })
  • SSR : fetch('https://...', { cache: 'no-store' }
  • CSR : jsx/tsx파일 상단에 'use client;'

📌 어떤 렌더링 방식이 좋을까 ?

Next.js에서는 다양한 렌더링 방식을 지원하는 것을 살펴보았는데, 그러면 언제 어떠한 렌더링 방식을 선택하는 것이 좋을까 ??

SSG 방식 사용을 권장

가능하면 SSG 렌더링 방식을 사용하는 것이 좋다고 한다.

⇒ 페이지가 한번에 빌드되고 CDN에 의해 서비스되는 것이 매 요청마다 서버가 페이지를 렌더링하게 만드는 것보다 훨씬 빠르기 때문이다.

Ex) Static Generation은 다음 예시들을 포함한 많은 상황들에서 사용할 수 있다.
=> 마케팅 페이지, 블로그 포스트, 이커머스 (쇼핑몰) 제품 목록, 도움이나 기록을 위한 페이지 등.

⇒ 따라서, 유저의 요청 이전에 페이지를 렌더링할 수 있는 상황이면, SSG를 사용하는 게 좋다.

유저의 요청 이전에 페이지를 렌더링 할 수 있는 상황

  • 불러오는 data가 없는 경우
  • 불러오는 data가 있고, 이 data가 build time에 불러와져도 괜찮은 경우

유저의 요청 이전에 페이지를 프리렌더링 할 수 없다면 SSR or CSR

하지만 만약 유저의 요청 이전에 페이지를 프리렌더링 할 수 없다면, SSG는 좋은 방법이 아니다.

⇒ 유저의 요청 전에 data를 불러오면 안되는 경우, 유저의 요청에 따라 불러올 data가 바뀌는 경우

=> 해당 페이지가 자주 업데이트되는 페이지를 보여주거나 매 요청마다 페이지의 컨텐츠가 바뀐다면 이런 경우는 SSR을 사용해야 한다.(프리 렌더링 된 페이지가 항상 최신 상태로 유지될 수 있음)

=> 아니면 자주 업데이트되는 데이터를 관리하기 위해 CSR을 사용할 수도 있다.


🙇🏻‍♂️ 참고

[Next.js] Pre-Rendering
Understanding Next.js Rendering Strategies — SSR, CSR, SSG & ISR
Nextjs data Fetching 이해하기 (CSR, SSR, SSG, ISR)

profile
꾸준히, 깊게

0개의 댓글