240926 Next.js - 주요 랜더링 패턴

신한별·2024년 9월 26일

💪 매일 기록

목록 보기
75/97
post-thumbnail


기존

전통적인 프론트엔드 배포 방법 방법, MPA

  1. 전통적인 서버 사이드 랜더링 방식인 MPA로부터 프론트엔드 웹 개발이 시작되었습니다.
/about → about.html
/profile → profile.html
  1. 페이지 이동 시 및 랜더링 시 깜빡거리는 현상이 있고 컨텐츠의 양에 따라서 페이지별 편차가 심해지게 됩니다. 결국에는 UX가 저하됩니다.
  2. 이러한 문제 때문에 React, Angular, Vue 등 SPA ((Single Page Application))이 등장합니다.

획기적 방법, SPA (Single Page Application)

  1. 브라우저에서 동작하는 Javascript를 이용해 동적으로 페이지, 컴포넌트 등을 랜더링 하는 방식
  2. 'Client의 사이드에서 랜더링을 한다'라는 개념은 기존 프론트엔드 개발자들에게 획기적 방법으로 소개
  • 최초 서버로부터는 텅 빈, root라는 id를 가진 div만 다운로드 ⇒ javascript Bundle 을 통해 UI가 완성
  • 더 이상 새로고침이나 깜빡거림 없이 웹서비스 이용이 가능하여 UX가 크게 향상
  • 그러나 다음과 같은 단점이 새롭게 대두됨
    • 늦는 초기 로딩 속도
      1. 텅 빈 div만 불러오기 때문에 Javascript의 평가, 실행이 될 때까지 하얀 화면이 유저에게 노출됨
      2. 이를 보완하기 위해 Code Spilitting(Lazy-Loading) 방법 제시
      3. 하나로 번들된 코드를 여러 코드로 나눠 당장 필요한 코드가 아니면 나중에 불러옴
      4. 그러나 태생적으로 완벽하게 해결되지는 못함

4가지 주요 랜더링 기법

CSR(Client Side Rendering)

특징

  • 순수 React 사용했을 때 100%
  • 브라우저에서 JavaScript를 이용해 동적으로 페이지를 랜더링하는 방식
  • 랜더링 주체 : 클라이언트

장점

  • (최초 한번 로드가 끝나면) 사용자와의 상호작용이 빠르고 부드러움
  • 서버에게 추가적인 요청을 보낼 필요가 없기 때문에, 사용자 경험이 좋다.
  • 서버 부하가 적음

단점

  • 첫 페이지 로딩 시간(Time To View)이 길 수 있습니다.
  • JavaScript가 로딩 되고 실행될 때까지 페이지가 비어있어 검색 엔진 최적화(SEO)에 불리.

코드

import React from 'react';
import ReactDOM from 'react-dom';

function App() {
  return <h1>Hello, Client Side Rendering!</h1>;
}

// index.js
ReactDOM.render(<App />, document.getElementById('root'));

SSG(Static Site Generation)

특징

  • 서버에서 페이지를 렌더링 하여 클라이언트에게 HTML을 전달하는 방식.
  • 최초 빌드 시에만 생성이 됨
  • 사전에 미리 정적 페이지를 여러 개 만들어놓음 → 클라이언트가 홈페이지 요청을 하면, 서버에서는 이미 만들어져있는 사이트를 바로 제공! → 클라이언트는 표기만 함

장점

  • 첫 페이지 로딩 시간이 매우 짧아(TTV) 사용자가 빠르게 페이지를 볼 수 있다. 또한, 검색 엔진 최적화(SEO)에 유리.
  • CDN(Content Delivery Network) 캐싱 가능

단점

  • 정적인 데이터에만 사용할 수 있음
  • 사용자와의 상호작용이 서버와의 통신에 의존하므로, 클라이언트 사이드 렌더링보다 상호작용이 느릴 수 있습니다. 또한, 서버 부하가 클 수 있습니다.
    • 마이페이지 처럼 데이터에 의존하여 화면을 그려주는 경우 사용 불가

코드(next.js 12 버전)

// app router 버전은 본 예제에서 다룹니다.
// 아래 예제는 편하게 훑어보세요 :)
import React from 'react';

function HomePage({ data }) {
  return <div>{data}</div>;
}

export async function getStaticProps() {
  const res = await fetch('https://...'); // 외부 API 호출
  const data = await res.json();

  return { props: { data } };
}

export default HomePage;

ISR(Incremental Static Regeneration)

특징

  • SSG처럼 정적 페이지를 제공
  • 설정한 주기만큼 페이지를 계속 생성해 줌
    • ex : 주기가 10분이라면? → 10분마다 데이터베이스 또는 외부 영향 때문에 변경된 사항을 반영하는 역할
  • 정적 페이지를 먼저 보여주고, 필요에 따라 서버에서 페이지를 재생성하는 방식.

장점

  • 정적 페이지를 먼저 제공하므로 사용자 경험이 좋으며, 콘텐츠가 변경되었을 때 서버에서 페이지를 재생성하므로 최신 상태를 (그나마) 유지
  • CDN 캐싱 가능

단점

  • 동적인 콘텐츠를 다루기에 한계가 있을 수 있다. ( 실시간 페이지 아님 )
  • 마이페이지 처럼 데이터에 의존하여 화면을 그려주는 경우 사용 불가

코드

import React from 'react';

function HomePage({ data }) {
  return <div>{data}</div>;
}

export async function getStaticProps() {
  const res = await fetch('https://...'); // 외부 API 호출
  const data = await res.json();

  return { 
    props: { data },
    revalidate: 60, // 1초 후에 페이지 재생성
  };
}

export default HomePage;

SSR(Server Side Rendering)

