웹 렌더링, React 탄생 전부터 RSC(React Server Components)까지의 흐름

안녕하세요?

지금 가장 주목받고 있는 React 진영의 기술은 단연 RSC(React Server Components)와 Islands Architecture인데요.

React Server Components와 Islands Architecture가 무엇을 해결하려고 하는지 이해하기 위해 React를 메인으로 공부하는 웹 개발자 입장에서 웹페이지 개발의 역사에 대해 쭉 살펴보는 것도 좋을 듯싶어 여기저기 자료를 찾아봤습니다.

이 글은 순전히 한번 읽어볼 정도의 가치만 있으니 참고 바랍니다.

** 목 차 **

  1. React 탄생 전의 웹

  2. 웹 앱 프레임워크

  3. 이 시기까지의 웹 렌더링

  4. Rails, PHP 시대

  5. React의 등장

  6. React SPA 시대

  7. React(CSR)의 장단점

  8. Next.js SSR

  9. SSR의 트레이드오프

  10. Next.js SSG의 주요 특징

  11. SSG의 주요 특징

  12. SSG의 Next.js 파생인 ISR 방식

  13. 더 나은 웹 렌더링을 위해

  14. React Server Components

  15. RSC의 주요 특징

  16. Next.js App Router

  17. Next.js App Router with RSC의 장단점

  18. 그 외의 흐름


1. React 탄생 전의 웹

React 탄생 전의 웹은 iPhone과 Ajax가 주도한 Web 2.0 시대라고 불리는데요.

2005년부터 웹에서 Ajax 기술이 주목받기 시작했으며, 이 때즘, Google Maps 및 Gmail과 같은 서비스가 시장을 주도했었습니다.

Ajax에서 가장 중요한 jQuery가 나온 게 바로 2006년부터네요.

그러다가, iPhone이 2007년 처음 등장하면서 많은 게 변했습니다.

스마트폰 앱의 등장으로 소프트웨어에 사용자의 편의성을 향상시켜야 하는 질적 변화인 변화가 일어났으며, Mobile Safari가 시대를 주도했습니다.

애플의 의도대로 Flash의 종말이 왔으며, HTML5 및 CSS3로 대체되는 과정을 겪게 되었습니다.

그리고 이때쯤 웹 페이지가 아닌 '웹 앱'이 만들어지기 시작한 시대가 되었습니다.

기술과 디바이스의 양대 힘으로 현재까지 이어지는 SNS 등 다양한 플랫폼이 등장한 시대이기도 합니다.

그렇다 하더라도 현재에도 웹앱 보다는 웹 페이지가 더 많고 일반적이며 또, WordPress로 만들어진 사이트가 가장 많다고 알려져 있습니다.


2. 웹 앱 프레임워크

순수한 JavaScript나 jQuery만을 사용하여 복잡한 웹 앱을 구축 및 운영하는 것은 어려웠습니다.

그래서 최선의 구현 방법과 문법을 제공하는 프레임워크들이 주목받았습니다.

Backbone.js(2010년~), AngularJS(2009년~), Knockout.js(2010년~) 등이 대표적인 예시입니다.

MVVM과 같은 당시 주류 아키텍처는 현재도 모바일 앱 개발 등에서 가장 일반적인 설계 지침으로 사용되기도 합니다.


3. 이 시기까지의 웹 렌더링

이 시기까지의 웹 렌더링은 여러 가지가 있었습니다.

대표적인 예시로는 RoR, Erb + jQuery, CoffeeScript(Rails에서 일시적으로 유행한 altJS로 채택)가 그것입니다.

아래처럼 말입니다.

<%= link_to "Delete Note", @article, remote: true, method: :delete %>

<%= form_with(model: @user) do |f| %>
  <%= f.label :name %><br>
  <%= f.text_field :name %>
  <%= f.submit %>
<% end %>
$ ->
  $("a[data-remote]").on "ajax:success", (event) ->
    alert "Deleting this note!"

$("<%= escape_javascript(render @user) %>").appendTo("#users");

4. Rails, PHP 시대

바야흐로, Ruby on Rails와 PHP의 시대가 도래했는데요.

서버 사이드 렌더링이 대세였습니다.

