원문: https://www.builder.io/blog/hydration-tree-resumability-map
2022년, 재앙과도 같았던 컨퍼런스에서 Solid와 Astro를 개발하고 있는 친구들과 이야기를 나눌 수 있는 좋은 기회를 가졌는데, 제겐 그 대화가 컨퍼런스의 최고 하이라이트였습니다! 모든 측면에서 건전한 아이디어 교환과 토론이 있었습니다.
“재개 가능성은 그저 하이드레이션에 불과합니다.”
— 그들은 제게 이의를 제기했습니다.
그들이 틀렸다는 직감이 강하게 들었지만, 어떻게 제 주장을 입증할 수 있을까요? 어떤 멘탈 모델이 그 차이를 보여줄 수 있을까요?
기본부터 살펴봅시다. 애초에 하이드레이션을 무엇으로 정의해야 할까요? 대화 도중 어느 순간 이야기가 딴 길로 샜고, 모든 것을 하이드레이션이라고 부를 수 있게 되었습니다. Ruby on Rails 앱의 작은 jQuery 스크립트 조차도요.
“자바스크립트를 실행하는 것이 하이드레이션을 의미한다면 개념으로서의 하이드레이션은 완전히 의미를 잃게 됩니다. 이는 유용하지 않으며 역사를 거스르는 짓입니다.”
알고리즘으로서의 하이드레이션은 리액트, 뷰, 스벨트, 앵귤러와 같은 SPA 프레임워크가 SSR 지원을 추가했을 때 처음 등장했습니다. 이러한 프레임워크가 브라우저에서 상호작용하게 되려면 루트(<App/>
)에서 앱 전체를 다시 실행하여 HTML로 직렬화할 때(renderToString
) 손실된 상태와 이벤트 핸들러를 복구해야 했습니다.
모든 하이드레이션 구현은 단일 컴포넌트를 루트(일반적으로 <App/>
)로 사용하며, 상호작용이 가능해지려면 트리의 모든 컴포넌트가 실행되어야 합니다. 이벤트 핸들러가 설정된 후에야 사용자가 이벤트 핸들러와 상호작용할 수 있습니다.
하이드레이션은 이전에 서버에서 실행되던 컴포넌트 트리에 상호작용을 추가하는 과정을 통해서만 이해할 수 있습니다. 이는 O(n) 복잡도의 알고리즘으로, 여기서 n은 활성화(wake-up)할 컴포넌트의 수입니다.
Astro 프레임워크에 의해 주목받기 시작한 부분 하이드레이션 개념은 트리의 모든 부분, 특히 완전히 정적인 부분에 하이드레이션을 적용할 필요는 없다는 이해에서 비롯되었습니다. 이 접근 방식은 '상호 작용의 섬(islands of interactivity)'을 설정하여 브라우저의 작업 부하를 줄여 더 빠른 상호 작용으로 이어집니다.
부분 하이드레이션이란 다양한 시점에 hydrateRoot()
를 여러 번 호출하기 때문에 이름이 잘 어울립니다.
하지만 이러한 '상호 작용의 섬'은 개발자가 수동으로 만들어야 한다는 점을 강조할 필요가 있습니다. 또한 이러한 섬은 경계를 생성하여 각 섬이 독립적인 하위 애플리케이션으로 작동하므로 애플리케이션의 다른 부분 간의 통신을 방해할 수 있습니다.
부분 하이드레이션과 마찬가지로, 리액트 서버 컴포넌트는 다른 특성을가진 하이드레이션의 한 형태로 희소 하이드레이션(Sparse Hydration)이라고 부를 수 있습니다.
리액트 서버 컴포넌트는 고립된 섬을 만드는 대신 단일 루트를 유지하여 컴포넌트가 서로 통신할 수 있도록 합니다. 하지만 브라우저에서는 루트의 "서버 컴포넌트"를 다시 실행할 필요가 없습니다. 대신 리액트는 해당 컴포넌트의 가상노드(vNode)를 데이터로 HTML에 직렬화합니다. 이는 공간과 시간의 트레이드오프입니다.
섬 방식 마찬가지로, 개발자는 'use server' 또는 'use client' 지시문을 사용하여 리액트 서버 컴포넌트에서 경계를 설정하는 노력을 기울여야 합니다.
마지막으로, 하이드레이션하거나 컴포넌트를 순회 할 필요 없이 즉각적인 상호 작용을 추구하는 패러다임인 재개 가능성에 대해 알아봅시다. 이는 트리 구조에서 완전히 벗어난 것입니다.
재개 가능성은 루트(또는 진입점)가 컴포넌트가 아닌 이벤트 핸들러라는 점에서 독특합니다.
전통적인 하이드레이션, 부분 하이드레이션, 리액트 서버 컴포넌트에서는 컴포넌트가 루트 역할을 합니다. 부분 하이드레이션의 경우 여러 개의 루트가 있을 수 있지만, 리액트 서버 컴포넌트의 경우 하나의 루트가 있습니다.
반면 재개 가능성은 이벤트 핸들러를 루트로 둡니다. 화살표는 이벤트에서 컴포넌트를 다시 가리키므로 다시 렌더링 할 수 있는 컴포넌트의 경우에도 사용자 코드를 실행할 필요가 없습니다. 이 접근 방식은 모든 컴포넌트를 정적인 것으로 취급하여 효과적으로 처리합니다.
재개 가능성은 프런트엔드 개발의 해시 맵으로, 애플리케이션에 컴포넌트가 얼마나 많던지 상관없이 자바스크립트의 양은 일정하게 유지되는 O(1) 아키텍처입니다. 하이드레이션은 근본적으로 모든 인터랙티브 컴포넌트를 다운로드하고 실행해야 하는 트리 순회(tree walking)입니다.
다양한 형태의 하이드레이션에는 각각 장단점이 있습니다(별도의 포스트로 작성할만한 주제입니다). 기본적으로 동일한 알고리즘을 실행하므로 개발자는 동일한 O(N) 알고리즘의 'N'을 변경해 다양한 트레이드오프를 선택할 수 있습니다.
부분 하이드레이션을 통해 개발자는 애플리케이션을 "수직적으로" 섬으로 분할할 수 있으며, 리액트 서버 컴포넌트를 통해 개발자는 애플리케이션을 "수평적으로" 분할할 수 있습니다. 또한 서스펜스 경계가 있는 리액트 서버 컴포넌트는 앱 내에서 하위 트리의 지연 하이드레이션을 구현할 수 있습니다.
반면 재개 가능성의 위상에선 공을 깨뜨리지 않고는 도넛으로 만들 수 없다는 생각과 유사하게 완전히 다른 알고리즘을 만듭니다. 하이드레이션 기반 프레임워크는 일부 판을 깨뜨리지 않고는 재개할 수 없습니다.
위상수학자에게 구는 정육면체와 동일하며, 둘 다 구멍이 없는 3차원 도형입니다.
🚀 한국어로 된 프런트엔드 아티클을 빠르게 받아보고 싶다면 Korean FE Article(https://kofearticle.substack.com/)을 구독해주세요!