react + vite + ssr

설치

  1. npm create vite-extra@latest
  2. ssr-react 선택: ssr 환경의 리액트 프로젝트를 만들 목적
  3. streaming / non-streaming
    • streaming: 데이터가 준비되는 대로 실시간·점진적으로 처리/전송. 빠른 반응과 실시간성이 필요할 때 유리
      • 데이터를 한 번에 모두 준비해서 보내는 것이 아니라, 데이터가 생성되는 즉시 또는 처리 가능한 단위(청크, chunk)로 나누어 실시간 또는 점진적으로 전송합니다.
      • 예를 들어, 서버 사이드 렌더링(SSR)에서 streaming을 사용하면, 서버가 HTML을 한 번에 다 만들어서 보내는 것이 아니라, 먼저 렌더링된 부분부터 클라이언트로 보내고, 나머지는 준비되는 대로 순차적으로 전송합니다.
      • 사용자는 전체 데이터가 도착하기 전에 일부 결과를 먼저 받아볼 수 있어, 초기 반응 속도가 빠르고, 대용량 데이터나 실시간 데이터 처리에 유리합니다.
      • 대표적인 예: 유튜브 동영상, 실시간 채팅, 라이브 방송, 실시간 로그 분석 등.
    • non-streaming: 전체 데이터를 모두 준비한 뒤 한 번에 처리/전송, 구현이 쉽고, 단순한 요구에 적합
      • 데이터를 모두 준비한 뒤 한 번에 전송하거나 처리합니다.
      • 서버에서 모든 데이터를 완전히 렌더링하거나 준비한 후, 클라이언트에 한 번에 전달합니다.
      • 전체 데이터가 준비될 때까지 기다려야 하므로, 초기 응답 속도가 느릴 수 있습니다.
      • 구현이 단순하고, 데이터 크기가 작거나 실시간성이 필요 없는 상황에 적합합니다.
  4. typescript + SWR
    • SWC란 무엇인가?
      • SWC는 Rust로 만들어진 초고속 자바스크립트/타입스크립트 트랜스파일러이자 번들러입니다.
      • TypeScript, JSX(React), 최신 자바스크립트 문법을 구형 브라우저나 Node.js가 이해할 수 있는 코드로 변환해줍니다.
      • 기존 Babel이나 tsc(TypeScript Compiler)보다 훨씬 빠른 속도를 자랑합니다.
    • SWC의 주요 용도
      • TypeScript와 JSX 트랜스파일: TypeScript 코드를 자바스크립트로, JSX를 React.createElement 형태로 변환.
      • 최신 JS 문법 변환: ES6+ 문법을 구형 환경에 맞게 변환.
      • 빌드 속도 향상: Babel, tsc에 비해 빌드 및 핫 리로드 속도가 매우 빠름.
      • Vite, Next.js 등에서 공식 지원: Vite의 플러그인(@vitejs/plugin-react-swc)으로 쉽게 적용 가능.
    • SWC가 필요한가?
      • TypeScript + React + Vite 조합이라면, SWC를 쓰면 빌드/개발 속도가 크게 향상됩니다.
      • react-query를 쓰는 것과는 별개로, SWC는 컴파일러/트랜스파일러로서 코드 변환 및 빌드 성능에 영향을 줍니다.
      • 대규모 프로젝트, 빠른 개발 환경, 최신 문법 사용이 필요하다면 SWC 사용을 추천합니다.

설치 후


프로젝트 설치 후 파일을 확인해보면, SSR을 위한 entry-client.tsx, entry-server.tsx, server.js가 세팅이 되어있다.

entry-client.tsx

import './index.css'
import { StrictMode } from 'react'
import { hydrateRoot } from 'react-dom/client'
import App from './App'

hydrateRoot(
  document.getElementById('root') as HTMLElement,
  <StrictMode>
    <App />
  </StrictMode>,
)

위 코드는 SSR(서버 사이드 렌더링)을 지원하는 리액트 프로젝트의 클라이언트 엔트리 파일(entry-client.tsx)에서 자주 볼 수 있는 형태입니다.

  • 코드 설명
    • hydrateRoot: SSR에서 서버가 미리 렌더링해준 HTML에 리액트가 이벤트 바인딩 등 “수분 공급(hydration)“을 하는 함수입니다.
    • BrowserRouter: 리액트 라우터의 브라우저 기반 라우터(클라이언트 라우팅).
    • App: 리액트 앱의 루트 컴포넌트.
  • hydrateRoot를 쓰는가?
    - SSR 환경에서는 서버가 <div id="root">...</div> 안에 이미 완성된 HTML을 넣어줍니다.
    - 클라이언트는 이 HTML을 그대로 활용하고, 이벤트 처리 등 리액트의 기능을 “붙이는” 작업만 합니다. (이 과정을 hydration, 수분 공급이라고 부릅니다.)
    - 반면, CSR에서는 HTML이 비어 있고, JS가 모든 UI를 처음부터 그립니다.
  • 효과
    • 서버가 미리 렌더링한 HTML을 클라이언트가 받아서, 그 위에 리액트가 이벤트 바인딩 및 상태 관리 기능을 붙임(수분 공급).
    • 초기 로딩 속도가 빠르고, SEO에도 유리.

entry-server.tsx

import { StaticRouter } from "react-router";
import App from "./App";
import {
  renderToPipeableStream,
  RenderToPipeableStreamOptions,
} from "react-dom/server";

export function render(_url: string, opts?: RenderToPipeableStreamOptions) {
  return renderToPipeableStream(
    <StaticRouter location={_url}>
      <App />
    </StaticRouter>,
    opts
  );
}
  • 코드 설명
    • renderToPipeableStream: React 18에서 도입된 SSR용 함수로, React 컴포넌트를 HTML로 렌더링하여 Node.js의 스트림 형태로 반환합니다.
      즉, 서버가 HTML을 “스트리밍” 방식으로 클라이언트에 점진적으로 전송할 수 있게 해줍니다.
    • StrictMode: 리액트 개발 모드에서 잠재적 문제를 감지하기 위한 래퍼(개발용).
    • App: 리액트 앱의 루트 컴포넌트.
    • RenderToPipeableStreamOptions: 스트리밍 옵션(예: onShellReady, onAllReady 등 콜백 포함).
  • renderToPipeableStream을 쓰는가?
    • SSR 환경에서 서버가 리액트 컴포넌트를 HTML로 변환해야 할 때,
      React 18부터는 renderToPipeableStream을 사용해 스트리밍 SSR을 구현할 수 있습니다.
    • 이 함수는 Node.js의 스트림에 HTML을 “조각” 단위로 계속 밀어넣어주기 때문에, 클라이언트가 전체 페이지를 기다리지 않고 일부 콘텐츠를 빨리 볼 수 있습니다.
    • CSR에서는 이런 기능이 필요 없으므로, 이 함수를 사용하지 않습니다.
  • 효과
    • 서버가 리액트 컴포넌트를 HTML로 변환해서 클라이언트에 전달합니다.
    • 이때 사용하는 함수가 renderToPipeableStream(React 18+) 또는 renderToString(React 17 이하)입니다.
    • 서버에서 HTML을 스트리밍 방식으로 생성하여, 클라이언트가 빠르게 일부 콘텐츠를 볼 수 있습니다.
    • 서버 코드에 react-dom/server가 반드시 필요합니다.

0개의 댓글