서버 사이드 프레임워크에 결합된 템플릿 엔진이 HTML이나 JS를 생성하고, 사용자가 처음으로 볼 인터페이스인 HTML을 반환하는 것은 서버의 역할이었으며, UI의 형성을 포함하여 브라우저에서도 좋은 UX를 구현하기 위한 주요 책임은 서버 측에 있었습니다.

프론트 엔드 엔지니어라는 직업은 존재하지 않았으며, 대신 마크업과 스타일링만을 담당하는 코더라는 직종이 존재했습니다.

클라이언트의 역할은 템플릿 엔진에 전달된 객체를 사용하여 HTML과 CSS를 작성하고 jQuery 등을 사용하여 DOM에 이벤트를 추가하는 것입니다.

물론, 당시부터 컴포넌트나 모듈로 프론트 엔드를 관리하는 등의 생각이 존재했으며, MVVM이나 Pub/Sub(event bus)와 같은 설계 패턴이 사용되어 컴포넌트를 분할하면서도 상태 관리와 이벤트 전파를 시도하기도 했었습니다.


5. React의 등장

그러다가 React가 등장했습니다.

React를 한 마디로 표현하면 UI = f(state)입니다.

상태를 정의하면 그것이 UI가 된다는 것입니다.

선언적 UI라는 패러다임을 만들게 됩니다.

Web에서는 가상 DOM 기술을 통해 아주 빠르고 실용적으로 렌더링됩니다.

React의 선언적 UI로 인해 다른 분야까지 선언적 UI의 시대를 가져옵니다.

Swift UI, Flutter 등의 모바일 앱 개발에서도 선언적 UI의 개념이 반영되어 UI 제작의 글로벌 스탠다드가 되었습니다.

React는 jQuery를 대체한 것이 아니라, jQuery가 필요하지 않은 상황에서 React를 사용할 수 있게 되었기 때문에 jQuery가 사라졌다는 말은 정확하지 않은 것 같습니다.

브라우저의 발전(IE9의 점유율 감소)과 JS(EcmaScript)의 발전, 그리고 Babel, TypeScript, Flow 등의 존재로 인해 ES2015나 altJS를 ES5로 컴파일할 수 있게 되어 jQuery가 필요하지 않아 졌습니다.

React는 프론트 엔드의 설계를 처음부터 다시 만들었기 때문에 Backbone.js, AngularJS 및 풀스택 프레임워크의 템플릿 엔진에 영향을 미쳤습니다.


6. React SPA 시대

템플릿 엔진의 중요도가 낮아졌습니다.

UI 구성 및 브라우저 상에서의 UX 책임은 클라이언트의 역할로 이전되었습니다.

프론트 엔드 엔지니어라는 직업이 탄생했습니다.

Ruby on Rails나 Django와 같은 프레임워크 위에서 React나 Vue를 사용하는 것이 일반적이었으며, 그렇다고 HTML을 반환한 후 SPA로 만드는 것은 그래도 어려운 작업입니다.

Web2.0 시대에는 Twitter나 Google Map API와 같은 Web API가 널리 사용되었습니다.

비동기 통신을 기반으로 한 SPA 개발을 더욱 적극적으로 추진하게 되었습니다.


7. React(CSR)의 장단점

장점

  • Web 앱의 시대에 맞는 부드러운 경험을 쉽게 만들 수 있게 되었습니다.

  • 서버 비용이 저렴하고, 스케일링이 쉬워졌습니다.

  • FCP(FCP는 First Contentful Paint의 약어로, 웹 페이지가 로드되어 브라우저에 표시되기 시작하는 시점을 의미합니다)는 느리지만, 한 번 메인 JS를 캐시한 후에는 기존 SSR 앱보다 더 빠르게 작동할 수 있습니다. (사용자에게 세부적인 피드백이나 인터랙티브한 페이지/컨텐츠 전환에 대한 체감이 빠릅니다.)

  • 캐시를 잘 활용하면 네트워크 비용의 이점을 얻을 수 있습니다.

단점

  • 모바일에서는 통신 속도 등이 영향을 미치기 때문에 사이트의 성능 보장이 어렵습니다.

  • 백색 화면이 오랜 시간 표시되는 문제가 발생하는 사이트도 있습니다.

  • 인터랙티브가 적은 페이지나 앱에 대해서 CSR을 채택하는 것은 성능의 단점에 대한 이점이 적습니다.

  • SEO적으로 불리하다는 시대가 있었습니다.

  • Web은 페이지를 기반으로 발전해 왔기 때문에, Web 표준의 준수에 어려움이 생길 수 있습니다.


