이전 글에서 살펴본 SSR의 문제점으로는 크게 세 가지가 있습니다.
1️⃣ You have to fetch everything before you can show anything
2️⃣ You have to load everything before you can hydrate anything
3️⃣ You have to hydrate everything before you can interact with anything
각 문제에 대해 짚어보고 Suspense를 통해 어떤 개선이 이루어졌는지 알아봅니다.
💡 fetch everything before you can show anything
SSR은 서버에서 모든 데이터가 준비된 후에 렌더링 됩니다.
즉, 모든 데이터가 준비되는 시간이 지연되는 만큼 렌더링 시간 또한 지연되는 것입니다.
위 그림과 같이 article 컴포넌트의 데이터를 제외한 나머지 컴포넌트의 데이터 준비가 완료되었더라도
article 컴포넌트의 데이터까지 준비가 완료되어야 렌더링이 가능합니다.
데이터 준비가 완료된 컴포넌트 우선적으로 사용자에게 보인다면 훨씬 효율적이겠죠.
💡 load everything before you can hydrate anything
SSR 프로세스는 서버에서 렌더링 완료된 HTML 페이지를 받고 상호작용 가능하도록 JS를 로드하여 HTML에 연결(hydration)해주는 과정을 거칩니다.
문제점은 hydration 과정이 모든 JS가 로드 완료되고 진행된다는 점입니다.
각 컴포넌트 별로 hydration 과정이 개별적으로 진행된다면 효율적이겠습니다.
💡 hydrate everything before you can interact with anything
앞서 언급한 두 가지 문제점의 공통점은 개별적으로 진행하지 못한다는 점입니다.
모든 데이터가 준비되어야 렌더링이 가능하고 모든 JS가 로드되어야 hydration이 가능했습니다.
마지막 문제점 또한 비슷한 맥락이네요.
모든 hydration이 완료되어야 상호작용이 가능합니다.
🚨 문제점
위의 그림과 같이 모든 데이터가 준비 완료 -> 모든 JS 파일이 로드 완료 -> 모든 hydrate가 완료되어야 상호작용이 가능합니다.
문제점은 waterfall 형태의 처리 방식에 있습니다.
문제를 개선하기 위해서는 위의 그림과 같이 앱 전체 단위로 진행되는 방식에서 Concurrent하게 화면을 구성하는 각각의 단위로 진행되어야 합니다.
💡 React 18: Suspense 그리고 개선 방향
React18의 Suspense 활용할 경우 Streaming HTML과 Selective Hydartation 기능을 사용할 수 있습니다.
⚪️ Streaming HTML
Suspense로 특정 컴포넌트를 감쌀 경우 해당 컴포넌트가 준비되기 전까지 fallback UI를 보여줍니다.
Suspense로 감싼 Article 컴포넌트는 최초로 서버에서 렌더링 된 HTML에 fallback UI가 들어갑니다.
이를 통해 위의 그림과 같이 Article 컴포넌트의 데이터 준비를 기다리지 않고 페이지의 나머지 요소를 보여줄 수 있습니다.
서버에서 Article 컴포넌트의 데이터 준비가 완료될 경우 React는 같은 stream에 추가로 HTML을 전송합니다.
( HTML을 올바른 위치에 배치하기 위해 inline script를 함께 전송합니다. )
이로써 첫 번째 문제점인 모든 데이터가 준비 완료된 이후 렌더링을 시작하는 문제를 해결할 수 있습니다.
⚪️ Selective Hydartation
위의 코드에서 Article 컴포넌트는 Suspense로 감싸져있고
Article 컴포넌트는 서버에서 데이터 준비가 완료된 이후에 전송됩니다.
Article 컴포넌트 외의 요소들과 나중에 전송된 Article 컴포넌트는 Selective Hydration을 통해 각각 hydration을 진행하게 됩니다.
모든 JS 로드되는 것을 기다리지 않고 Suspense로 기준으로 나뉜 부분은 각각 hydration이 발생합니다.
두 번째 문제점인 모든 JS 로드된 이후 hydartion이 진행되는 문제를 해결 가능합니다.
⚪️ 우선순위에 따른 hydration
추가로 Post 컴포넌트도 Suspense로 감싸주었습니다.
hydration은 트리에서 더 먼저 발견되는 부분이 먼저 진행되어
Post 컴포넌트가 Article 컴포넌트보다 hydration이 우선적으로 진행됩니다.
Post 컴포넌트가 hydrating 중에 Article 컴포넌트에서 이벤트가 발생하면 이벤트 발생한 컴포넌트에 hydration 우선순위를 부여합니다.
즉, 유저 상호작용을 통해 유동적으로 hydration 우선순위를 부여할 수 있습니다.
Seletive Hydration의 장점은 Suspense boundary를 더욱 세분화할 경우 더 분명해집니다.
이로써, 세 번째 문제점인 모든 hydration이 진행된 후 상호작용이 가능한 문제를 해결 가능합니다.
💡 마무리
React18에서 가장 큰 변화인 Fiber Architecture를 통해 테스크를 Concurrent하게 처리할 수 있습니다.
이번 글을 통해 기존 SSR에서의 문제점에 대해 정리하였고
Suspense를 활용하여 Waterfall 형태의 진행 방식에서 Concurrent한 방식으로 개선할 수 있음을 확인했습니다.
이를 통해, React 개발 서사에서 Suspense 등장에 대해 이해할 수 있었습니다.
React를 처음 접했을 당시에는 SPA의 대표 라이브러리로써 CSR 방식만을 사용하는 줄 알았으나
기존 SSR의 문제점을 개선하고 더 나아가 React Server Component를 도입하여
각 상황에 적합한 렌더링 방식을 채택할 수 있도록 다양한 선택지를 제공해 주는 것 같습니다.
🔦 References
Written by
At
Wed Mar 27 2024