왜?
•
자바스크립트가 늘어나며(자바스크립트가 늘어난다는 것은 번들용량 증가로 인한 다운로드 시간 증가 및 rendering에 걸리는 시간 증가 모두를 포함한다.) 이용자가 첫화면을 보기까지 오랜 시간이 걸렸다.
과거
•
php , ruby on rails
•
서버에서 렌더링 완료 후 interactivity를 위해 jQuery 추가
•
느린 개발, error prone, duplicated logic
현재의 SSR
•
Angular, svelte, react, vue에서 수행하는 그것.
•
Component를 서버에서 HTML로 렌더링해서 브라우저에게 전달해주는 방식 → 초기 화면은 더 빠르게 뜬다.
•
Interactive 요소들은 SSR 초기에는 동작하지 않고 hydration 과정을 거쳐야 동작한다.
•
SSR을 사용하지 않는다면 JS를 다운받고 로딩하는 동안 유저는 빈페이지를 보게된다. → 나쁜 사용자 경험
Hydration
•
메모리상 컴포넌트를 렌더링하고(VDOM) HTML에 이벤트 핸들러와 같은 로직을 붙여주는 과정.
◦
DOM은 이미 서버에서 그려져서 브라우저로 왔으므로 DOM을 다시 그리지는 않는다.
현 (대중적인)SSR의 문제점
두번 렌더링되는 앱
•
서버에서 렌더된 후 유저에게 전달된 후 클라이언트에서 한번더 렌더링 됨
◦
Interactivity를 위해 Hydration을 사용하므로 서버에서한번 브라우저에서 한번 총 두번 실행된다.→ TTI가 느려짐
•
Reconcile 로직을 이용해 처음에 서버에서 받은 DOM 노드들을 최대한 활용, 퍼포먼스가 조금더 나아지지만 기본적인 CSR보다 TTI가 훨씬 늘 수 밖에 없음.
모든 백엔드 API의 결과를 기다려야한다.
•
예를 들어 느린 백엔드 API가 존재할 경우 다른 HTML은 다그렸어도 해당 “느린” API 때문에 SSR과정 자체가 느려진다.
•
느려지는 SSR은 해당 API를 사용하는 컴포넌트 뿐 아니라 네비게이션바, 사이드바, 포스팅 본문과 같은 모든걸 뜻한다. → 느려지지 않아도 되는 데이터들이 느려진다는 뜻
모든 자바스크립트 로딩이 되어야 Hydrate 할 수 있다.
•
하나의 컴포넌트에 복잡하고 큰 로직이 존재하여 다운로드에 긴 시간이 걸릴경우 해당 컴포넌트의 복잡하고 큰 로직으로 인한 긴 시간이 모두 소모되어야 다른 컴포넌트들도 hydration을 수행할 수 있다.
모든 Hydration 로직은 한번에 이루어진다.
•
모든 컴포넌트가 전부 hydration이 이루어져야 실제로 상호작용 가능한 컴포넌트가 된다.
•
부분적인 선 hydration이 이루어지지 않으므로 링크와 같은 페이지 이동또한 “모든 컴포넌트의 hydration”이 끝날때 까지 기다려야한다.
이 모든것을 해결할수 있는 하나의 방법 React 18의 suspense - concurrency
suspense
•
Suspense는 React 18 등장 전에는 로딩UI를 선언적으로 보여주는 방법에 불가했으나 React 18부터는 실제로 하는 부분들이 많아진다.
•
아래는 “문제를 어떻게 해결하는가에 대한 설명”
모든 백엔드의 API 결과를 기다려야한다
•
suspense로 오래걸리는 백엔드에 API 요청하는 컴포넌트를 감쌀 경우 해당API 결과를 기다릴 필요 없이 다른 UI 요소들의 HTML 부터 보낸다.
•
이 과정에서 Hydration이 되기전에 댓글 부분을 먼저 보여줄 수 있다.
모든 자바스크립트 로딩이 되어야 Hydrate 할 수 있다.
•
Susepense로 해당 컴포넌트가 감싸져있을 경우 부분 hydration이 가능하다. → 코드 부분부분이 로드될때 마다 hydration을 진행할 수 있다.
모든 Hydration 로직은 한번에 이루어진다.
•
Streaming HTML 보다 자바스크립트가 먼저 로드될 경우 리액트는 페이지를 먼저 Hydration한다.
•
이때 suspense는 일관적으로 non blocking 하게 동작하여 리액트는 먼저 도착한것을 먼저 처리할 뿐
Hydration 중지 및 우선순위 변경
•
추가적으로 유저가 해당 컴포넌트를 먼저 클릭했을 경우 해당 컴포넌트를 먼저 hydration한다.
미래
•
google wiz, marko, builder
•
앱을 두번 실행할 일이 없다.