Next.js의 등장과 웹 렌더링의 변화


8. Next.js SSR

JavaScript를 작성하는 엔지니어가 HTML, JS를 적절한 상태로 사용자에게 전달하는 책임을 모두 수행할 수 있게 되었습니다.

서버 사이드와 프론트 엔드의 경계가 불분명해졌으며, BFF(SSR 포함)까지 프론트 엔드 엔지니어의 업무로 인식되는 조직이 늘어났습니다.

SSR을 통해 적절한 HTML이나 CSS를 반환할 수 있게 되어, 백색 화면이 표시되는 것과 같은 현상은 사라졌지만, 반대로 하이드레이션이라는 기술적인 문제가 발생하게 되었습니다.

"하이드레이션" 또는 "리하이드레이션"은 React가 서버 사이드에서 실행될 수 있어 UI를 구성할 수 있지만, 해당 UI는 HTML과 CSS가 적용된 상태일 뿐입니다.

예를 들어 버튼은 보이지만 클릭해도 아무 일도 일어나지 않습니다.

버튼을 클릭하여 어떤 작업을 수행하려면 JavaScript가 브라우저에서 실행되어 인터랙티브 상태가 될 때까지 기다려야 합니다.

이 그림이 보이고 나서 인터랙티브 상태가 될 때까지의 과정을 Web에서는 "하이드레이션"이라고 합니다.

SSR된 HTML과 JS로 만든 프리즈드라이의 컵라면이 뜨거운 물로 먹을 수 있는 상태(브라우저에서 인터랙티브 상태가 되는)로 돌아가는 것과 같은 느낌입니다.


9. SSR의 트레이드오프

장점

  • 어떤 것이든 만들 수 있습니다. (가장 유연함)

단점

  • 요청마다 서버 사이드에서 HTML을 생성하기 때문에 서버 비용이 높아지거나 스케일링 문제를 가질 수 있습니다.
  • 하이드레이션의 문제에 대한 방침이나 대응책이 필요한 경우가 있습니다.
  • 모바일에서는 하이드레이션이 몇 초에서 몇 분이 걸리는 경우도 있습니다.

참고로 하이드레이션의 문제는 React 이후 고유한 문제가 아닙니다.

JS, jQuery 시대부터 HTML의 렌더링을 우선시하여 JS를 defer나 async(DOMContentLoaded)로 실행한 경우, 보이는 것과는 다르게 클릭해도 아무 일도 일어나지 않는 버튼 문제는 예전부터 존재했습니다.

그러나 번들 크기가 커진 것으로 인해 더욱더 눈에 띄게 되었습니다.


CDN의 진화와 SSG


10. Next.js SSG의 주요 특징

  • React가 서버에서 작동하도록 되어 있기 때문에, 서버에서 HTML을 매번 생성하는 것이 아니라 미리 HTML/JS를 생성하여 CDN을 통해 정적으로 배포할 수 있게 되었습니다.

  • Next.js가 출시된 동시에 Fastly나 CloudFlare와 같은 CDN(Edge Side Cloud Computing)이 발전하여 가능한 일이 넓어졌기 때문에, 회원제 사이트 등에서도 이 SSG가 사용되기 시작했습니다.

  • Dev.to 등의 CDN과 SSG로 만들어진 사이트가 빠르고, 이 분야에서 화제가 되었습니다.

  • React와 거리를 두고 있던 서버 사이드 엔지니어도 Next.js나 주변의 렌더링 및 배포 메커니즘에 관심을 가지는 사람이 늘어난 것 같습니다.


11. SSG의 주요 특징

장점

  • 서버가 존재하지 않기 때문에 스케일링과 비용 측면에서 가장 강력합니다.

단점

  • 요구 사항을 충족시키지 못하는 서비스가 존재합니다.

  • 앱이나 SaaS 계열은 대체로 SSG로 대체할 수 없습니다.

  • 회원제이며 특정 사용자의 정보를 표시해야 하는 경우, 다른 아키텍처가 더 적합할 가능성이 높습니다.

SSG는 요구 사항에 따라 최상의 구성이 될 수 있으며, 워드프레스와 같이 Web에서 가장 많이 사용되는 사이트를 대체할 수 있는 가능성이 있어 JAMStack과 같은 마케팅 용어도 등장했으며, Netlify 등의 Cloud Computing 회사가 주도했습니다.