특징

  • SSG, ISR처럼 렌더링 주체가 서버!
  • 클라이언트의 요청 시 렌더링
    • C → S : 이 페이지 줘!
    • S → C : (데이터베이스 읽고 등등 한 후) html 파일을 제공

장점

  • 빠른 로딩 속도(TTV)와 높은 보안성을 제공.
  • SEO 최적화 좋음
  • 실시간 데이터를 사용
  • 마이페이지 처럼 데이터에 의존한 페이지 구성 가능
  • CDN 캐싱 불가

단점

  • 사이트의 콘텐츠가 변경되면 전체 사이트를 다시 빌드해야 하는데, 이 과정이 시간이 오래 걸릴 수 있다. → 서버 과부하
  • 요청할 때 마다 페이지를 만들어야 함

코드

import React from 'react';

function HomePage({ data }) {
  return <div>{data}</div>;
}

export async function getServerSideProps() {
  const res = await fetch('https://...'); // 외부 API 호출
  const data = await res.json();

  return { props: { data } };
}

export default HomePage;

4가지 주요 렌더링 기법 비교

분류CSRSSRSSGISR
빌드시간짧다짧다길다길다
SEO나쁨좋음좋음좋음
페이지 요청에 따른 응답 시간보통길다짧다짧다
최신 정보인가?맞음맞음아님아닐 수 있음

중요 개념

🎉 TTV, TTI 그리고 Hydration
우리가 Next.js를 이해할 때는 위의 세가지 개념이 중요하다.
이 개념을 아는지 모르는 지에 따라서 렌더링 패턴을 이해하고 쓸 수 있느냐가 결정되기 때문.

1. TTV (Time to View)

  • 페이지가 브라우저에 렌더링되어 사용자가 볼 수 있는 시점까지 걸리는 시간을 의미.
    TTV는 성능 최적화와 사용자 경험 개선에 중요한 요소로, 페이지가 얼마나 빨리 사용자에게 표시되는지를 측정하는 데 사용.
  • 어떤 렌더링 방식을 사용하느냐에 따라 TTV가 달라질 수 있다. (SSR/SSG/CSR 등)

2. TTI (Time to Interactive)

  • 웹 페이지가 사용자와 완전히 상호작용할 수 있는 상태가 될 때까지 걸리는 시간을 의미.
    페이지가 로딩되고 나서 사용자 입력에 즉각 반응할 수 있는 시점까지의 시간을 측정하는 중요한 성능 지표.
    TTI가 빠르면 사용자는 페이지가 빨리 반응한다고 느끼며, TTI가 느리면 페이지가 렌더링된 후에도 반응이 지연되는 것처럼 느껴진다.

  • TTI 최적화 방법

    1. 코드 스플리팅: Next.js는 기본적으로 코드 스플리팅을 지원한다.
      이를 통해 처음 로드되는 자바스크립트 크기를 줄이고, 중요한 기능부터 빠르게 로드할 수 있습니다.
    2. Lazy Loading: 필요한 부분만 미리 로드하고, 나머지는 사용자 요청이 있을 때 로드하여 초기 로딩 속도를 개선.
    3. 리소스 최적화: 이미지 압축, 폰트 최적화, CSS/JS 파일의 크기 줄이기 등의 방법으로 리소스 로딩 속도를 개선할 수 있다.
    4. 서비스 워커와 캐싱: 캐싱을 통해 자주 사용되는 리소스를 빠르게 제공하여 상호작용 시간을 단축할 수 있다.

3. Hydration

  • Next.js와 같은 프레임워크에서 클라이언트 사이드 렌더링에서 사용하는 중요한 개념.
    서버 사이드 렌더링(SSR)이나 정적 사이트 생성(SSG) 이후, 서버에서 렌더링된 HTML이 브라우저에 전달되면, 클라이언트 측에서 자바스크립트를 통해 해당 HTML에 상호작용성을 추가하는 과정을 Hydration이라고 한다.
    (서버에서 HTML 껍데기를 먼저 클라이언트(브라우저)에게 보내고, 그 후 클라이언트에서 자바스크립트를 통해 해당 HTML에 상호작용성을 추가하는 과정!)
  • CSR

    • React에서 CSR로만 컴포넌트 렌더링을 할 때는 TTV가 오래 걸렸다.
      (모든 React 소스파일을 다운로드 받아야만 화면을 볼 수 있기 때문)
    • 여기에서 Hydration 개념이 들어간다.
      최초 서버에서는 index.html 파일만 제공하지만 이후 React 소스파일을 바탕으로 한 자바스크립트 파일이 모두 다운로드 돼야만(즉, Hydration이 돼야만) 최종 소스코드를 볼 수 있는 것.
      • 하지만 CSR의 과정에서의 Hydration 과정을 Hydration으로 볼 것이냐 하는 것은 이견이 있을 수 있다.
  • SSR

    • 서버에서는 사용자의 요청이 있을 때마다 페이지를 새로 그려서 사용자에게 제공.
    • 두 과정으로 나눠서 제공.
      1. pre-rendering : 사용자와 상호작용하는 부분을 제외한 껍데기만을 먼저 브라우저에게 제공. TTV가 엄청나게 빠름.
      2. hydration : 이 과정이 일어나기 전까지는 껍데기만 있는 html 파일이기 때문에 사용자가 아무리 버튼을 click 해도 아무 동작이 일어나지 않는다. 인터렉션에 필요한 모든 파일을 다운로드 받는 과정 즉, hydration 과정이 끝나야 그제서야 인터렉션이 가능. 이 간극! TTI를 줄이는 것이 관건이라 할 수 있다.
  • SSG, ISR도 SSR과 마찬가지로 hydration 과정이 존재.

0개의 댓글