(번역) 재개 가능성(Resumability), 그게 뭐야?

Jung Han
9 min readSep 6, 2022

원문: https://dev.to/this-is-learning/resumability-wtf-2gcm

최근 들어 재개 가능성이라는 용어를 들어본 적이 있을 겁니다. 누군가가 Miško Hevery의 새로운 프레임워크인 Qwik의 가능성에 대해 열정적으로 이야기하는 것을 들었을 수도 있고, 곧 출시될 Marco6에 대한 작업에 대해 제가 언급을 들었을 수도 있습니다. 그리고 아마 재개 가능성이 하이드레이션과 관련되어 있다는 것 또한 들었을 것입니다. 또, 당신은 하이드레이션이 명확하게 무엇인지조차 당신은 알고있지 않을 수도 있습니다.

이 글은 그런 당신을 위한 글입니다.

왜 자바스크립트 개발자들은 목말라할까요?

하이드레이션(문제의 일부)에 대해서 여러 정의가 있지만, 제가 가장 좋아하는 정의는 다음과 같습니다.

하이드레이션은 서버 렌더링된 앱을 클라이언트 렌더링된 상태로 복원하는 프로세스입니다.(@mlrawlings)

이게 왜 중요할까요? 예전부터 계속 중요했던 것은 아니었습니다. 과거에는, 백엔드에서 서버 렌더링을 한 다음 상호 작용을 처리하기 위해 자바스크립트를 약간 추가했습니다. 아마도 일부 jQuery도 사용해서요.

이후 상호작용에 대한 요구가 더 증가했고, 우리는 코드에 더 많은 구조를 추가했습니다. 그런 명령형으로 작성된 조각된 코드들은 리액트, 앵귤러 및 뷰와 같은 오늘날 여러분들이 알고 사랑하는 선언적 프레임워크가 되었습니다. UI의 전체 표현은 이제 자바스크립트에 있습니다.

서버 렌더링 기능을 다시 얻기 위해, 이런 프레임워크에서는 서버에서도 실행되며 HTML을 생성합니다. 우리는 단일 언어로 단일 애플리캐이션을 작성하고 유지보수합니다. 브라우저에서 앱이 실행되면, 이런 프레임워크는 이벤트 핸들러를 추가하고 앱이 올바른 상태인지 확인하기 위해 동일한 코드를 재실행합니다. 그리고 그 “리하이드레이션”(추후 하이드레이션으로 축약됨)은 앱이 상호작용 할 수 있게 해줍니다.

괜찮아 보이죠? 하지만 문제가 있습니다.

불쾌한 골짜기에 들어서다

페이지 로드 시 전체 앱을 리렌더링하는 것은 특히 느린 네트워크 혹은 장비에서 페이지가 커질수록 큰 비용이 들 수 있습니다. 실제로 DOM 노드를 다시 만드는 것은 아니지만, 프로세스는 모든 앱 코드를 재생성하는 것처럼 동작합니다.

여기에는 두 가지 문제가 있습니다. 먼저 서버 렌더링 된 페이지가 표시되지만, 자바스크립트가 로드, 파싱 그리고 실행될 때까지 상호작용이 불가능합니다.

페이지에 자바스크립트가 없을 때 폴백을 포함할 수 있지만, 자바스크립트가 실행될 때까지 동일한 사용자 경험을 제공하지 않습니다. 누군가 버튼을 클릭할 수 있지만, 아무런 표시없이 아무런 일도 일어나지 않을 것입니다. 또는 누군가가 전체 페이지를 다시 로드해 이 작업을 다시 수행할 때까지 기다릴 수 있습니다. 0.5초만 더 기다렸다면 부드러운 상호작용이 가능했을 수도 있었는데 말이죠.

둘째로, 실행에 비용이 많이 들 수 있습니다. 이 작업은 메인 스레드를 차단할 수 있습니다. 스크롤 하거나 텍스트를 입력하려는 사용자는 입력이 지연되는 상황에 직면할 것입니다.

최고의 경험은 아닌 거죠.

그래서 재개 가능성이 뭔가요?