12. SSG의 Next.js 파생인 ISR 방식

ISR(Incremental Static Regeneration)은 시간이나 이벤트 등의 트리거를 기반으로 SSG를 수행하는 Next.js(Vercel)가 발표한 기능입니다.

비용 최적화 등이 어려워서, 그다지 보급되지 않은 것 같습니다.

CDN 최적화까지 포함하여 배포 흐름이나 서버만으로 완결시키지 않고, 예를 들어 SSR 결과를 30분 캐시하는 것과 같은 것도 가능하지만, 이러한 구성이 인프라에 대한 의존성이 적거나 컴퓨터 리소스가 적게 드는 경우도 있어서, 어떤 경우에 ISR이 적합한지 판단하기는 어려울 것 같습니다.

그렇지만 옵션이 하나 더 생긴 것은 유용한 경우도 있습니다.


13. 더 나은 웹 렌더링을 위해

가능한 유스 케이스에서는 SSG를 우선합니다.

하이드레이션을 고려한 SSR입니다.

가능한 경우 SSR 결과의 HTML, JS를 CDN에서 캐시합니다.

그러나 하이드레이션을 고려하는 것이 어려웠습니다.

CSR은 소극적인 옵션입니다.

그러나 PC 중심 등 모바일 사용자가 적은(네트워크 환경이 보장되는) 서비스의 경우, 사용자 경험이 좋고 인프라적으로도 배포하기 쉬울 수 있습니다.

B2B의 SaaS 등은 이 분야가 많습니다.

Slack과 같은 콘텐츠와 요청이 풍부한 SPA가 되면, 다른 병목 현상이 많아 렌더링 옵션이 오차가 될 수 있습니다.


14. React Server Components

RSC의 가장 기본적인 멘탈 모델은 "React 애플리케이션 내에 서버에서 실행되는 부분과 클라이언트 측에서 실행되는 부분이 있다"는 것입니다.

RSC에는 프로그램을 여러 단계로 분할하여 처리하는 경우 2단계 계산이 있습니다.

"stage 0"과 "stage 1"이 있습니다.

→ 지금까지의 SSR은 Stage 1에서 Node.js에서 React를 실행하는 상태였습니다.

→ 이번 RSC는 Stage 0을 추가했습니다.

→ 서버 측에서만 작동하기 때문에 useState와 같은 상태 관리 기능을 사용할 수 없습니다.


15. RSC의 주요 특징

Stage 0에 의해 UI 구성과 관련 없는 코드를 Stage 1에서 제외할 수 있습니다.

번들 크기를 줄일 수 있는 가능성이 있습니다.

React 팀은 제로 번들 크기의 React에도 대응하고 있습니다.

Next.js나 Nuxt.js에서는 클라이언트와 서버 코드가 섞이는 등의 보안 위험 등이 지적되어 왔지만, Server Component는 클라이언트에게 전달되지 않습니다.

클라이언트와 서버 코드는 공통화하지 않고 (유형, 유효성 검사, 스키마는 공통화하는 것이 좋을 수도 있지만) 명시적으로 분리하는 것이 좋습니다.

이러한 방식이 커뮤니티의 발전과 함께 공통 인식이 되고 있습니다.

Server Component는 useState를 사용할 수 없지만, Next.js에서는 톱 레벨 페이지에서만 사용할 수 있었던 getServerProps() 등이 어디에서든 사용할 수 있게 되었습니다.

특히 React Query나 SWR을 사용하는 경우, 상당한 설계 변경이 발생할 수 있습니다.

fetch 등의 문제와 캐시 등의 문제를 어떻게 처리할 것인가는 중요한 문제입니다.

컴포넌트 설계와 상태 관리에도 설계의 영향을 미칠 수 있는 변경 사항입니다.


16. Next.js App Router

Next.js 개발팀이 내건 App Router의 개발 의도는 다음과 같은데요.

"우리의 라우터를 스트리밍과 호환되도록 만들고, 레이아웃에 대한 향상된 지원 요청을 해결하기 위해 새 버전의 라우터를 구축하기로 결정했습니다."

→ RSC와 Suspense로 인해 React UI는 Concurrent Rendering과 Partial Hydration을 지향할 수 있게 되었습니다.

