November 29, 2022
이 글을 통해 새로운 자바스크립트 웹 프레임워크의 확산에 대해 이해하고, 규모에 따른 문제와 최근 혁신의 진화에 대해 자세히 알아봅시다.
자바스크립트 생태계에서 최신을 따르는 것은 새가슴들에는 적합하지 않습니다.
업계에 새로 진입하는 사람들이 새로운 라이브러리, 프레임워크, 개념 및 강력한 의견 사이에서 일어나는 일들을 따라가기 것은 매우 어려운 일입니다.
여러분이 기술의 최전선에 있다면, 보통 여러분이 가장 많은 희생을 감수하는 선발주자인 것을 아는 게 좋습니다. 여러분에게 익숙한 “구식” 기술을 기본으로 하고, 새로운 기술에 대해 늦은 채택자가 되는 것이 훌륭한 선택일 수 있습니다.
그렇더라도, 이 포스트는 자바스크립트 생태계에서 프레임워크의 최전선에 대해서 빠르게 알려줄 것입니다.
우리는 대규모 웹 애플리케이션을 만들 때 과거의 문제점들을 살펴보면서 현재 상황을 이해할 것입니다.
솔루션의 확산에 초점을 맞추기보다는 근본적인 문제에 대해서 자세히 알아보겠습니다. 각 프레임워크는 서로 다른 해결방안과 서로 다른 장단점을 제공합니다.
결국 우리는 React, Svelte, Vue, Solid, Astro, Marko, Fresh, Next, Remix, Qwik 및 오늘날의 환경에 맞는 “메타 프레임워크”와 같은 인기 프레임워크의 상위 수준 모델을 이해할 것입니다.
현재를 이해하기 위해서 과거를 이해하는 것은 도움이 됩니다. 미래를 보기 위해 기억을 따라 과거부터 차근차근 살펴보며 시작해보겠습니다.
이전에 이야기 했지만, 이번에는 대안적인 접근 방식과 사고방식을 촉발한 더 큰 프로젝트의 문제에 초점을 맞춰보겠습니다.
웹은 함께 연결된 정적 문서로 시작되었습니다. 누군가 미리 문서를 준비하고 그것을 컴퓨터에 올려놓을 수 있었습니다.
이제 멋진 점은 다른 사람이 물리적인 위치를 이동하지 않고도 그것에 접근할 수 있다는 것입니다. 이것은 꽤 깔끔했습니다.
어느 순간, 우리는 이 문서들을 동적으로 만드는 것이 멋지겠다고 생각했습니다.
우리는 요청에 따라 다른 콘텐츠를 제공할 수 있는 CGI와 같은 기술을 얻었습니다.
그 다음 Perl과 같은 표현형 언어를 사용하여 스크립트를 작성했습니다. 이것은 명시적으로 웹을 위해 구축된 첫 번째 언어인 PHP에 영향을 미쳤습니다.
PHP의 멋진 혁신은 HTML을 백엔드 코드에 직접 연결하는 것이었습니다. 동적인 값을 포함하는 문서를 프로그래밍 방식으로 쉽게 만들 수 있도록 했습니다.
웹의 가장 중요한 혁신 중 하나는 다음과 같습니다.
<html>
<body>
이 문서는 미리 준비되어 있습니다.
</body>
</html>
동적인 값을 쉽게 포함할 수 있게 되었습니다.
<html>
<body>
Y2K?
<?php echo time(); ?>
</body>
</html>
이러한 동적인 페이지는 히트를 쳤습니다. 이제 세션을 가능하게 하는 쿠키 뿐만 아니라 사용자에게 보낸 내용을 쉽게 커스터마이즈 할 수 있게 되었습니다.
서버 기반 템플릿 프레임워크는 현재 데이터베이스와 통신하는 언어 생태계 전반에 걸쳐 등장했습니다. 이러한 프레임워크는 정적 페이지로 시작하여 동적 페이지로 쉽게 확장할 수 있도록 해주었습니다.
웹은 빠르게 진화하고 있었고, 우리는 더 많은 상호작용 경험을 원했습니다. 이를 위해 Flash와 같은 브라우저 플러그인을 활용했습니다. 이밖에 다른 경우에 우리는 백엔드에서 제공되는 HTML 위에 자바스크립트 조각을 “뿌리곤”했습니다.
jQuery
나 Prototype
과 같은 도구들은 웹 API의 다듬어지지 않은 부분들을 매끄럽게 하고, 경쟁적인 브라우저들의 단점을 보완하였습니다.
빠르고 간략하게 정리하자면, 기술 회사들은 점점 커지고 있었고, 프로젝트와 팀이 성장함에 따라 더 많은 비즈니스 로직들이 이러한 템플릿에 침투하는 것이 일반적이었습니다.
서버 코드는 데이터를 서버 템플릿 언어로 주무르기 위해 작성되고 있었습니다. 템플릿은 종종 글로벌 변수에 접근하는 비즈니스 로직의 뒤죽박죽 한 형태로 진화했습니다. SQL 주입과 같은 공격이 일상화되면서 보안 문제가 대두되고 있었습니다.
결국 우리는 “Ajax 웹 애플리케이션에 대한 새로운 접근법”을 얻었습니다.
이제 동기식 새로고침 대신 비동기식 페이지를 업데이트할 수 있게 되었습니다.
이 패턴은 Google maps나 Google docs와 같은 최초의 거대한 클라이언트 사이드 애플리케이션에 의해 대중화되었습니다.
우리는 데스크톱 스타일의 소프트웨어를 위한 웹 배포의 힘을 보기 시작했습니다. 이것은 CD 형태의 소프트웨어를 구입하는 것과 비교했을 때, 상당한 진전이었습니다.
노드가 등장했을 때, 그것이 가져온 새로운 것은 프런트엔드와 동일한 언어로 백엔드를 작성할 수 있다는 것이었습니다. 비동기 우선 모델 개발자 모두는 그것에 익숙했습니다.
노드는 (그리고 지금도)매력적이었습니다. 더 많은 기업이 온라인으로 전환되면서 경쟁 우위는 빠르게 배송하고 그것을 반복하는 것이 되었습니다.
노드의 생태계는 작업을 수행하기 위해 선반에서 가져올 수 있는 작은 단일 목적 패키지를 재사용하는 것을 강조했습니다.
데스크톱과 모바일에 필적할 수 있는 웹에 대한 우리의 욕구는 계속 커졌습니다. jQuery UI
, Dojo
, Mootools
, ExtJs
및 YUI
같은 재사용 가능한 “위젯” 라이브러리와 유틸리티의 모음이 있었습니다.
우린 이런 조각을 너무 많이 뿌리고 있었고, 프런트엔드에서는 더 많은 것을 하고 있었습니다. 이에 따라 종종 프런트엔드와 백엔드 사이에서 템플릿이 중복되는 경우가 발생했습니다.
Backbone
이나 Knockout
및 많은 다른 프레임워크들이 등장했습니다. 이들은 MVC
, MVVM
등의 아키텍처를 통해 프런트엔드의 관심사를 분리하였고, jQuery 플러그인 및 모든 위젯 들과 호환되었습니다.
구조를 추가하는 것은 프런트엔드 코드를 확장하는 데 도움이 되었습니다. 또한 백엔드로부터 템플릿 이동을 가속했습니다.
하지만 여전히 페이지를 업데이트하고 컴포넌트를 동기화하기 위해서 미세 조정된 DOM을 조작하고 있었습니다. 데이터 동기화에 관련된 버그는 자주 발생했고 이 문제는 사소하지 않았습니다.
이때, 구글의 지원을 받은 Angular가 등장하였습니다. Angular는 HTML을 동적으로 작동시켜 생산성 향상을 도모하였습니다. 그것은 스프레드시트에서 영감을 받은 반응형 시스템과 함께 양방향 데이터 바인딩을 제공하였습니다.
선언적인 양방향 바인딩은 업데이트할 때마다 발생하는 보일러 플레이트의 상당 부분을 제거했습니다. 양방향 바인딩은 좋았고, 개발자들을 더 생산적으로 만들었습니다.
하지만 규모가 커짐에 따라 무엇이 변화하고 있는지 추적하는 것이 어려워졌고, 종종 성능 저하로 이어졌습니다. 업데이트 사이클이 발생하는 곳에서 메인 스레드를 차지했습니다. (오늘날 Svelte는 단점을 완화하면서 양방향 바인딩을 유지합니다.)
모바일의 부상 외에도 이러한 생산성을 끌어올리는 프레임워크는 프런트엔드와 백엔드의 분리를 가속했습니다.
이를 통해, 프런트엔드와 백엔드의 분리를 강조하는 다양한 아키텍처를 탐색할 수 있는 길을 열었습니다.
이것은 HTML을 미리 만들어 CDN에서 서비스하는 것을 강조하는 Jamstack 철학의 주요 부분이었습니다.
그 당시, Jamstack은 정적 문서를 제공하는 것과 비슷했습니다.
그러나 이제는 Git 기반의 워크플로우, 멀리 떨어진 중앙 집중식 서버에 의존하지 않는 강력한 CDN 인프라, 분리된 프런트엔드와 통신하는 독립된 API들을 갖추고 있습니다. CDN의 정적 자산을 처킹(Chucking)하는 것은 서버를 운영하는 것보다 운영 비용이 훨씬 저렴했습니다.
오늘날 Gatsby
, Next
등 많은 다른 툴들이 이러한 아이디어를 활용합니다.
시계태엽을 돌려 우리는 빅 테크 시대를 향해 빠르게 진입했습니다. 우리는 기민하게 움직이고 판을 뒤엎기 위해 노력하였습니다.
업계에 진입하는 사람들에게 자바스크립트는 매우 중요했고, 별도의 백엔드로 지원되는 SPA를 구축하는 것이 일반적인 상황이 되었습니다.
React가 페이스북에서 탄생하게 된 몇 가지 과제는 다음과 같습니다.
React가 등장하면서 여러분이 할 수 있게 된 새로운 것은 선언적으로 프런트엔드 코드를 쓰는 것이었습니다.
MVC 프레임워크가 확장되지 않았던 프런트엔드에 대한 우려의 분리를 다시 생각하게 되었습니다.
템플릿에서 자바스크립트 기반의 JSX로 전환하는 것은 처음에는 쉽지 않았습니다. 하지만 대부분은 그렇게 했습니다.
컴포넌트 모델은 독립적인 컴포넌트들을 병렬로 보다 더 쉽게 작업할 수 있는 별도의 프런트엔드 팀을 분리할 수 있게 했습니다.
아키텍처 관점에서 컴포넌트 모델은 공유된 기본 요소(primitives)부터 페이지의 뿌리까지 구성된 “유기체(organisms)“까지 컴포넌트의 계층화를 허용했습니다.
단방향 데이터 흐름은 데이터 흐름을 이해하고 추적하고 디버그하기 쉽게 만들었습니다. 이전에는 찾아보기 힘들었던 예측 가능성이 추가되었습니다.
가상 DOM은 UI에 대한 설명을 반환하는 함수를 작성하고, React가 어려운 부분을(hard bits)를 파악하도록 할 수 있음을 의미했습니다.
이를 통해 데이터가 자주 변경될 때의 일관성 문제를 해결하고 템플릿 구성을 훨씬 더 효율적으로 만들었습니다.
시계태엽을 더 빠르게 감아보겠습니다. React는 히트했고, 업계 표준이 되었습니다. 심지어는 성능이 필요하지 않은 사이트에도 마찬가지였습니다. 규모가 커짐에 따라서 우리는 몇 가지 한계점을 보기 시작했습니다.
DOM은 React의 모델의 문제였습니다. 브라우저는 연속적인 렌더링 주기에서 DOM 노드를 지속해서 생성하고 파괴하도록 설계되지 않았습니다.
새로운 수준의 간접 참조를 도입하여 해결할 수 있는 모든 문제와 마찬가지로 React는 가상 DOM 뒤에 추상화했습니다.
매끄럽게 느껴지려면 사람들은 100ms 이하의 피드백을 인식해야 합니다. 스크롤과 같은 작업을 수행할 때는 훨씬 더 낮습니다.
이러한 최적화는 단일 스레드 환경과 결합하여 대화형 애플리케이션의 새로운 병목 현상이 되었습니다.
가상 DOM과 실제 DOM 간의 조정이 일어나는 동안 대규모의 대화형 앱은 사용자 입력에 반응하지 않게 되었습니다. Long task와 같은 용어가 등장하기 시작했습니다.
이에 따라 2017년에 동시(concurrent) 모드를 위한 기반이 포함된 React의 전체적인 재작성이 이루어졌습니다.
한편, 더 빨리 움직인다는 것은 더 많은 코드를 전송한다는 것을 의미했습니다. 브라우저들이 자바스크립트를 소화하기 위한 느린 시작 시간이 문제가 되었습니다.
우리는 HTML과 가상 DOM 뿐만 아니라 CSS를 작성하는 방법으로 모든 암묵적인 런타임 비용에 주목하기 시작했습니다.
컴포넌트 모델은 CSS에 대한 우리의 경험을 부드럽게 했습니다. 스타일을 컴포넌트와 함께 위치할 수 있게 하여 삭제 가능성을 향상했습니다. 이전에 CSS 코드를 삭제하는 것을 두려워했던 모든 사람들에게 환상적인 특성이었습니다.
우리가 다루고 있던 종속(cascade)과 그것의 특수성에 대한 문제들은 CSS in JS 라이브러리에 의해 추상화되었습니다.
이러한 라이브러리의 첫 번째 흐름은 종종 암묵적인 런타임 비용이 수반되었습니다. 컴포넌트가 렌더링 될 때까지 기다렸다가 해당 스타일을 페이지에 삽입해야 했습니다. 이에 따라 스타일링 문제가 자바스크립트 번들에 포함되었습니다.
대규모에서 저조한 성능은 종종 능지처참과 같이 끔찍하며, 우리는 이러한 비용이 발생하는 것을 인지하고 있었습니다. 이것은 이후 스타일시트를 추출하기 위해 좀 더 똑똑한 사전 컴파일러를 사용함으로 런타임 비용이 없는데 중점을 둔 새로운 CSS in JS 라이브러리로 이어졌습니다.
브라우저가 HTML을 렌더링 할 때 CSS나 스크립트와 같은 렌더링 차단 리소스는 HTML의 나머지 부분을 표시하지 못하게 했습니다.
부모는 종종 컴포넌트 계층의 자식 컴포넌트에 대한 렌더링 차단의 원인이 되었습니다. 실제로 많은 컴포넌트는 데이터베이스의 데이터와 (코드 스플리팅을 통한) CDN의 코드에 의존하고 있었습니다.
이는 종종 순차적인 네트워크 요청 차단의 워터폴로 이어집니다. 컴포넌트가 렌더링 한 후 데이터를 가져오고 비동기 하위 컴포넌트의 잠금을 해제합니다. 그다음 프로세스를 반복하여 필요한 데이터를 가져옵니다.
UI가 로드될 때 화면에 나타나는 “스피너 지옥(spinner hell)” 또는 누적 레이아웃 이동을 흔히 볼 수 있습니다.
React는 이후 Suspense
를 출시하여 페이지 로드 단계를 원활하게 진행할 수 있도록 지원했습니다. 하지만 기본적으로 순차적 네트워크 워터폴를 방지하지는 않습니다. 데이터를 가져오기 위한 Suspense는 데이터를 가져올 때 렌더링하는 패턴을 허용합니다.
우리는 React의 몇몇 트레이드오프(tradeoffs)가 어떻게 대규모로 완화되는지 이해하기 위해 계속 돌아볼 것입니다. 이것은 새로운 프레임워크에서 패턴을 프레임화 하는데 도움이 될 것입니다.
React에서는 가상 DOM의 런타임 비용을 피할 수 없었습니다. 동시(Concurrent) 모드는 상호작용 경험에서 사물의 반응성을 유지하는 것에 대한 해답이었습니다.
CSS in JS의 영역에서는 Stylex라고 불리는 내부 라이브러리가 사용되었습니다. 이것은 수천 개의 컴포넌트가 렌더링 될 때 런타임 비용 없이 효율적인 개발자 경험을 유지합니다.
페이스북은 Relay를 통해 순차적인 네트워크 워터폴 문제를 피했습니다.
주어진 시작점에 대해 정적 분석은 로드해야 하는 코드와 데이터를 정확하게 결정했습니다.
즉, 최적화된 graphQL 쿼리에서 코드와 데이터를 병렬로 로드할 수 있었습니다.
이는 초기 로딩 및 SPA 전환이 순차적 네트워크 워터폴보다 확연히 빨랐습니다.
여기서 근본적인 문제는 특정 사용자와 관련이 없는 자바스크립트를 전송하는 것이었습니다.
이것은 A/B 테스트, 기능 플래그(feature-flagged) 경험 및 특정 유형의 사용자와 집단을 위한 코드가 있을 때 어려웠습니다. 언어와 로케일(Locale) 설정도 그렇습니다.
코드의 분기가 많은 경우, 정적 의존성 그래프는 특정 사용자 집단에 대해 함께 사용되는 모듈을 확인하기 어려웠습니다.
페이스북은 AI로 구동되는 동적 번들링 시스템을 사용했습니다. 이는 긴밀한 클라이언트-서버 통합을 활용해서 런타임 요청을 기반으로 최적의 종속성 그래프를 계산했습니다.
이것은 우선순위에 따라 단계적으로 번들을 로드하는 프레임워크와 결합합니다.
페이스북은 수년간 구축된 복잡한 인프라와 자체 라이브러리를 갖추고 있었습니다. 만약 여러분이 빅 테크 기업이라면, 엄청난 양의 돈과 자원을 소비하여 이러한 장단점들을 대규모로 최적화할 수 있을 것입니다.
이것은 프런트엔드 제품 개발자가 성능을 유지하면서 작업을 완료할 수 있는 성공의 구덩이를 만듭니다.
우리 대부분은 페이스북과 같은 규모에 맞는 애플리케이션을 만들고 있지 않습니다. 여전히 많은 조직에서 성능은 주요 토픽입니다. 우리는 가능한 상위 컴포넌트에서 데이터 가져오기, 네트워크 병렬화, 인라인 요구사항등과 같은 패턴들에서 배울 수 있습니다.
빅 테크 기업들은 종종 자체 애플리케이션 프레임워크를 내부적으로 굴리고 있었고, 많은 솔루션들은 다양한 사용자 공간 및 라이브러리에 흩어져 있었습니다.
이에 따라 많은 사람들이 자바스크립트 생태계에 피로를 겪고 프레임워크 번아웃까지 이어졌습니다.
아직 우리와 함께하고 있습니까? 우리는 여전히 SPA가 기본인 시대에 있습니다. 이것은 업계에 진입하는 사람들의 현 주소입니다.
React는 논쟁의 여지가 없는 챔피언이고, 우리는 대규모의 트레이드오프를 겪고 있습니다.
React는 하나의 계층을 제공했습니다. 필요한 다른 계층을 생태계에 맡기고 모든 중요한 측면에서 변동을 야기했습니다. 라우팅, 상태 관리, 데이터 가져오기 등은 각각 고유한 개념과 API들을 가지고 있었습니다.
불변 대 가변, 클래스 기반의 OOP 대 함수형 스타일과 같은 여러 가지 토론들과 라이브러리들이 꽃을 피웠습니다.
오늘날, 많은 개발자들은 어떤 선택을 해야 하고 어떻게 설계해야 하는지에 대한 불확실성에 빠져 있습니다.
컴포넌트 모델은 여전히 확고했습니다. 그러나 런타임 비용, 자바스크립트 기반 JSX와 복잡성은 논쟁의 대상이었습니다.
빅 테크 기업으로부터 나오지 않은 많은 풀뿌리 대안들이 많은 사람에게 광범위하게 주목받았습니다. 이 대안들에 대한 매우 높은 수준의 요약을 살펴보겠습니다.
사람들이 Angular 2 또는 React로 마이그레이션 하는 것을 논의할 때, Vue는 시작하기까지 낮은 진입 장벽으로 그것들과의 차이를 메꾸었습니다.
복잡한 웹팩 구성으로 골치 아플 필요가 없었습니다. CDN을 통한 도입으로 많은 개발자가 직관적으로 사용할 수 있는 템플릿으로 컴포넌트 구축을 시작할 수 있었습니다.
라우팅 및 스타일링과 같은 핵심 컴포넌트들을 핵심 팀에서 사용할 수 있어, 의사결정의 피로를 줄일 수 있었습니다.
또한 템플릿에 정적 분석을 사용하여 더 빠른 런타임을 위한 최적화를 허용함으로써 React의 조정 알고리즘의 측면을 완화했습니다. 이것을 컴파일러 정보 가상 DOM이라고 합니다.
Svelte는 사전에 컴파일하는 접근 방식을 개척하여, 런타임에 우리가 겪는 복잡성과 오버헤드를 제거했습니다.
이 아이디어는 최소한의 바닐라 자바스크립트의 간소화된 출력으로 자체 컴파일하는 프레임워크를 갖는 것이었습니다. 익숙한 가변 스타일의 자바스크립트를 사용하는 선언적 컴포넌트를 기반으로 현대적인 개발 경험을 유지하고자 했습니다.
가상 DOM을 완전히 탈피했기 때문에, 상태 업데이트와 같은 작업을 수행하기 위해 불변 스타일의 자바스크립트를 작성하는 제약에 얽매이지 않았습니다. 많은 사람에게 이것은 웹 애플리케이션을 만드는 훨씬 더 간단하고 건전한 모델이었습니다.
Solid는 Knockout의 영감을 받아 간단하고 예측할 수 있는 반응형 모델을 제공하였습니다. React와 마찬가지로 그것은 기능의 합성이 용이하도록 템플릿을 피했습니다.
React는 끊임없이 리렌더링 하는 접근 방식을 취하는 데 반해, Solid는 한 번 렌더링 한 다음 간소화된 반응형 시스템을 사용하여 가상 DOM의 오버헤드 없이 세밀한 업데이트를 수행하는 방식을 취했습니다.
Solid는 많은 리액트 개발자들이 사용하는 hooks과 코드가 유사합니다. 그것의 API는 더 효율적이고, 세밀한 반응성과 합성할 수 있는 기본 요소들에 초점을 맞추어 hooks 종속성 배열과 같은 것들을 더 매끄럽게 처리했습니다.
이러한 각각 프레임워크에 대해 말할 것이 훨씬 더 많습니다. 각 프레임워크는 기본적인 모델과 선호도에 따라 서로 다른 장단점을 가지고 있습니다.
사실, 진화는 종종 일단 시도해보는 사람들에게서 발생합니다. 각 프레임워크가 서로 학습하면서 현재의 문제점에 대한 다양한 솔루션을 시도합니다.
큰 주제는 간소화와 단순화입니다. 런타임에서 컴파일 시간으로 옮기는 것은 이러한 주제 중 하나이고, 메모이제이션에 대한 필요성을 잠재적으로 제거하는 기능인 “React forget”에 영감을 주었습니다.
그들 모두의 공통점은 도큐먼트의 상호작용 부분을 해결하는 것이었습니다. 앞에서 살펴본 것처럼, 이것은 쉽게 확장할 수 있는 방식으로 바로잡기에는 어려운 측면이었습니다.
한편, 우리는 순수한 클라이언트 측 렌더링의 장단점을 보고 있습니다. 그것은 페이지를 로딩할 때, 비어있는 흰 화면이 더 오래 지속됩니다.
모바일 장치와 네트워크에서 흰 화면이 지속되는것은 재앙에 가깝습니다.
많은 웹사이트의 경우 저하되지 않는 빠른 성능으로 빠르게 움직이는 것이 중요한 경쟁 우위가 됩니다.
우리는 한 걸음 나아가 서버에서 먼저 콘텐츠를 렌더링함으로써 콘텐츠를 더 빨리 렌더링 하는 방법을 모색하고 있었습니다. (그러나 동시에 그것이 타협해야 하는 부분임을 알게 되었습니다.)
이 초기 단계는 많은 “메타” 프레임워크와 HTML 우선 프런트엔드 프레임워크의 새로운 물결을 위한 길을 열었습니다.
“우리는 탐험을 멈추지 않을 것입니다. 그리고 우리의 모든 탐험의 끝은 우리가 출발했던 그곳에 도착하는 것입니다. 그리고 처음으로 그곳을 알게 될 것입니다.”
PHP에서 영감을 얻은 Next는 CDN으로 푸시 되는 정적 페이지를 생성하는 프로세스를 간소화하기 위해 나섰습니다. 또한 React 앱에서 SSR을 사용하는 번거로운 부분도 원활하게 처리했습니다.
그것은 파일 기반의 라우팅을 사용하여 앱을 구성하는 것에 대해 많은 사람이 원하는 부분을 제시했습니다. 그리고 다른 많은 좋은 특징들을 가지고 있습니다.
그 이후로 “메타” 프레임워크의 물결이 만들어졌습니다. Vue의 경우, Nuxt라는 유사한 프레임워크를 가지고 있고, Svelte는 Sveltekit, Solid는 곧 출시될 SolidStart를 가지고 있습니다.
이 프레임워크들은 모든 부분을 통합하고 효율적으로 설계된 서버 우선(server-first) 프레임워크입니다. 오랫동안 주목을 받아온 것은 인터렉티브 요소뿐만이 아닙니다.
사용자 경험과 개발자 경험을 서로 손상하지 않고 개선하는 것에 대한 대화가 시작되었습니다.
멀티 페이지 아키텍처는 서버에서 HTML을 제공하며, 내비게이션이 풀 페이지 새로고침으로 일어납니다.
빠른 시작은 많은 사이트, 특히 로그인 외부 사이트에서 매우 중요합니다. 그것은 검색 순위와 이탈률과 직접적인 연관이 있습니다.
React와 같은 클라이언트 렌더링 라이브러리를 사용하는 것은 낮은 상호작용성을 가진 많은 사이트와 앱에서는 지나칩니다.
많은 사람에게 자바스크립트 우선 대신 HTML 우선, SPA 대신 MPA, 제로 자바스크립트를 기본값으로 설정과 같은 것들은 상황을 역전시키는 것을 의미합니다.
Marko, Astro, Fresh, Rocket, 그리고 Enhance와 같은 프레임워크들은 이러한 접근 방식을 사용했습니다.
일부 메타 프레임워크들과는 대조적으로, 라우터는 첫 번째 로드 후에 클라이언트로 이관되지 않고 서버에 남아있었습니다.
자바스크립트 생태계에서 이것은 노드 직후 서버 기반 템플릿으로 되돌아가는 것입니다.
이번 라운드의 MPA 이전 세대와 다릅니다. 컴포넌트 기반 모델에 작성된 스프링클은 종종 아일랜드 패턴(islands pattern)을 사용하고 있습니다. 프런트엔드 및 백엔드 코드가 동일한 언어로 제공되며, 종종 같은 파일에 있습니다.
이를 통해 일부 상호작용을 추가할 때 프런트엔드와 백엔드에 걸쳐 다르게 구성된 중복된 템플릿 코드 문제가 제거됩니다.
Remix는 React 생태계의 점진적인 개선을 가져왔습니다.
기술적인 관점에서 볼 때, 곧 출시될 다른 메타 프레임워크와 마찬가지로 엣지 호환(edge-compatible)의 런타임 React Router의 컴파일러입니다.
중첩 레이아웃과 데이터 가져오기 API를 통해 Relay로 페이스북이 대규모로 해결한 것과 같이 동일한 문제를 해결합니다.
이를 통해 코드와 데이터를 병렬로 조기에 가져올 수 있습니다. Suspense와 함께 “렌더링 할 때 가져오기(fetch as you render)” 패턴에 대한 좋은 전제 조건입니다.
점진적 향상에 중점을 둔다는 것은 그것의 API가 웹 표준을 기반으로 하며 데이터 변형 스토리는 HTML 형식을 기반으로 한다는 것을 의미합니다.
이벤트 핸들러를 연결하여 필수 가져오기 요청을 수행하는 대신, 서버에서 데이터를 처리하는 수행 기능에 데이터를 제출하는 양식을 렌더링 합니다. (종종 동일한 파일에 있습니다) 이것은 PHP에 영감을 받았습니다.
Next와 마찬가지로 애플리케이션은 전통적인 서버 렌더링 MPA처럼 자바스크립트 없이 작동하도록 축소하거나 페이지 단위로 대화형 React 앱으로 확장할 수 있습니다.
Remix 또한 낙관적인 UI 업데이트, 경합 상태 처리, 우아한 성능 저하(graceful degradation)와 같이 잘 갖춰진 프레임워크가 제공하기를 바라는 것들을 처리하기 위한 최종 사용자 경험에 초점을 맞춘 많은 API와 패턴을 제공합니다.
Quic 프로토콜과 헷갈리지 마세요. Qwik 프레임워크는 불필요한 자바스크립트를 최소화하는 것이 전부입니다.
그것의 API는 React처럼 보이지만, 그것의 접근 방식은 하이드레이션 과정을 연마함으로써 다른 메타 프레임워크와는 다릅니다.
가상 머신을 일시 중지하고 다른 물리 머신으로 이동하는 방법과 같습니다. Qwik은 이 아이디어를 서버와 브라우저 사이에서 발생하는 작업으로 가져갑니다.
이는 “재개 가능한(resumable)” 하이드레이션의 개념으로, 서버에서 무언가를 시작하고 클라이언트에서 재작업 없이 다시 시작할 수 있다는 것을 의미합니다.
이는 하이드레이션이 발생하면 따라오는 부분 하이드레이션과 대조적으로 Qwik은 애초에 그것을 피하려고 합니다.
이것은 동적 번들링과 서비스를 가능하게 하는 긴밀한 서버와 클라이언트 통합의 힘을 활용하는 것은 흥미로운 아이디어입니다.
이러한 개념은 애플리케이션이 MPA로 시작하여 동적으로 SPA로 전환할 수 있는 MPA와 SPA 사이의 경계를 흐리기 시작합니다. 때때로 (주로 유행어로) “전환 앱(transitional apps)“으로 언급됩니다.
한편 백엔드 인프라와 호스팅은 지속해서 개선되고 있습니다.
첨단에 있는 CDN은 SPA의 정적 자산을 쉽고 빠르게 제공합니다. 이제 런타임과 데이터를 엣지로 이동하는 것도 실현 가능해지고 있습니다.
이것은 브라우저 외부에 새로운 런타임 계층을 생성하지만, 여전히 사용자에게 최대한 가깝게 만듭니다.
이렇게 하면 브라우저에서 현재 수행한 많은 작업을 다시 서버로 쉽게 옮길 수 있습니다. 이를 통해 발생하는 네트워크 대기 시간의 단점을 어느 정도 완화합니다.
React 서버 컴포넌트와 같은 아이디어는 이 계층에서 브라우저로 서버 컴포넌트 출력을 스트리밍하는 개념을 탐구하고 있습니다.
Deno 및 Bun과 같은 새로운 자바스크립트 런타임은 자바스크립트 에코시스템을 단순화하고 능률화하기 위해 크롭 하고 있으며 속도와 빠른 시작 시간에 최적화된 이 엣지 실행 시간의 새로운 세계를 위해 구축되었습니다.
또한 표준 웹 API를 채택하여 이 계층에서 실행되는 애플리케이션 프레임워크로 이어졌습니다. 서버리스 기능과 스트리밍 아키텍처가 탐구되고 있습니다.
여기서 스트리밍은 큰 주제입니다. HTML을 조기에 플러시 할 수 있게 하여 브라우저는 HTML을 수신할 때 점진적으로 렌더링할 수 있습니다. 그리고 백엔드가 모든 데이터를 동시에 가져오는 동안 CSS 및 JS와 같은 렌더링 차단 리소스를 검토하기 시작합니다. 이렇게 하면 순차적인 왕복을 병렬화하는 데 도움이 됩니다.
우리는 많은 것을 살펴봤지만, 깊은 내용을 파고들지는 못했습니다.
이 포스트와 우리가 언급하지 않은 수많은 다른 것들에서 언급된 최고의 프레임워크, 아키텍처 또는 패턴이 무엇인지에 대한 보편적인 답은 없습니다.
이것들은 항상 특정 지표에 대한 교환입니다. 그리고 무엇을 얻고 포기해야 하는지 아는 것은 여러분이 무엇을 만들고 있느냐에 따라 달려있습니다. 사용자가 누구인지, 사용 패턴은 어떤지, 주요 사용자 경험과 관련된 다른 요구사항(성능)들도 중요합니다.
우리 대부분에게 진실은 중간 어디엔가 있습니다. 프레임워크와 혁신의 새로운 물결의 좋은 점은 필요에 따라 확장 및 축소할 수 있는 레버를 제공한다는 것입니다.
업계에 입문하는 사람들과 경험이 있는 사람들 모두에게 기본에 투자하는 것은 항상 좋은 베팅입니다.
프레임워크의 진화는 네이티브 웹을 서서히 더 밀어붙이며, 거친 가장자리를 부드럽게 하기 위한 프레임워크의 이전의 요구를 제거하고 이전의 단점을 완화하여 우리가 점점 더 네이티브 웹의 기능을 채택할 수 있도록 합니다.
🚀 한국어로 된 프런트엔드 아티클을 빠르게 받아보고 싶다면 Korean FE Article(https://kofearticle.substack.com/)을 구독해주세요!