단어만 보면 일부 작업을 수행한 뒤에 일시 중지했다가 다시 시작하는 것처럼 느껴집니다. 재개 가능성은 브라우저에서 앱이 시작될 때 프레임워크가 추가 작업을 피하고, 대신 서버에서 실행되는 동안 발생한 내용을 활용할 수 있도록 하는 프로세스입니다. 일종의 컴퓨터가 최대 절전 모드로 전환된 다음 다시 실행했을 때 전환되기 전 상태가 그대로 유지되는 것과 비슷합니다. 재개 가능성을 제외하고는 서버/브라우저 네트워크 경계에서 이 작업을 수행합니다.

재개 가능성을 달성하는 방법은 어떤 면에서는 더 복잡하지만 다른 면에서는 매우 간단하기도 합니다. 시작 시 일부 전역 이벤트 핸들러를 연결한 다음 상호 작용 시 필요한 코드만 실행합니다.

친숙한 느낌이 드시나요? 예전에 바닐라 자바스크립트나 jQuery를 활용해 하던 일과 비슷하지 않나요?

가장 큰 차이점은 현대적인 방식으로 코드를 작성한다는 것입니다. 이건 서버와 브라우저에서 작동하는 단일 앱입니다. 선언적이며 조합(compose) 또한 가능합니다. 그리고 당신이 선호하는 모든 프레임워크의 장점 또한 사용할 수 있습니다.

그럼…하이드레이션이 중요한 이유는 뭘까요? 모든 것이 재개가 가능하지 않은 이유는 뭘까요?

하기 꽤 어렵기 때문입니다. 최신의 선언적 프레임워크는 데이터 기반입니다. 이벤트에서 일부 상태를 업데이트하고 일부 컴포넌트는 다시 리렌더링합니다. 그리고 그 과정에 이 도전들이 놓여 있습니다.

컴포넌트가 상태를 생성하기 위해 실행되지 않는 경우 이벤트 핸들러에 상태가 어떻게 존재할까요? 현대의 프레임워크는 클로저 내에 값을 포함한 함수로 뒤엉켜 있습니다.

컴포넌트와 상관없이 업데이트 해야 하며, 전역에서 사용할 수 있는 모든 것이 필요합니다. 반응형 상태가 필요하며, 코드에서 만든 모든 클로저를 사용하지 않아야 합니다.

또한, 서버에서 앱의 전체 상태를 전달해야 합니다. 앱에서 관리하는 상태 데이터뿐만 아니라 프레임워크의 내부 상태도 포함됩니다. 위 예시는 지나치게 단순화되었지만, 전역 스코프는 앱의 모든 데이터로 구성되어야 합니다.

이런 구현은 쉽지 않으며, 트레이드 오프가 없는 것은 아닙니다.

직렬화

더 무거운 컴파일 외에도 재개 가능성은 직렬화할 수 있는 것에 의존합니다. 그리고 이건 더 많을 수 있습니다. 일반적인 서버 렌더링 앱은 앱의 초기 상태를 두 장소에 저장합니다. 하나는 당신이 작성한 자바스크립트 소스 코드로 하드코딩 되고 다른 하나는 직렬화된 JSON으로 페이지에 작성됩니다. 후자는 서버 실행 시간에 생성된 모든 동적, 비동기 데이터를 얻는 방법입니다.

브라우저에서 애플리케이션을 깨울 때 자바스크립트 코드가 현재 렌더링 된 HTML과 동일한 상태여야 하므로 이 방법이 필요합니다.

아마 당신은 “이 정보를 HTML에서 가져올 수는 없나요?”라고 생각할 수도 있습니다.

가져올 수도 있고, 가져오지 못할 수도 있습니다. 최종 산출물은 최종 포맷팅 된 데이터만 포함됩니다. 손실이 있을 수 있습니다.

실제 시간이 포함되지 않은 포멧팅된 날짜를 HTML에서는 표현하지만, UI를 통해 사용자가 다른 가능한 형식으로 변경할 수 있도록 할 수 있습니다. HTML만 사용한다면 해당 정보를 얻을 수 없습니다.