→ 이에 따라 이 시대의 Router 구성을 Page에서 App으로 재검토하고 있습니다.

또한 React 공식문서에서는 RSC 이후에는 Create React App 등에서 순수한 React SPA를 만드는 것이 비권장 사항이 되어, Next.js나 Remix 등의 래퍼 프레임워크를 통해 작업하는 것을 권장하고 있습니다.


17. Next.js App Router with RSC의 장단점

장점

  • SSR의 중에서도 가장 클라이언트적인 체감을 제공하는 앱을 만들 수 있는 잠재력이 있습니다.

  • SSG를 수행하는 경우에도, RSC를 사용하면 번들 크기를 줄일 수 있는 가능성이 있습니다.

  • 이름 때문인지 오해하는 사람도 있지만, RSC를 사용한 후 (Stage 0을 실행한 후) SSG를 수행할 수 있으므로, 단순히 전달할 번들 크기를 줄이는 데 효과가 있습니다.

  • CSR의 경우에도 마찬가지이므로, 개발적인 어려움을 제외하면 기능적인 단점은 없습니다.

단점

  • SSR을 사용하는 경우, SSG나 CSR과 비교하여 서버가 필요합니다.

  • Vercel이 서버를 판매하기 위해 이러한 움직임을 하는 것은 아닌지라는 비판도 있습니다.

  • 저는 위의 내용에 동의하지 않습니다. 순수하게 UX를 개선하기 위한 설계를 추구하고 있다는 느낌이 들며, 또한 App Router와 RSC 모두 SSR 고유의 것이 아닙니다. SSG나 CSR과 함께 사용할 수 있습니다.

적합성은 조직에 따라 다르게 느껴집니다.

실제로 React를 개발하는 Meta 사는 Node.js 회사가 아니므로, React 자체가 RSC 개발을 자사에서 완결할 수 없어 Vercel과 같은 외부 파트너와 협력하고 있습니다.

설계가 변경됩니다. 좋은 앱을 만들기 위한 설계나 작성 방법은 더욱 어려워졌습니다(요구되는 컨셉트에 대한 이해가 높아졌다는 느낌).

Next.js가 어려워졌다는 의견도 종종 보입니다.

개인적으로는, Fetch와 Cache 등의 상태 관리에 대한 베스트 프랙티스나 설계가 확립되지 않으면 보급되지 않을 것 같습니다.

React를 일상적으로 작성하고 따라가고 있지만, 이러한 의견의 감정을 이해할 수 있습니다.


18. 그 외의 흐름

성능의 안정성과 웹 표준의 준수를 향상시키기 위해 SPA 대신 MPA를 사용하는 파벌도 있으며, Astro라는 프레임워크가 일정한 지지를 받고 있습니다.

Deno를 사용한 Web은 SSR로 회귀한다는 기사가 화제가 되고 있습니다.

또한 Fresh(Deno의 프레임워크)나 Astro에서 사용하는 Islands Architecture는 React Server Components와 아키텍처가 매우 유사합니다.

RSC는 MPA Island Architecture를 기반으로 routing 등의 단점을 제거하여 SPA로 만든 것으로도 알려져 있습니다.

최근 등장한 React Server Components, Islands Architecture(Astro, Fresh), Qwik는 하이드레이션의 문제를 해결하려는 시도로 볼 수 있습니다.

SSR의 문제를 해결하기 위한 Partial Hydration도 있습니다.

Edge Computing 상에서 렌더링하는 것에 초점을 맞춘 SSR의 파생인 Remix와 같은 프레임워크도 있으며, ESR이라고도 불립니다.

Static한 콘텐츠만 전달했던 CDN 시대부터 Edge Computing을 통한 렌더링의 구현이 쉬워졌습니다.


지금까지 살펴본 내용은 웹 렌더링과 관련된 기술입니다.

이에 대한 기술로는 SSR, SSG, RSC, Astro, Fresh, Qwik 등의 기술이 소개되었습니다.

이러한 기술들은 웹 렌더링의 성능과 안정성을 향상시키기 위해 개발되었으며, 각각의 기술은 장단점을 가지고 있습니다.

이러한 기술들은 웹 개발자들에게 많은 영감을 주고 있으며, 앞으로 더욱 발전할 것으로 예상됩니다.