Suspense on the server
New Suspense SSR Architecture in React 18 · Discussion #37 · reactwg/react-18
Overview React 18 will include architectural improvements to React server-side rendering (SSR) performance. These improvements are substantial and are the culmination of several years of work. Most...
github.com
서버 사이드 렌더링의 장점
서버 사이드 렌더링을 하지 않을 때는 자바스크립트가 로드되기 전까지는 아무것도 볼 수가 없다. 하지만 서버 사이드 렌더링을 하면 자바스크립트가 로드되기 전에는 버튼을 클릭하거나 상호 작용할 수 있는 부분은 사용하지 못하지만 자바스크립트가 로드되는 과정에서도 정적인 파일들을 화면에 보여줄 수가 있다. 그래서 네트워크가 느린 컴퓨터도 빠르게 화면을 볼 수가 있다. 이것 뿐 아니라 index 생성이 쉽고 속도가 빨라 검색 엔진 순위에도 도움이 된다.
오늘날 서버 사이드 렌더링의 단점은?
- 어떤 걸 가져오려면 모든 걸 Fetch해줘야 한다.
- Hydrate을 하기 전에 모든 걸 로드해야 한다.
- 어떤 것과도 상호 작용하기 전에 모든 걸 Hydrate해야 한다.
- 결국 All or Nothing!
이러한 방법을 해결하기 위해서 React 18에서 하는 것은?
- Streaming HTML (Server)
- Selective Hydration (Client)
Streaming HTML(서버 부분)
모든 데이터를 가져오기 전에 HTML 스트리밍하는 방법은 renderToString 대신 renderToPipeableStream 메소드를 사용하는 것이다. <Suspense>로 <Comments>를 감싸면 React가 페이지의 나머지 부분에 대해 HTML 스트리밍을 시작할 때까지 기다릴 필요가 없다고 React에 알린다. 그리고 React는 주석 대신 자리 표시자(스피너)를 보낸다.
이후 댓글 데이터가 서버에서 준비되면 React는 추가 HTML을 동일한 스트림에 보내고 해당 HTML을 "올바른 위치"에 넣기 위한 최소한의 인라인 <script> 태그를 보낸다.
결과적으로 React 자체가 클라이언트에 로드되기 전에도 뒤늦은 댓글 HTML이 "Pop-up"된다. 이것은 우리의 첫 번째 문제를 해결한다. 이제 아무것도 표시하기 전에 모든 데이터를 가져올 필요가 없다. 화면 일부가 초기 HTML을 지연시키는 경우 모든 HTML을 지연하거나 HTML에서 제외할지 선택할 필요가 없다. 나중에 HTML 스트림에서 해당 부분이 "Pop-in"되도록 허용할 수 있다. 기존 HTML 스트리밍과 달리 하향식(top-down) 순서로 발생할 필요가 없다.
Selective Hydration(클라이언트 부분)
모든 코드가 로드되기 전에 Hydrate하는 방법? 현재는 초기 HTML을 더 일찍 보낼 수 있지만 여전히 문제가 있다. 댓글 위젯에 대한 JavaScript 코드가 로드될 때까지 클라이언트에서 앱을 Hydrate을 시작할 수 없다. 코드 크기가 크면 시간이 걸린다. 큰 번들을 피하기 위해 일반적으로 "코드 분할"을 사용한다. 코드 조각을 동기적으로 로드할 필요가 없도록 지정하면 번들러가 이를 별도의 it 태그로 분할한다. 로드할 필요가 없도록 지정하면 번들러가 이를 별도의 <script> 태그로 분할한다.
React.lazy로 코드 분할을 사용해 기본 번들에서 댓글 코드를 분할할 수 있다. 이전에 이 방법은 서버 사이드 렌더링에서 작동하지 않았다.
React.lazy
클라이언트 사이드 렌더링 단계에서 큰 번들의 자바스크립트 코드들을 작은 청크들로 나누어 로드될 수 있게 해주는 역할. 리액트 18부터는 서버 사이드에서도 가능하다.
서버 사이드 렌더링에서 순차적으로 Hydrating 하는 순서
HTML이 순차적으로 스트리밍되고 렌더링하는 비용이 큰 컴포넌트들은 <Suspense>로 감싸면서 해당 부분이 여전히 폴백 엘리먼트를 내보내고 있어도 그와 상관없이 페이지의 다른 부분 Hydrating을 진행한다.
나머지 부분까지 HTML 스트리밍된 후 JS 번들이 로드된 컴포넌트들은 그 부분 또한 Hydrating해준다.
사용자의 인터렉션에 따라 어떤 것을 먼저 hydration시킬지에 대한 우선 순위를 정할 수 있게 되었다. React는 클릭이 발생했음을 기록하고 대신 더 긴급하기 때문에 댓글에 우선 순위를 부여한다.