재개 가능성은 일반적으로 직렬화하는 앱의 데이터에만 의존하기보다는, 서버가 렌더링할 때 프레임워크의 내부 상태를 얻기 위한 유사한 요구 사항이 있습니다. 최소한 각 컴포넌트에 들어오는 모든 프로퍼티는 직렬화해야 합니다. 그래야 전체 컴포넌트 트리를 실행하지 않고 독립적으로 깨울 수 있게 됩니다.

삼총사

다행히 코드를 재개할 수 있게 하려면 브라우저에서 업데이트할 수 있는 항목에 대한 다양한 지식이 필요합니다. 왜냐하면 어떤 이벤트가 어떤 UI를 업데이트할 수 있는지 알아야 하기 때문입니다. 이런 이유로 재개 가능성은 일반적으로 두 가지 다른 최적화와 결합합니다.

한가지 최적화는 점진적 하이드레이션(또는 선택적 하이드레이션)으로 알려져 있습니다. 재개할 수 있는 프레임워크에서는 실제로 하이드레이션되지 않지만, 필요할 때까지 코드 로드를 계속해서 지연할 수 있습니다. 이를 통해 번들을 크게 줄여 “기본적으로 0KB 자바스크립트”를 달성할 수 있습니다. 이는 페이지 로드 지표에 큰 도움이 되지만, 상호 작용이 필요할 때까지만 지연할 수 있습니다. 재개 가능성의 이점은 자바스크립트를 열심히 실행할 필요가 없기 때문에 로드 및 파싱 비용만 들게 됩니다. 그러나 여전히 주의 깊게 수행해야 하며, 중요한 페이지 상호 작용을 미리 로드하는 것이 좋습니다.

서버 렌더링 페이지에 적용하게 되면 다중 페이지 애플리케이션(Multi-Page Application, MPA)에서 찾을 수 있는 업데이트 되지 않는 항목에 대해서도 알 수 있습니다. 이를 통해 프레임워크는 서버에서만 실행해야 하는 컴포넌트에 대한 코드 전송 또는 데이터 직렬화를 건너뛸 수 있습니다. 그리고 이 부분은 재개 가능성의 비용을 크게 상쇄합니다.

이것은 부분 하이드레이션으로 알려져 있습니다. Marko, Astro 또는 Fresh 같은 프레임워크에서 이 기술의 버전인 아일랜드(island)를 본적이 있을 겁니다. 재개할 수 있는 프레임워크와의 차이점은 아일랜드보다 훨씬 더 작은 하위 컴포넌트 수준에서 이 작업을 수행할 수 있으며, 자동으로 수행할 수 있다는 점입니다.

이런 최적화는 종종 독립적으로 작동하는 삼총사로 제공된다는 것을 인식하는 것이 중요합니다. 재개 가능성은 코드가 로드되는 시기나 로드되는 양과는 관련이 없습니다.

재개할 수 있는 세상에서 살기

아직 재개 가능성이라는 종착지에 도달하지 못했고, 시간이 조금은 걸릴 것입니다. 하지만 저희는 SPA 서버 렌더링으로 시작된 문제점을 해결할 것입니다. 우리는 하이드레이션이란 괴물을 만들었고 이제 그 괴물을 물리쳐야 합니다. 가장 큰 요구는 오늘날 우리가 사용하는 MPA의 성능 트레이드오프를 완전하게 완화하는 것입니다.

여기에서 격차를 조정(reconcile)할 수 있고, 이 모든 것이 라우팅에 의존할 때까지 어떤 트레이드오프가 가치가 있는지에 대해 질문을 할 것입니다. 이 접근 방식이 스스로 증명할 기회를 갖기 위해서는 모든 부분이 함께 작동해야 합니다.

하지만 만약 그렇게 된다면, jQuery의 오래된 명령형 웹을 현대의 선언적 자바스크립트 프레임워크와 통합하게 될 것입니다. 그리고는 아마도 웹 단어 사전에서 재개 가능성 및 하이드레이션과 같은 단어를 제거할 수 있을 것입니다.

그리고 이것은 노력할 가치가 있습니다.

🚀 한국어로 된 프런트엔드 아티클을 빠르게 받아보고 싶다면 Korean FE Article(https://kofearticle.substack.com/)을 구독해주세요!

--

--