CSR, SSR 그리고 React18
제가 회사에서 작업하는 프로젝트는 2개가 있는데요. 하나는 SSR로 구현되어 있고, 하나는 CSR로 구현되어 있습니다. CSR은, JavaScript 파일이 브라우저에 다운로드 되면, React는 Tree를 렌더링 하고 DOM Node를 생성합니다. 그리고 Data Fetching 을 합니다. 이러한 특성 때문에 콘텐츠의 첫 번째 바이트를 수신하는데 걸리는 시간인 TTFB(Time To First Byte)는 빠르지만, 페이지의 주요 콘텐츠가 로딩되는데 걸리는 시간 LCP(Largest Contentful Paint) 은 SSR에 비하여 느릴 수 있습니다. SSR 은, 서버에서 Data Fetching + 자바스크립트를 실행한 뒤 해당 HTML 을 클라이언트에 제공합니다. 따라서, TTFB는 다소 느릴 수 있어도 CSR에 비해 LCP는 빠릅니다. React18에서는, SSR에서 성능적인 구조 개선을 이루었습니다. SSR 을 구현하는 Api인 renderToString, renderToNodeStream 이 Deprecated 되고, renderToPipeableStream 이 추가되었는데요. renderToPipeableStream 은, 에러 바운더리 처리를 해주는 Suspense를 서포트 하고, streaming 을 지원합니다. Suspense는 이전 renderToNodeStream Api 에서도 서포트 하던 기능이었는데, 이번에 추가된 streaming 이란 무엇일까요? MDN 문서에 따르면 streaming 이란, 'breaking a resource that you want to receive over a network down into small chunks, then processing it bit by bit'이라고 되어 있습니다. 즉, 리소스를 작은 덩어리로 나누어서 순차적으로 받는다는 말입니다. 기존 React SSR에서는 페이지에 필요한 모든 데이터를 Fetching 한 뒤 HTML 을 생성 후 클라이언트에 보내야 했습니다. 그렇지만 Streaming 기능을 구현함으로써, 더 작은 단위로 더 빨리 클라이언트로 보내면서, 더 빠른 TTFB 가 가능해지고, 스트리밍을 시작하는 즉시, 다른 자산 (CSS, JavaScript, Font 등) 을 로드하여 더 많은 요청의 병렬 화가 가능해졌습니다. 이 외에도 Selective Hydration 을 구현하여, 렌더링 비용이 큰 컴포넌트는 Suspense로 감싸서 부분적이고 독립적인 Hydrate 도 구현하였다고 합니다. (Hydration: SSR에서 정적 렌더링 시, 건조한 HTML(이벤트가 없는) 상태에 수분 보충(이벤트)을 해주는 기술) React18에서는 성능적으로 많은 개선이 일어난 것 같습니다. 빠르게 실무에서 적용해 볼 수 있으면 좋겠네요