← 목록으로

2026년과 이후 JavaScript의 동향 - 라이브러리와 프레임워크

2026년과 이후 JavaScript의 동향 - 라이브러리와 프레임워크

요약

4-00

"어느 한 프레임워크가 독보적인 위치를 차지하지 않는 상태는 많은 이들에게 희망과 고통을 동시에 안겨준다." 2020년 글은 이 문장으로 시작했습니다. 6년이 지난 지금, 이 문장은 절반만 맞습니다. 사용률로 보면 React는 독보적인 위치를 굳혔고, 고민은 '어떤 프레임워크를 고를까'에서 'React 위에서 어떤 메타 프레임워크와 빌드 도구를 고를까', 그리고 'AI 도구가 기본값으로 고르는 스택을 그대로 받아들일까'로 옮겨 갔습니다. 여기서 메타 프레임워크는 UI 라이브러리 위에 라우팅, 서버 렌더링(SSR), 빌드 구성을 더한 프레임워크(Next.js, Nuxt 등)를 가리킵니다.

2020년 글은 라이브러리와 프레임워크를 React, Angular 편과 Vue.js, Svelte, Stimulus 편으로 나누었지만, 이번에는 한 글로 묶었습니다. 개별 프레임워크의 기능보다 프레임워크 사이에서 함께 일어난 변화(Signals로의 수렴, 서버로의 회귀, Rust 기반 빌드 도구로의 이동, 웹 표준의 흡수, AI 도구의 영향)가 더 크게 보였기 때문입니다.

2020년 글의 마지막 부분에서는 "어떤 프레임워크든 모두 JavaScript와 웹을 기반으로 하기 때문에 프레임워크 위주로 접근하기보다는 기본적인 기술을 깊게 이해하는 접근이 필요하다"라고 썼습니다. 이 글에서도 같은 관점을 유지합니다. 6년 동안 프레임워크들은 서로 다른 이름으로 같은 문제를 풀었고, 그 문제의 상당 부분은 결국 브라우저와 언어 표준 쪽으로 넘어가고 있습니다.

이번 연재는 다음 네 편으로 구성됩니다.

이 글에서는 먼저 2020년 이후 React, Angular, Vue, Svelte, Preact의 변화를 정리합니다. 이어서 프레임워크 사이의 공통 흐름인 Signals와 메타 프레임워크, 프레임워크를 가리지 않는 도구 모음인 TanStack, 상태 관리, 빌드 도구, 테스트 도구, 웹 표준을 차례로 살펴봅니다. 마지막으로 AI 코딩 도구가 프레임워크 선택과 개발 방식에 가져온 변화를 정리합니다.

이 글의 내용은 2026년 10월을 기준으로 작성되었습니다. 글을 읽는 시점에 따라 글의 내용과 사실이 다를 수 있습니다.

2020년 이후 6년: 3(+1)대 프레임워크의 지금

2020년 글은 React, Angular, Vue를 3대 프레임워크로, Svelte를 '+1'로 놓았습니다. 당시 npm 다운로드 수로 보면 React는 Vue, Angular와 대략 4.5배 차이가 있었고, Svelte는 관심도에 비해 실제 도입은 아직 적었습니다.

6년 뒤의 숫자는 다음과 같습니다. 같은 주의 npm 주간 다운로드 수를 2020년 11월 첫 주와 2026년 10월 첫 주(9월 28일~10월 4일)로 비교했습니다.

표 1 npm 주간 다운로드 수 비교(출처: npm registry API, 패키지별 조회, 2026년 9월 28일~10월 4일)

패키지 2020년 11월 1일~7일 2026년 9월 28일~10월 4일 증가
react 8,869,607 224,422,510 약 25배
vue 1,962,540 20,397,470 약 10배
@angular/core 2,076,121 7,300,962 약 3.5배
svelte 101,464 7,724,778 약 76배

React와 Vue의 차이는 4.5배에서 약 11배로 벌어졌습니다. 다운로드 수에는 CI 환경의 반복 설치와 다른 패키지의 의존성으로 받는 경우가 섞여 있어 실사용자 수로 읽을 수는 없습니다. 다만 방향은 분명합니다. Svelte는 증가율이 가장 높아 이제 Angular와 비슷한 다운로드 수를 기록하고 있습니다.

설문 조사도 같은 경향을 보여 줍니다. State of JS 2025(전체 응답자 13,002명)에서 '사용해 본 적 있다'의 비율은 다음과 같습니다.

표 2 State of JS 프런트엔드 프레임워크 사용률과 유지 의향(출처: State of JS 2025: Front-end Frameworks)

프레임워크 2020 사용률 2025 사용률 2025 유지 의향(retention)
React 80% 85% 72%
Vue 48% 52% 84%
Angular 55% 48% 48%
Svelte 14% 27% 86%
Preact 13% 15% 81%
Solid - 10% 89%
Lit 5% 10% 67%
htmx - 9% 69%
Alpine.js 3% 9% 77%

4-01

그림 1 State of JS 프런트엔드 프레임워크 사용률 추이(2016년~2025년)(출처: State of JS 2025: Front-end Frameworks)

유지 의향은 '다시 사용하겠다'라고 답한 비율입니다. React는 사용률이 가장 높지만 유지 의향은 2020년 87%에서 2025년 72%로 내려왔고, 관심도(interest) 역시 58%에서 27%로 떨어졌습니다. 같은 조사에서 프런트엔드 프레임워크 사용 시 겪는 고충(주관식, 3,747명 응답) 1위는 '인지 부담(cognitive overload)'(1,066건), 2위는 '생태계 문제'(759건)였습니다. 특정 프레임워크의 문제보다 배우고 따라가야 할 것이 많다는 피로가 가장 큰 불만입니다. Solid는 사용률 10%에 불과하지만 5년 연속 유지 의향 1위를 기록했습니다.

4-02

그림 2 State of JS 프런트엔드 프레임워크 만족도(유지 의향) 추이(2016년~2025년)(출처: State of JS 2025: Front-end Frameworks)

설문 주최 측은 2025년 결과를 "지난 1년간 사용률 순위에 변동이 없었다"라고 요약했습니다. Alpine.js와 htmx가 자리를 바꾼 것이 유일한 변화였습니다. 평균 응답자가 경력 전체에서 사용해 본 프레임워크 수는 2.6개였습니다. 매달 프레임워크를 갈아타는 개발자의 이미지는 사실과 거리가 있습니다(참고: State of JS 2025: Front-end Frameworks).

Stack Overflow 2026 개발자 설문의 웹 프레임워크 항목(응답 10,281명)에서도 React가 41.5%로 Node.js(46.4%)에 이어 2위였고, Vue 17.2%, Angular 16.0%, Svelte 7.8% 순이었습니다. 2025년 조사(React 44.7%, Angular 18.2%, Vue 17.6%)와 비교하면 Vue와 Angular의 순서가 바뀌었습니다.

4-03

그림 3 Stack Overflow 2026 개발자 설문의 웹 프레임워크와 웹 기술 사용 비율(출처: 2026 Stack Overflow Developer Survey: Technology)

정리하면 2020년의 '3(+1)대' 구도는 'React와 나머지'로 바뀌었습니다. 다만 나머지가 정체한 것은 아닙니다. Angular, Vue, Svelte는 오히려 React보다 큰 폭으로 내부 구조를 바꾸었고, 그 방향은 서로 비슷합니다.

표 3 2020년 이후 주요 릴리스 연표

시기 React Angular Vue Svelte
2021 - v13: View Engine 제거 - -
2022 18(동시성 렌더링) - 3이 기본 버전, 2.7 SvelteKit 1.0
2023 react.dev 공개 v16: Signals, v17: @if/@for Vue 2 지원 종료 SvelteKit 2
2024 19 v19: standalone 기본 3.5 5(runes)
2025 19.2, Compiler 1.0, CRA 유지보수 모드 v21: zoneless 기본 3.6 알파, 베타 -
2026 React Foundation, 19.3 v22: Signal Forms 안정 3.6 RC SvelteKit 3

React

2020년 글은 React 17을 "새 기능보다 React 자체의 업그레이드를 쉽게 만드는 디딤돌"로 소개했습니다. 그 디딤돌 위에 올라온 것이 18과 19입니다. 18은 렌더링을 중단하고 재개할 수 있는 동시성 렌더링을, 19는 서버와 클라이언트를 하나의 컴포넌트 모델로 잇는 서버 컴포넌트와 Actions를 정식 기능으로 만들었습니다. 이후의 19.x 마이너 릴리스는 그 위에 화면 전환과 백그라운드 렌더링 같은 UI 기능을 차례로 쌓고 있습니다. 2026년 10월 기준 최신 버전은 보안 패치가 반영된 19.3.1(10월 14일)입니다(참고: npm registry: react).

공식 문서는 2023년 3월 react.dev로 옮겨 갔고, 한국어판 ko.react.dev도 함께 운영됩니다. 이 글의 React 문서 링크는 가능한 한 한국어판을 가리킵니다.

React 18: 동시성 렌더링

2022년 3월 29일 공개된 React 18의 핵심은 동시성 렌더링(concurrent rendering)입니다. 이전까지 React의 렌더링은 한 번 시작하면 끝날 때까지 멈출 수 없었습니다. 18부터 React는 여러 버전의 UI를 동시에 준비하고, 더 급한 업데이트가 들어오면 진행 중인 렌더링을 중단했다가 다시 시작할 수 있습니다.

개발자가 이 기능을 쓰는 통로는 전환(Transition) API입니다. 입력창에 글자를 입력하는 업데이트는 즉시 반영되어야 하지만, 그 입력으로 걸러진 검색 결과 목록은 조금 늦어도 됩니다. startTransition으로 감싼 업데이트는 '급하지 않은 업데이트'로 표시되어 더 급한 업데이트에 밀려날 수 있습니다.

import { startTransition } from 'react';
import { createRoot } from 'react-dom/client';

// 18부터는 ReactDOM.render() 대신 createRoot()를 사용한다.
const root = createRoot(document.getElementById('root'));
root.render(<App />);

function handleSearch(input) {
  setInputValue(input); // 급한 업데이트: 즉시 반영

  startTransition(() => {
    setResults(input); // 급하지 않은 업데이트: 중단될 수 있음
  });
}

다음 개념도는 키 입력이 연달아 들어올 때 두 방식의 차이를 보여 줍니다. 전환으로 표시한 목록 렌더링은 새 입력이 들어올 때마다 중단되고, 입력값은 바로 화면에 반영됩니다.

concept-react-transition

그림 4 전환(startTransition)이 진행 중인 렌더링을 중단하고 입력부터 반영하는 과정(개념도)

그 밖에 setTimeout과 Promise 안의 상태 업데이트도 한 번의 렌더링으로 묶는 자동 배칭(automatic batching), Suspense를 지원하는 스트리밍 서버 렌더링, 그리고 useId, useDeferredValue, 외부 상태 저장소를 동시성 렌더링과 안전하게 연결하는 useSyncExternalStore 같은 Hook이 추가되었습니다.

React 19: Actions, use, 서버 컴포넌트

2024년 12월 5일 공개된 React 19는 2023년 도입된 Canary 채널에서 프레임워크가 먼저 검증해 온 기능을 정식으로 내놓은 릴리스입니다. 2020년 글에서 소개한 릴리스 채널 체계가 이렇게 쓰이게 되었습니다.

Actions

폼 제출처럼 데이터를 변경하는 비동기 작업은 그동안 개발자가 대기 상태, 오류, 낙관적 업데이트를 직접 관리해야 했습니다. React 19는 전환 안에서 실행되는 비동기 함수를 Action이라 부르고, 이 Action의 상태를 다루는 Hook인 useActionState를 제공합니다.

import { useActionState } from 'react';

function ChangeName() {
  const [error, submitAction, isPending] = useActionState(
    async (previousState, formData) => {
      const result = await updateName(formData.get('name'));
      return result.error || null;
    },
    null,
  );

  return (
    <form action={submitAction}>
      <input type="text" name="name" />
      <button type="submit" disabled={isPending}>변경</button>
      {error && <p>{error}</p>}
    </form>
  );
}

<form>의 action 속성에 함수를 전달할 수 있게 되었고, 하위 컴포넌트에서 부모 폼의 제출 상태를 읽는 useFormStatus, 서버 응답 전에 결과를 먼저 화면에 반영하는 useOptimistic이 함께 추가되었습니다.

use

use는 렌더링 중에 Promise나 Context의 값을 읽는 API입니다. Promise가 아직 이행되지 않았다면 가장 가까운 Suspense 경계가 대체 화면을 보여 줍니다. 다른 Hook과 달리 조건문 안에서도 호출할 수 있습니다.

import { use } from 'react';

function Comments({ commentsPromise }) {
  // Promise가 이행될 때까지 Suspense 경계에서 대기한다.
  const comments = use(commentsPromise);
  return comments.map(comment => <p key={comment.id}>{comment.text}</p>);
}

서버 컴포넌트와 서버 함수

서버 컴포넌트(Server Components)는 2020년 12월 21일, 2020년 글이 발행된 직후 제로 번들 사이즈 React 서버 컴포넌트라는 이름으로 처음 공개되었습니다. 서버에서만 실행되어 클라이언트 번들에 포함되지 않는 컴포넌트이며, 데이터베이스나 파일 시스템에 직접 접근할 수 있습니다. 4년의 실험을 거쳐 React 19에서 안정 기능이 되었습니다. 'use server' 지시어를 붙인 서버 함수(Server Functions)는 클라이언트에서 호출할 수 있는 서버 측 함수로, 앞의 Actions와 결합해 폼 제출을 서버까지 이어 줍니다.

다음 개념도는 한 페이지 안에서 서버 컴포넌트와 클라이언트 컴포넌트가 나뉘는 방식을 보여 줍니다. 서버 컴포넌트의 코드는 브라우저로 가지 않고, 'use client'로 표시한 컴포넌트만 번들에 들어가 하이드레이션됩니다. 하이드레이션은 서버에서 렌더링한 HTML에 클라이언트 JavaScript가 이벤트 처리와 상태를 연결하는 과정입니다.

concept-rsc-boundary

그림 5 서버 컴포넌트와 'use client' 컴포넌트가 실행되는 위치와 브라우저 번들에 포함되는 코드(개념도)

서버 컴포넌트는 React 단독으로는 쓸 수 없고, 번들러와 라우터를 함께 제공하는 프레임워크가 필요합니다. React 팀이 프레임워크 사용을 권장하는 방향으로 돌아선 배경이 여기에 있습니다. 서버 컴포넌트를 안정적으로 지원하는 프레임워크가 아직 Next.js에 집중되어 있다는 점은 뒤의 'React와 Next.js의 관계' 절에서 다룹니다.

실행 영역이 서버로 넓어진 만큼 위험도 커졌습니다. 2025년 12월 3일 공지된 CVE-2025-55182(CVSS 10.0)는 서버 함수 페이로드의 역직렬화 결함으로 인증 없이 원격 코드를 실행할 수 있는 취약점이었고, 취약한 버전의 react-server-dom-webpack, react-server-dom-parcel, react-server-dom-turbopack을 사용하는 서버 환경이 영향을 받았습니다. 서버 함수 엔드포인트를 직접 구현하지 않았더라도 서버 컴포넌트를 지원하는 서버 환경이라면 취약할 수 있었습니다. 2026년 10월 14일에는 같은 패키지에서 원격 코드 실행이 가능한 치명적(critical) 취약점이 다시 공개되었습니다(뒤의 'React와 Next.js의 관계' 절 참고). 프런트엔드 라이브러리의 보안 공지도 백엔드 프레임워크의 공지만큼 무겁게 다뤄야 하는 대상이 되었습니다.

그 외의 변화

함수 컴포넌트가 ref를 일반 prop으로 받게 되어 forwardRef가 필요 없어졌고, <ThemeContext.Provider> 대신 <ThemeContext>를 쓸 수 있게 되었습니다. 컴포넌트 안에서 렌더링한 <title>, <meta>는 <head>로 옮겨지며, preload, preinit 같은 리소스 사전 로딩 API도 추가되었습니다.

2020년 글에서 다룬 React 17의 '새로운 JSX Transform'이 React import 없이 JSX를 쓰게 만든 변화였다면, 19의 이 변화들은 forwardRef, Context.Provider처럼 React만의 개념을 걷어 내는 방향입니다.

React 19.2와 19.3: Activity, useEffectEvent, View Transitions

2025년 4월 React Labs 글에서 예고한 기능들이 이후 마이너 릴리스로 차례로 들어왔습니다.

React 19.2(2025년 10월 1일)는 다음 기능을 정식으로 추가했습니다.

  • <Activity>: 화면에서 숨긴 영역의 상태를 유지한 채 낮은 우선순위로 미리 렌더링합니다. 사용자가 이동할 가능성이 높은 화면을 미리 준비해 두는 데 씁니다.
  • useEffectEvent: Effect 안에서 쓰지만 의존성 배열에 넣고 싶지 않은 '이벤트' 성격의 로직을 분리합니다. 의존성 배열을 둘러싼 오래된 혼란을 줄이기 위한 Hook입니다.
  • cacheSignal: 서버 컴포넌트의 cache() 수명이 끝났음을 AbortSignal로 알립니다.
  • 성능 트랙(Performance Tracks): Chrome DevTools의 성능 패널에 React 전용 트랙을 추가해 스케줄러와 컴포넌트 렌더링 시점을 보여 줍니다.
  • 부분 사전 렌더링(Partial Pre-rendering): 정적인 부분을 미리 렌더링하고 동적인 부분은 나중에 이어서(resume) 렌더링합니다.

4-04

그림 6 Chrome DevTools 성능 패널에 표시된 React의 Scheduler 트랙과 Components 트랙(출처: React 19.2)

import { Activity, useEffect, useEffectEvent } from 'react';

function Tabs({ tab }) {
  return (
    <>
      {/* 숨겨진 탭도 상태를 유지하며 백그라운드에서 렌더링된다. */}
      <Activity mode={tab === 'home' ? 'visible' : 'hidden'}>
        <Home />
      </Activity>
      <Activity mode={tab === 'posts' ? 'visible' : 'hidden'}>
        <Posts />
      </Activity>
    </>
  );
}

function ChatRoom({ roomId, theme }) {
  // theme은 의존성에 넣지 않는다. theme이 바뀌어도 다시 연결하지 않는다.
  const => showNotification('연결됨', theme));

  useEffect(() => {
    const connection = createConnection(roomId);
    connection.on('connected', () => onConnected());
    connection.connect();
    return () => connection.disconnect();
  }, [roomId]);
}

React 19.3(2026년 9월 9일)에서는 <ViewTransition>이 안정 기능이 되었습니다(2026년 10월 기준 React 19.3 발표문의 한국어판은 아직 없습니다). 브라우저의 View Transition API를 React의 전환과 연결해, 전환으로 표시된 업데이트가 일어나면 요소의 등장, 퇴장, 이동을 애니메이션으로 처리합니다. addTransitionType으로 전환의 원인(다음 슬라이드, 이전 슬라이드 등)에 따라 다른 애니메이션을 지정할 수 있습니다.

startTransition(() => {
  addTransitionType('next');
  setCurrentSlide(c => c + 1);
});

<ViewTransition enter={{ next: 'from-right' }} exit={{ next: 'to-left' }}>
  <Page />
</ViewTransition>

같은 릴리스에서 <Fragment>에 ref를 전달하는 Fragment Refs가 안정화되었고, 브라우저에서만 렌더링할 컴포넌트를 표시하는 react-dom의 browser() 함수, Trusted Types 지원이 추가되었습니다. 브라우저 표준 API(View Transition, Trusted Types)를 React의 모델로 감싸는 작업이 최근 릴리스의 주된 방향입니다. 이 흐름은 뒤의 '웹 표준이 라이브러리를 대체하는 흐름' 절에서 다시 다룹니다.

React Compiler 1.0

React의 렌더링 성능 최적화는 오랫동안 개발자의 몫이었습니다. 불필요한 재렌더링을 막으려면 useMemo, useCallback, React.memo로 값과 함수를 직접 메모이제이션해야 했고, 의존성 배열을 잘못 쓰면 오래된 값이 남는 버그가 생겼습니다.

2025년 10월 7일 정식 출시된 React Compiler 1.0은 이 작업을 빌드 시점으로 옮긴 도구입니다. 컴포넌트와 Hook의 코드를 분석해 필요한 곳에 자동으로 메모이제이션을 넣습니다. 코드를 다시 작성할 필요는 없습니다.

// 컴파일러가 있으면 이렇게만 작성한다.
function TodoList({ todos, filter }) {
  const visible = todos.filter(t => t.status === filter);
  return <List items={visible} => select(id)} />;
}

// 컴파일러가 없을 때 같은 효과를 내려면 useMemo, useCallback이 필요했다.
const visible = useMemo(() => todos.filter(t => t.status === filter), [todos, filter]);
const => select(id), []);

Meta는 가상 현실(VR) 기기용 앱 스토어인 Quest Store에 적용한 결과 초기 로딩과 페이지 이동이 최대 12% 빨라졌고 일부 상호작용은 2.5배 이상 빨라졌으며, 메모리 사용량은 변하지 않았다고 밝혔습니다. React 17 이상에서 쓸 수 있고(17, 18에서는 react-compiler-runtime 패키지가 필요합니다), Expo SDK 54부터는 새 앱에 기본으로 켜져 있습니다(참고: React Compiler v1.0).

2020년 글에서 Angular Ivy를 다루며 "컴파일러가 생성한 코드 자체가 렌더링 엔진의 역할을 한다"라고 설명했습니다. 런타임 라이브러리로 출발한 React도 이제 컴파일러를 공식 도구로 갖게 되었습니다. Babel 플러그인으로 출발한 탓에 빌드 속도가 과제로 남아 있고, 컴파일러를 Rust로 옮기는 작업이 Next.js와 Oxc 양쪽에서 진행되고 있습니다. Oxc 쪽의 결과는 뒤의 '빌드 도구' 절에서 다룹니다.

React Foundation과 Create React App의 유지보수 모드 전환

React를 둘러싼 운영 구조에도 큰 변화가 있었습니다.

2025년 10월 React Conf에서 React Foundation 설립이 발표되었고, 2026년 2월 24일 Linux Foundation 산하 재단으로 공식 출범했습니다. React, React Native, JSX의 소유권이 Meta에서 재단으로 넘어갔습니다. 플래티넘 회원은 Amazon, Callstack, Expo, Huawei, Meta, Microsoft, Software Mansion, Vercel 여덟 곳입니다. 재단 이사회와 별개로 기술 방향은 기존 기여자와 메인테이너가 결정하며, 이를 위한 임시 리더십 위원회가 구성되었습니다. 2011년 Facebook 광고팀의 실험 프로젝트로 출발한 React가 15년 만에 한 회사의 프로젝트에서 벗어났습니다(참고: FaxJs, 2020년과 이후 JavaScript의 동향 - 라이브러리와 프레임워크 1).

도구 측면의 변화는 Create React App 지원 종료입니다. 2025년 2월 14일 React 팀은 CRA(Create React App)를 비권장(deprecated)으로 지정하고 유지보수 모드로 전환했습니다. 새 앱은 프레임워크(Next.js, React Router, Expo)로 시작하라고 권장했습니다. 프레임워크 없이 쓰려면 Vite, Parcel, Rsbuild(Rspack 기반 빌드 도구) 같은 빌드 도구를 쓰라고 안내했습니다. CRA로는 라우팅, 데이터 가져오기, 코드 분할 같은 실서비스의 문제를 풀기 어렵다는 이유였습니다. 2020년 글에서 React 17의 점진적 업그레이드 데모가 "CRA로 작성된 데모"였다는 점을 떠올리면, 6년 사이 React를 시작하는 기본 경로가 완전히 바뀌었습니다.

Recoil의 결말

2020년 글은 Facebook이 공개한 상태 관리 라이브러리 Recoil을 Atom과 Selector 중심으로 자세히 소개했고, DEVIEW 2020의 "Recoil: 왕위를 계승하는 중입니다" 세션도 함께 소개했습니다. 결과적으로 Recoil은 왕위를 계승하지 못했습니다. Recoil 저장소는 2025년 1월 1일 아카이브되어 읽기 전용이 되었습니다. 정식 1.0은 끝내 나오지 않았습니다.

Recoil이 제시한 "React 트리와 별도의 차원에 원자 단위 상태를 두고 컴포넌트와 연결한다"라는 아이디어 자체는 살아남았습니다. 같은 개념은 Jotai 같은 라이브러리로 이어졌고, 더 크게 보면 뒤에서 다룰 Signals가 프레임워크 차원에서 같은 문제를 풀고 있습니다. React 18의 useSyncExternalStore가 외부 상태 저장소를 동시성 렌더링과 안전하게 연결하는 공식 통로를 열면서, 상태 관리의 중심은 React 내부 API에 기대는 대형 라이브러리보다 작은 외부 저장소 쪽으로 옮겨 간 것으로 보입니다.

Angular

2020년 글은 Angular의 Ivy 렌더러를 비중 있게 다루며 "모든 내부 도구가 Ivy로 전환되면 레거시 View Engine을 제거하는 것"을 차기 목표로 소개했습니다. 이 목표는 2021년 11월 4일 Angular v13에서 이루어졌습니다. v13부터 View Engine은 사용할 수 없고, Angular는 Ivy 전용이 되었습니다.

Ivy 위에서 Angular 팀은 이후 5년 동안 프레임워크의 기본 구성을 거의 모두 바꾸었습니다. NgModule 대신 standalone 컴포넌트, Zone.js 기반 변경 감지 대신 Signals, 구조 지시자 대신 내장 제어 흐름, webpack 대신 esbuild와 Vite가 기본값이 되었습니다. Angular 팀은 이 시기를 스스로 'Angular 르네상스'라고 불렀습니다. v17과 함께 새 문서 사이트 angular.dev가 베타로 공개되었고, 이후 기본 문서 사이트가 되었습니다. 2026년 10월 기준 최신 메이저 버전은 2026년 6월 3일 출시된 v22이며, v20부터 v22까지가 지원 대상입니다. 이 중 v20의 지원은 2026년 11월 28일에 끝납니다(참고: Versioning and releases).

4-05

그림 7 Angular 지원 버전과 지원 종료 일정(2026년 10월 기준)(출처: Versioning and releases)

standalone 컴포넌트

Angular 애플리케이션은 오랫동안 NgModule이라는 별도의 모듈 단위로 컴포넌트를 묶어야 했습니다. Angular 팀은 standalone이 Angular를 배우고 시작하기 쉽게 만든다고 설명합니다. v14에서 NgModule 없이 쓰는 standalone 컴포넌트가 개발자 미리보기로 도입되었고, v17에서 ng generate가 생성하는 기본 형태가 되었으며, v19부터는 standalone: true가 기본값입니다(참고: The future is standalone!). standalone 컴포넌트는 필요한 의존성을 imports로 직접 가져옵니다. NgModule도 계속 지원됩니다.

Signals와 내장 제어 흐름

v16(2023년 5월 3일)은 Signals 기반의 새 반응성 모델을 개발자 미리보기로 도입했고, v17에서 signal과 computed가, v20에서 effect가 안정화되었습니다. 2020년 글에서 설명한 Angular의 변경 감지는 이벤트가 일어나면 Zone.js가 이를 가로채 컴포넌트 트리 전체의 바인딩을 다시 검사(dirty-checking)하는 방식이었습니다. Signals는 어떤 값이 어떤 템플릿에서 읽히는지 추적하므로, 값이 바뀐 곳만 갱신할 수 있습니다.

import { Component, signal, computed, effect } from '@angular/core';

@Component({
  selector: 'app-counter',
  template: '{{ count() }} x 2 = {{ double() }}',
})
export class CounterComponent {
  readonly count = signal(0);
  readonly double = computed(() => this.count() * 2);

  constructor() {
    // 컴포넌트 생성자는 effect()에 필요한 주입 컨텍스트(injection context)를 제공한다.
    effect(() => console.log(`count: ${this.count()}, double: ${this.double()}`));

    this.count.set(1);
    this.count.update(v => v + 1);
  }
}

이 예시에서 최종 값은 count가 2, double이 4입니다. effect()는 변경 감지 과정에서 실행되므로, 각 set()과 update() 직후에 로그가 하나씩 출력되는 것은 아닙니다(참고: Angular: Effects). 주입 컨텍스트는 inject()로 의존성을 가져올 수 있는 실행 구간이며, 생성자와 필드 초기화가 여기에 해당합니다.

같은 v17(2023년 11월 8일)에서는 템플릿 문법도 바뀌었습니다. *ngIf, *ngFor, *ngSwitch 대신 @if, @for, @switch 블록을 쓰는 내장 제어 흐름(built-in control flow)이 도입되었습니다. @for는 track 식을 필수로 요구하고 새로운 비교 알고리즘을 써서, 공개 벤치마크에서 *ngFor보다 최대 90% 빠른 런타임을 기록했습니다. 같은 블록 문법으로 컴포넌트를 지연 로딩하는 @defer도 추가되었습니다.

4-06

그림 8 공개 벤치마크에서 내장 제어 흐름(angular-cf)과 *ngFor(angular-ngfor)의 작업별 소요 시간 비교(출처: Introducing Angular v17)

@if (user.isLoggedIn) {
  <p>환영합니다, {{ user.name }}</p>
} @else {
  <p>로그인이 필요합니다.</p>
}

@for (item of items; track item.id) {
  <li>{{ item.title }}</li>
} @empty {
  <li>항목이 없습니다.</li>
}

@defer (on viewport) {
  <comment-list />
}

4-07

그림 9 @defer로 화면에 보일 때 하위 트리를 지연 로딩하는 컴포넌트 트리(출처: Introducing Angular v17)

새 제어 흐름은 Ivy 컴파일러가 직접 처리하는 문법이라 별도의 import가 필요 없고, ng generate @angular/core:control-flow로 기존 템플릿을 자동 변환할 수 있습니다.

Zone.js 없는 Angular

Signals가 변경 감지를 대신할 수 있게 되면서 Zone.js는 필수가 아니게 되었습니다. Zone.js 없는(zoneless) 변경 감지는 v18에서 실험 기능, v20에서 개발자 미리보기를 거쳐 v20.2에서 안정화되었고, v21(2025년 11월 19일)부터 새 애플리케이션에는 Zone.js가 기본으로 포함되지 않습니다. Angular 팀에 따르면 2024년 Google 내부에서 새로 만든 Angular 앱의 절반 이상이 이미 zoneless였고, HTTP Archive에서도 1,400개 이상의 공개 Angular 앱이 zoneless로 확인되었습니다.

같은 v21에서 Karma를 대신해 Vitest가 기본 테스트 러너가 되었고, Signals 기반의 새 폼 API인 Signal Forms가 실험 기능으로, 스타일이 없는 접근성 컴포넌트 라이브러리 Angular Aria가 개발자 미리보기로 공개되었습니다(참고: Announcing Angular v21).

Angular v22

2026년 6월 3일 공개된 Angular v22는 v21에서 미리 공개한 기능을 안정화하는 데 초점을 두었습니다.

  • Signal Forms, Angular Aria, 비동기 반응성 API(resource, httpResource)가 안정 기능이 되었습니다.
  • 새 애플리케이션의 기본 변경 감지 전략이 OnPush(입력값이 바뀌거나, 컴포넌트에서 이벤트가 일어나거나, 템플릿이 읽는 시그널이 바뀔 때만 다시 검사하는 전략)가 되었고, 기존 기본값 ChangeDetectionStrategy.Default는 Eager(변경 감지가 실행될 때마다 항상 검사하는 전략)로 이름이 바뀌었습니다.
  • @Service 데코레이터, 서비스를 지연 로딩하는 injectAsync, 템플릿 안의 화살표 함수와 전개(spread) 문법이 추가되었습니다.
  • webpack 기반 빌더(@angular-devkit/build-angular, @ngtools/webpack)가 비권장으로 지정되었습니다.

2020년 글은 Angular를 "프레임워크 자체만으로 온전한 애플리케이션을 만들 수 있다"라는 점에서 다른 프레임워크와 구별했습니다. 이 성격은 유지되었지만, 내부는 함수형 API, 세밀한 반응성, Vite 기반 빌드처럼 다른 프레임워크와 겹치는 부분이 많아졌습니다. 사용률은 내려갔지만(표 2), Angular는 지난 6년간 기본 구성을 가장 넓게 바꾼 메이저 프레임워크 중 하나입니다.

Vue

2020년 글은 9월에 공개된 Vue 3 One Piece와 Composition API를 다루며, npm에서 Vue를 설치하면 아직 2.x가 내려온다고 설명했습니다. 2022년 1월 Vue 3가 기본 버전이 되었고, Vue 2는 2.7 Naruto를 마지막 마이너로 2023년 12월 31일 지원이 종료(end-of-life)되었습니다. 지원 종료 후의 보안 패치는 HeroDevs의 유료 연장 지원(Vue 2 NES)으로 넘어갔습니다.

2020년 글에서 실험 기능으로 소개한 <script setup>은 이제 Composition API로 단일 파일 컴포넌트를 작성할 때 권장하는 방식이 되었습니다(참고: Vue.js: script setup).

Vue 3.5

Vue 3.5(2024년 9월 1일)는 반응성 시스템을 다시 손봐 메모리 사용량을 56% 줄이고, 크고 깊은 반응형 배열의 반응성 추적을 일부 경우 최대 10배 빠르게 했습니다. props 구조 분해(Reactive Props Destructure)가 안정화되었고, useTemplateRef, useId, 지연 하이드레이션(lazy hydration) 같은 API가 추가되었습니다.

// 구조 분해한 props도 반응성을 유지하고, 기본값은 JavaScript 문법으로 지정한다.
const { count = 0, msg = 'hello' } = defineProps<{ count?: number; msg?: string }>()

4-08

그림 10 구조 분해한 props를 편집기가 props.foo로 표시하는 인레이 힌트(출처: Announcing Vue 3.5)

Vue 3.6과 Vapor Mode

2020년 글은 Vue 3의 컴파일러가 템플릿을 분석해 "블럭"과 패치 플래그 같은 힌트를 만들고, 런타임이 이 힌트로 VDOM(가상 DOM) 비교를 줄인다고 설명했습니다. Vapor Mode는 이 방향을 끝까지 밀고 나가 VDOM 자체를 없앱니다. 템플릿을 DOM을 직접 생성하고 갱신하는 코드로 컴파일하는 방식으로, 2020년 글에서 소개한 Svelte, 그리고 Solid의 접근과 같습니다.

2025년 12월 23일 공개된 Vue 3.6.0-beta.1에서 Vapor Mode는 기능 구현을 마쳤고, Vue 팀은 서드파티 벤치마크에서 Solid, Svelte 5와 같은 수준의 성능을 보인다고 밝혔습니다. 같은 릴리스에서 @vue/reactivity는 alien-signals 기반으로 다시 작성되었습니다. Vapor Mode는 컴포넌트 단위로 선택합니다.

<script setup vapor>
import { ref } from 'vue'
const count = ref(0)
</script>

<template>
  <button @click="count++">{{ count }}</button>
</template>

Vapor 컴포넌트만으로 앱을 만들면(createVaporApp) 런타임이 가장 작아지고, 기존 VDOM 앱 안에 섞어 쓸 수도 있습니다(vaporInteropPlugin). Options API와 getCurrentInstance() 등은 지원하지 않으며, Vue 팀은 성능이 중요한 일부 화면이나 작은 신규 프로젝트에 먼저 적용하라고 권합니다. 2026년 10월 기준 3.6은 RC(출시 후보) 12번째 버전까지 나왔고, 최신 안정 버전은 3.5.44입니다.

Nuxt와 Vite

Vue 생태계의 메타 프레임워크인 Nuxt는 Nuxt 4(2025년 7월 15일)에서 애플리케이션 코드를 app/ 디렉터리로 옮기고 데이터 가져오기 API를 정리했습니다. 2026년 7월의 4.5는 Vite 8과 Rspack 2를 지원합니다. 운영 측면에서는 Nuxt와 Nitro(Nuxt의 서버 엔진) 개발을 지원하던 NuxtLabs가 2025년 7월 Vercel에 합류했습니다. MIT 라이선스와 공개 로드맵은 유지됩니다.

Vue가 생태계 전체에 남긴 가장 큰 영향은 Vue 자체보다 Vite일 수 있습니다. Evan You가 Vue를 위해 만든 Vite는 이제 React Router, Astro, Angular, SvelteKit이 기반으로 쓰는 공통 빌드 도구가 되었습니다. Vue 공식 문서도 create-vue와 Vite로 시작하라고 안내하며, Vue CLI는 유지보수 모드입니다. 이 내용은 '빌드 도구' 절에서 다시 다룹니다.

Svelte

2020년 글은 Svelte를 "관심도에 비해 실제 도입에 대한 온도 차가 존재한다"라고 평가했습니다. 6년 뒤 State of JS 사용률은 14%에서 27%로, npm 주간 다운로드는 약 10만에서 약 772만으로 늘었습니다(표 1, 표 2). 유지 의향은 86%로 여전히 높습니다.

Svelte 5와 룬

2024년 10월 22일 공개된 Svelte 5는 프레임워크를 처음부터 다시 쓴 릴리스입니다. Svelte 3, 4는 컴포넌트 최상위의 let 변수 할당을 컴파일러가 반응성으로 바꾸어 주었습니다. 이 방식은 간결했지만 컴포넌트 밖이나 .js 파일에서는 같은 규칙을 쓸 수 없었고, 무엇이 반응형인지 코드만 보고 알기 어려웠습니다.

Svelte 5는 룬(runes)이라 부르는 $로 시작하는 컴파일러 키워드로 반응성을 명시합니다. 내부는 Signals 기반의 세밀한 반응성으로 바뀌었습니다. $state, $derived, $effect, $props, $bindable, $inspect, $host가 있고, import 없이 씁니다(참고: Svelte: What are runes?).

<script>
  let { step = 1 } = $props();
  let count = $state(0);
  let doubled = $derived(count * 2);

  $effect(() => {
    console.log(`count: ${count}`);
  });
</script>

<button => (count += step)}>
  {count} x 2 = {doubled}
</button>

이벤트 핸들러는 on:click 지시어 대신 onclick 같은 일반 prop이 되었고, slot은 {#snippet} 블록으로 대체되었습니다. 기존 Svelte 4 문법도 대부분 그대로 동작하며, npx sv migrate svelte-5로 자동 변환할 수 있습니다. React의 Hooks, Vue의 Composition API처럼, Svelte도 '마법 같은 암묵적 반응성'에서 '명시적인 반응성 단위'로 옮겨 갔습니다.

SvelteKit 2와 3

2020년 글이 '가제'로 소개했던 SvelteKit은 2022년 1.0을 거쳐 2023년 12월 14일 SvelteKit 2가 되었습니다. 2020년 글은 SvelteKit이 개발 서버로 Snowpack(현재는 유지보수가 중단되어 Vite를 권장합니다)을 쓴다고 설명했는데, 정식 버전의 SvelteKit은 Vite 기반이며 SvelteKit 2도 Vite 5 지원을 주요 변경으로 내세웠습니다. 2025년에는 서버 함수를 타입 안전하게 호출하는 원격 함수(remote functions)가 실험 기능으로 제공되며 매달 개선되었습니다.

2026년 8월 13일 SvelteKit 3 RC가 공개되었고, 10월 1일 SvelteKit 3이 정식 출시되었습니다. 설정이 svelte.config.js에서 vite.config.ts로 옮겨 갔고, $lib 별칭 대신 Node.js 표준인 #lib 서브패스 import를 쓰며, Vite 8이 필수입니다. 원격 함수는 여전히 실험 기능이며, 쓰려면 실험 플래그로 켜는 Async Svelte가 필요합니다.

2020년 글이 짚었던 SvelteKit의 어댑터 방식은 이후 다른 메타 프레임워크에도 퍼졌습니다. Next.js도 2026년 Adapter API를 안정화했습니다.

Preact

State of JS 2025에서 Preact는 React, Vue, Angular, Svelte에 이어 사용률 5위(15%)이고 유지 의향은 81%입니다. 2020년 사용률 13%에서 크게 오르지는 않았지만, 설문 주최 측은 2025년에 관심도가 오른 프레임워크로 Solid와 Preact 두 개만 꼽았습니다. npm 주간 다운로드는 2020년 11월 첫 주 약 44만에서 2026년 10월 첫 주 약 4,452만으로 늘었습니다(참고: npm registry API). 다른 패키지의 의존성으로 설치되는 경우가 많이 섞인 수치입니다.

Preact는 React와 같은 API를 3KB 안팎의 크기로 제공하는 것을 목표로 하는 라이브러리입니다. 2019년 10월의 Preact X(10.x) 이후 7년 가까이 메이저 버전이 바뀌지 않다가, 2025년 8월 베타를 거쳐 2026년 9월 30일 Preact 11이 정식 출시되었습니다. 업그레이드 가이드에 정리된 주요 변화는 다음과 같습니다.

  • ESM 전용 배포: 코어와 부가 패키지를 .mjs 확장자의 ESM(ECMAScript modules)으로만 배포하고 CommonJS, UMD 번들은 제공하지 않습니다. 폴리필 없이 지원하는 브라우저는 Chrome 71, Safari 12.1, Firefox 69, Edge 79 이상이며 IE11 지원은 끝났습니다.
  • Hydration 2.0: 컴포넌트가 DOM 노드를 하나도 반환하지 않거나 여러 개 반환해도 하이드레이션할 수 있습니다. 스트리밍 서버 렌더링 결과에 남긴 주석 표식을 기준으로 하이드레이션을 이어 갑니다.
  • prop으로 전달되는 ref: 함수 컴포넌트에서 forwardRef 없이 ref를 일반 prop처럼 받습니다. React 19와 같은 방향입니다.
  • React와 맞춘 동작: Hook 의존성 비교에 Object.is를 쓰고, useEffect의 정리 함수를 화면을 그린 뒤에 실행합니다. createPortal은 코어로 옮겨졌고, 숫자 스타일 값에 px를 자동으로 붙이는 동작과 defaultProps는 preact/compat으로 옮겨졌습니다.
// Preact 11에서는 forwardRef 없이 ref를 prop으로 받는다.
function TextInput({ ref, ...props }) {
  return <input ref={ref} {...props} />;
}

출시 발표문에 따르면 팀은 몇 년간 미뤄 둔 호환성이 깨지는 변경을 이번 버전에 한꺼번에 반영했습니다. 다만 대부분은 타입 정의 변경이라 업그레이드할 때 손볼 코드가 많지 않다고 설명합니다. @preact/signals, preact-render-to-string, preact-iso, prefresh, @preact/preset-vite 같은 공식 패키지는 출시 시점에 이미 Preact 11을 지원합니다.

Preact가 React와 다른 길을 가는 지점은 반응성입니다. 뒤의 'Signals로의 수렴' 절에서 다루는 Preact Signals는 2022년 9월 공개된 뒤 React에서도 쓸 수 있는 프레임워크 독립 패키지로 자리 잡았습니다. '메타 프레임워크와 서버로의 회귀' 절에서 다루는 Remix 3도 Preact를 포크해 자체 컴포넌트 모델을 만들었습니다. React 호환 API와 작은 크기라는 Preact의 특성이 다른 프레임워크의 출발점으로도 쓰이고 있습니다.

Signals로의 수렴

앞의 절들을 나란히 놓으면 공통점이 보입니다. Angular는 Zone.js 대신 Signals를, Svelte 5는 룬이라는 이름의 Signals를, Vue 3.6은 alien-signals 기반의 반응성 시스템과 VDOM 없는 Vapor Mode를 택했습니다. 2020년 글이 VDOM과 Incremental DOM의 차이를 설명하는 데 많은 지면을 썼다면, 2026년의 질문은 '값 하나가 바뀌었을 때 어디까지 다시 계산하는가'로 바뀌었습니다.

시그널(signal)은 값을 담는 반응형 단위입니다. 값을 읽는 쪽(파생 값, 효과, 템플릿)이 자동으로 의존성으로 기록되고, 값이 바뀌면 그 값을 읽은 곳만 다시 실행됩니다. 컴포넌트 함수 전체를 다시 실행한 뒤 결과를 비교하는 React의 모델과 다릅니다.

다음 개념도는 장바구니 수량 하나가 바뀔 때 두 모델이 다시 계산하는 범위를 비교합니다. 두 방식 모두 실제로 고치는 DOM은 한 곳이지만, 그 한 곳을 찾는 방법이 다릅니다.

concept-signals-update

그림 11 값 하나가 바뀔 때 컴포넌트 재실행 방식과 Signals 방식이 다시 계산하는 범위(개념도)

Solid와 Preact Signals

이 흐름을 대중화한 프레임워크는 Solid입니다. State of JS 2025는 Solid를 "5년 연속 만족도 1위"로 소개하며, 창시자 Ryan Carniato가 Signals 개념을 널리 알리는 데 큰 역할을 했다고 평가했습니다. 2026년 10월 기준 Solid 2.0은 15번째 RC까지 나왔으며, 반응성 코어가 @solidjs/signals 패키지로 분리되었습니다. 메타 프레임워크 SolidStart가 맡던 기능도 2.0에서 코어와 Vite 플러그인으로 옮겨 갔습니다(뒤의 'SolidStart의 은퇴' 절 참고).

Preact Signals는 signal, computed, effect 세 가지 API로 된 프레임워크 독립 코어(@preact/signals-core)와 Preact, React용 연결 패키지를 제공합니다.

TC39 Signals 제안

프레임워크마다 비슷한 기능을 따로 구현하는 상황을 언어 표준으로 풀려는 시도가 TC39 Signals 제안입니다. 2024년 4월 Stage 1이 되었고, 초안은 Angular, Ember, MobX, Preact, Qwik, RxJS, Solid, Svelte, Vue 등의 작성자와 메인테이너 의견을 바탕으로 만들어졌습니다. 목표는 프레임워크가 공통의 반응성 코어 위에서 동작하고, 서로 다른 프레임워크의 상태가 함께 쓰일 수 있게 하는 데 있습니다.

const counter = new Signal.State(0);
const isEven = new Signal.Computed(() => (counter.get() & 1) === 0);

// 프레임워크가 렌더링 예약에 사용할 저수준 API
const watcher = new Signal.subtle.Watcher(() => {
  queueMicrotask(render);
});

function render() {
  // 의존성은 Computed(isEven)가 추적한다. 여기서는 값을 읽어 다시 계산하고, watch()를 다시 호출해 다음 알림을 받는다.
  console.log(`짝수인가: ${isEven.get()}`);
  watcher.watch();
}

watcher.watch(isEven);
render(); // 최초 평가로 counter에 대한 의존성을 만든다.
counter.set(counter.get() + 1);

진행은 신중합니다. TC39 제안 목록 기준 마지막 회의 발표는 2024년 6월이고, 2026년 10월 현재도 Stage 1입니다. 챔피언들은 Stage 2로 가기 전에 성능이 검증된 여러 폴리필 구현과 실제 프레임워크 통합 사례를 먼저 확보하겠다고 밝혔습니다. signal-polyfill로 미리 써 볼 수 있고, Lit은 이 제안을 연동하는 @lit-labs/signals를 내놓았습니다. 표준이 되기까지는 시간이 더 걸리겠지만, 다섯 개 이상의 프레임워크가 같은 모델로 모였다는 사실만으로도, Signals는 지난 6년의 가장 분명한 기술적 합의입니다.

React는 이 흐름에서 예외입니다. React는 Signals를 도입하는 대신 컴파일러로 불필요한 재렌더링을 줄이는 길을 택했습니다. 같은 문제를 런타임 반응성으로 풀 것인가, 빌드 시점의 분석으로 풀 것인가의 차이입니다.

메타 프레임워크와 서버로의 회귀

2020년 글은 Svelte의 Sapper와 SvelteKit을 설명하며 "파일 시스템 기반의 라우팅(Next.js의 것과 유사)"이라는 표현을 썼습니다. 당시 메타 프레임워크는 UI 라이브러리 위에 얹는 선택 사항이었습니다. 2026년에는 출발점이 되었습니다. React 팀이 CRA를 유지보수 모드로 전환하며 프레임워크로 시작하라고 권장한 것이 상징적입니다.

State of JS 2025의 메타 프레임워크 사용률은 Next.js 59%, Astro 27%, Nuxt 23%, Gatsby 20%, SvelteKit 17%, Remix 14% 순입니다(참고: State of JS 2025: Meta-Frameworks). 2020년 사용률 28%였던 Gatsby는 2025년 유지 의향이 24%까지 떨어졌습니다.

Next.js

Next.js는 App Router로 React 서버 컴포넌트를 본격적으로 채택한 대표 프레임워크입니다. Next.js 16(2025년 10월 21일)은 Turbopack을 기본 번들러로 바꾸고, 'use cache' 지시어로 캐시할 대상을 명시하는 Cache Components를 도입했습니다. 이전 App Router의 암묵적 캐싱을 버리고 '기본은 동적, 캐시는 명시적 선택(opt-in)'으로 돌아섰습니다. middleware.ts는 proxy.ts로 이름이 바뀌었고, React Compiler 지원이 안정화되었습니다.

// next.config.ts에 cacheComponents: true를 설정한 뒤
async function ProductList() {
  'use cache';
  const products = await db.products.findMany();
  return <ul>{products.map(p => <li key={p.id}>{p.name}</li>)}</ul>;
}

2026년 8월 3일 공개된 16.3은 단일 페이지 애플리케이션(SPA)처럼 페이지 이동에 즉시 반응하게 만드는 기능 묶음인 즉시 이동(Instant Navigations)을 도입하고(느린 이동을 찾아 주는 개발 도구, 부분 프리페치 등), 개발 서버 메모리를 최대 90% 줄였습니다. 2026년 10월 6일 공개된 최신 마이너 버전 16.4는 React 19.3을 포함하고, create-next-app으로 만든 신규 앱에서 Cache Components를 기본으로 켭니다. 기존 앱에서는 next upgrade --agent 명령이 에이전트에게 버전별 업그레이드 안내를 제공합니다.

4-09

그림 12 Next.js 16.3의 Navigation Inspector로 페이지 이동 중의 로딩 화면을 멈춰 놓고 확인하는 화면(출처: Next.js 16.3)

사용률이 오르는 동안 만족도는 내려갔습니다. State of JS 2025에서 Next.js의 유지 의향은 55%로, 2020년 92%에서 크게 떨어졌고 1위 Astro(94%)와 39%p 차이가 났습니다. 메타 프레임워크 고충 항목(주관식, 2,110명 응답)에서는 '인지 부담'(462건) 다음으로 'Next.js 관련 문제'(302건)가 2위였고, '종속(lock-in)'(107건)과 'Vercel'(57건)도 함께 올랐습니다. Next.js 팀은 2026년 3월 16.2에서 배포 플랫폼이 공통으로 쓰는 Adapter API를 안정화하고, OpenNext(Next.js를 여러 플랫폼에 배포하는 오픈소스 어댑터), Netlify, Cloudflare, AWS, Google Cloud와 함께 생태계 워킹 그룹을 만들었습니다. Vercel 자신의 어댑터도 같은 공개 API를 씁니다.

4-10

그림 13 State of JS 메타 프레임워크 만족도(유지 의향) 추이(2018년~2025년)(출처: State of JS 2025: Meta-Frameworks)

React와 Next.js의 관계

Next.js는 React 위에 만든 여러 메타 프레임워크 중 하나지만, 지난 6년 동안 두 프로젝트의 관계는 '라이브러리와 그 사용자'보다 가까워졌습니다. React의 새 서버 기능은 Next.js에서 먼저 실서비스에 쓰였고, React 코어 팀의 상당수가 Next.js를 만드는 Vercel에서 일합니다.

관계가 가까워진 계기는 인력 이동입니다. 2021년 12월 Vercel은 React 코어 팀의 Sebastian Markbåge가 Vercel에 합류해 React 코어 팀을 계속 이끌고, React 18과 서버 컴포넌트를 Next.js에 도입하는 일을 함께한다고 발표했습니다(2026년 10월 현재 Markbåge는 팀 소개 페이지의 명예 멤버(emeritus)로 올라 있습니다). 2026년 10월 React 팀 소개 페이지에서 가장 많은 구성원이 Meta 소속이고, 그다음이 Vercel 소속입니다. 프로젝트 방향을 조율하는 리더십 위원회(Leadership Council) 7명 가운데 5명이 Meta, 2명(Andrew Clark, Sebastian Silbermann)이 Vercel 소속입니다.

서버 컴포넌트가 걸어온 길도 이 관계를 보여 줍니다. Next.js 13(2022년 10월 25일)은 app 디렉터리를 베타로 공개하며 서버 컴포넌트를 지원했고, Next.js 13.4(2023년 5월 4일)에서 App Router를 안정 기능으로 선언했습니다. 이때 Next.js 팀은 App Router가 "React의 canary 채널 위에 만들어졌다"라고 설명했습니다. React가 서버 컴포넌트를 안정 기능으로 선언한 React 19는 그로부터 1년 7개월 뒤인 2024년 12월에 나왔습니다. 서버 컴포넌트는 React 정식 버전보다 Next.js에서 먼저 실서비스에 쓰였고, Next.js가 사실상의 기준 구현 역할을 했습니다.

서버 컴포넌트는 Next.js 전용인가

기술적으로는 아닙니다. 다만 2026년 10월 기준 서버 컴포넌트를 안정 기능으로 쓸 수 있는 곳은 사실상 Next.js뿐입니다. 여기서는 두 가지를 구분해야 합니다.

  • 전통적인 서버 렌더링: 컴포넌트를 서버에서 HTML로 만들어 보내는 기능입니다. react-dom/server의 renderToPipeableStream 같은 API로 제공되며, Next.js의 Pages Router를 비롯해 React Router(구 Remix), Gatsby 등이 오래전부터 써 왔습니다. Next.js 전용이 아닙니다.
  • 서버 컴포넌트와 서버 함수: 번들러가 'use client', 'use server' 경계를 기준으로 서버용 코드와 클라이언트용 코드를 나눠 만들어야 동작합니다. React는 이 연결을 번들러별 패키지(react-server-dom-webpack, react-server-dom-parcel, react-server-dom-turbopack)로 제공합니다.

진입 장벽은 두 번째에 있습니다. React 문서는 서버 컴포넌트 자체는 React 19에서 안정 기능이지만 "React 서버 컴포넌트 번들러나 프레임워크를 구현하는 데 사용되는 기본 API는 시맨틱 버전(SemVer)을 따르지 않으며 React 19.x의 마이너(Minor) 버전 간에 변경될 수 있습니다"라고 밝히고, 구현하는 쪽에는 특정 React 버전에 고정하거나 Canary 릴리스를 쓰라고 권합니다(참고: 서버 컴포넌트). 이 하위 API를 릴리스마다 따라가려면 React 코어 팀과 가까이 일하는 쪽이 유리합니다. React 저장소 안에 Vercel의 번들러 Turbopack 전용 패키지(react-server-dom-turbopack)가 있다는 점도 두 프로젝트의 거리를 보여 줍니다.

다른 구현도 있습니다. 앞의 CVE-2025-55182 공지는 영향을 받는 프레임워크와 번들러로 Next.js 외에 React Router, Waku(서버 컴포넌트 중심의 경량 React 프레임워크), Parcel(@parcel/rsc), Vite 플러그인(@vitejs/plugin-rsc), RedwoodSDK(Cloudflare에서 동작하는 서버 우선 React 프레임워크)를 함께 꼽았습니다. 그러나 2026년 10월 20일 기준 주요 구현의 상태는 안정과 거리가 있습니다.

React 공식 문서의 새 React 앱 만들기도 풀스택 프레임워크로 Next.js(App Router), React Router, Expo를 이 순서로 권합니다. 지금으로서는 'React로 서버 컴포넌트를 쓰겠다'라는 결정이 대부분 'Next.js를 쓰겠다'라는 결정과 같습니다.

함께 움직이는 릴리스와 보안

새 React 버전도 Next.js를 통해 먼저 퍼집니다. React 19.3(2026년 9월 9일)은 한 달이 지나기 전에 Next.js 16.4(10월 6일)에 포함되었습니다. 보안 대응도 같은 구조입니다. 2026년 10월 14일 React는 GitHub 보안 권고로 서버 컴포넌트에서 인증 없이 원격 코드를 실행할 수 있는 치명적 취약점(GHSA-xqc2-xf4c-x3h3)을 공개했습니다. react-server-dom-webpack, -parcel, -turbopack의 19.0.0부터 19.3.0까지가 영향을 받고, 19.0.9, 19.1.10, 19.2.9, 19.3.1에서 수정되었습니다. React 저장소의 보안 권고 목록에서 치명적 등급의 서버 컴포넌트 취약점은 앞의 CVE-2025-55182(2025년 12월) 이후 열 달 만이고, 그사이에도 서버 컴포넌트와 서버 함수의 서비스 거부 취약점(high)이 2026년 1월, 4월, 5월, 7월에 이어졌습니다(참고: Security Advisories · react/react).

같은 날 Next.js도 16.4.1과 15.5.28로 보안 업데이트를 내며 이 권고와 연결된 'use cache' 함수의 원격 코드 실행 취약점, 서버 액션(Server Actions)을 겨냥한 서비스 거부 취약점을 함께 고쳤고, 이미지 최적화에 쓰는 sharp에서 비롯된 원격 코드 실행 취약점(CVE-2026-96889)도 이때 수정했습니다. 공지 작성자 중 Josh Story와 Sebastian Silbermann은 React 팀 소개 페이지에도 오른 Vercel 소속 엔지니어입니다. 10월 20일 기준 react.dev 블로그에는 이 건을 다룬 글이 아직 없습니다.

재단 출범 이후

앞의 'React Foundation과 Create React App의 유지보수 모드 전환' 절에서 본 것처럼 React의 소유권은 2026년 2월 재단으로 넘어갔고, Vercel은 플래티넘 회원 여덟 곳 중 하나입니다. 재단은 "React의 기술 거버넌스는 항상 React 파운데이션 이사회와 독립적으로 유지될 것"이라고 밝혔습니다(참고: React 재단: Linux 재단이 후원하는 React의 새로운 보금자리). 다만 재단이 바꾼 것은 소유권과 운영 구조이고, 코드를 만드는 사람의 소속은 그대로입니다. 재단 출범을 React가 Next.js와 거리를 두는 변화로 보기는 아직 이릅니다. State of JS 2025의 고충 항목에 'Next.js', 'Vercel', '종속'이 함께 오른 것은 개발자들도 이 관계를 의식하고 있다는 신호입니다. Next.js가 16.2에서 Adapter API를 안정화하고 다른 배포 플랫폼과 워킹 그룹을 만든 것은 그에 대한 대응으로 읽힙니다.

실무에서는 어떤 기능이 React의 것이고 어떤 기능이 Next.js의 것인지 구분해 두는 편이 좋습니다. use, Actions, <Activity>는 React의 API라 다른 프레임워크로 옮겨도 그대로 쓸 수 있습니다. 'use client', 'use server'도 React가 정한 규칙이지만, 앞에서 본 것처럼 서버 컴포넌트를 안정적으로 지원하는 프레임워크 안에서만 동작합니다. 'use cache'와 Cache Components, proxy.ts, 이미지 최적화, 증분 정적 재생성(incremental static regeneration, ISR)은 Next.js의 기능이라 Next.js를 떠나면 다시 구현해야 합니다. 서버 컴포넌트를 Next.js 밖에서도 안정 기능으로 쓸 수 있게 되는 시점이 두 프로젝트의 관계가 실제로 느슨해졌는지 확인할 기준이 될 것입니다.

Remix, React Router, 그리고 Remix 3

2022년 10월 31일 Remix 팀은 Shopify에 합류했습니다. 공동 창업자 Ryan Florence와 Michael Jackson이 Shopify로 옮겼고, Shopify는 "Remix는 독립적인 오픈소스 프레임워크로 남는다"라고 밝혔습니다(참고: Remix Joins Shopify, Remixing Shopify). Shopify가 Remix에 맡긴 역할은 커스텀 스토어프런트용 React 프레임워크 Hydrogen의 기반이었습니다. Hydrogen은 이때 React 서버 컴포넌트 대신 Remix의 데이터 로딩 방식을 택했습니다. 프레임워크 팀이 기업에 합류한 사례로는 뒤의 'Astro' 절에서 다루는 NuxtLabs, Astro, VoidZero보다 앞서며, Shopify가 배포 플랫폼이 아니라 Remix를 자사 제품에 직접 쓰는 회사라는 점이 다릅니다.

합류 이후 Remix의 방향은 Shopify의 쓰임새와 함께 움직였습니다. Remix 팀은 2024년 5월 Remix와 React Router를 합친다고 발표하며, Shopify의 핵심 업무를 맡은 500만 줄 규모의 애플리케이션이 React Router로 돌아가고 있다는 점을 이유 중 하나로 들었습니다. Remix 3으로 계획했던 기능은 2024년 11월 22일 React Router v7의 '프레임워크 모드'로 나왔고, 2026년 6월 17일 React Router v8에서는 react-router-dom 패키지가 제거되고 ESM 전용이 되었습니다. 서버 컴포넌트 지원은 아직 불안정(unstable) 단계입니다. Hydrogen도 2025년 5월 21일 2025.5.0에서 Remix 2를 떠나 React Router v7로 옮겼습니다(참고: Hydrogen May 2025 Release).

Remix라는 이름은 전혀 다른 방향으로 돌아왔습니다. 2025년 5월 Wake up, Remix!에서 팀은 Remix 3가 React를 쓰지 않고 Preact를 포크해 출발한 자체 컴포넌트 모델로 간다고 밝혔고, 원칙으로 웹 API 기반, 빌드 시점 분석에 기대지 않는 런타임 중심 설계, 의존성 최소화, 그리고 '모델 우선(Model-First)', 즉 LLM(대규모 언어 모델)이 다루기 좋은 코드와 문서를 꼽았습니다. 2026년 8월 31일 Remix 3 RC가 공개되었고, 10월 1일 첫 정식 버전인 Remix 3.0.0이 출시되었습니다. 정식 버전에서는 컴포넌트 런타임과 JSX 런타임의 진입점이 remix/ui에서 remix/component로 바뀌었습니다. 접근성을 갖춘 헤드리스(headless) UI 기본 요소와 애니메이션 유틸리티는 remix 패키지에서 분리되어, 아직 0.x 버전인 별도 패키지 @remix-run/ui로 옮겨졌습니다. 라우터, 미들웨어, 인증, 데이터 테이블 등 @remix-run/* 하위 패키지는 함께 1.0.0이 되었습니다.

Remix 3도 Shopify 안에서 만들어집니다. RC 발표문은 외부 사용자와 함께 Shopify 내부의 초기 사용자에게서 의견을 모았다고 밝혔고, 2025년 5월 글에서는 출발점으로 삼은 Preact를 "Shopify에서도 많이 쓰는 라이브러리"로 소개했습니다. 반면 Shopify의 상용 스토어프런트 프레임워크인 Hydrogen은 React를 계속 씁니다. 2026년 10월 기준 Hydrogen의 개발 도구(@shopify/cli-hydrogen 13.0)는 React Router v7(@react-router/dev 7.16)에 의존합니다. Shopify 안에서 React 기반 제품 라인(React Router, Hydrogen)과 React를 쓰지 않는 새 프레임워크(Remix 3)가 함께 개발되고 있습니다.

4-11

그림 14 React Router, Remix 1~2, Remix 3의 발전 과정(출처: React Router v8)

Astro

Astro는 페이지 대부분을 정적 HTML로 렌더링하고 상호작용이 필요한 부분만 JavaScript를 붙이는 아일랜드(islands) 구조로, 콘텐츠 중심 사이트에서 자리를 잡았습니다. React, Vue, Svelte 컴포넌트를 섞어 쓸 수 있습니다.

---
import Header from '../components/Header.astro';
import Carousel from '../components/Carousel.jsx';
import Reviews from '../components/Reviews.astro';
---
<Header />
<!-- 화면에 보일 때만 JavaScript를 불러와 하이드레이션한다. -->
<Carousel client:visible />
<!-- 서버 렌더링을 지연시켜 페이지 응답을 막지 않는다(서버 아일랜드). -->
<Reviews server:defer />

위 코드의 페이지가 브라우저에서 동작하는 순서는 다음과 같습니다.

concept-astro-islands

그림 15 Astro 페이지가 정적 HTML로 도착한 뒤 server:defer 영역을 채우고 client:visible 아일랜드를 하이드레이션하는 순서(개념도)

2026년 1월 16일 Astro 팀은 Cloudflare에 합류했습니다. MIT 라이선스, 오픈 거버넌스, Cloudflare 외 배포 대상 지원은 유지된다고 밝혔습니다. 6월 22일 공개된 Astro 7은 .astro 컴파일러를 Rust로 다시 쓰고 Vite 8을 채택했습니다.

NuxtLabs의 Vercel 합류, Astro와 VoidZero(뒤의 '빌드 도구' 절)의 Cloudflare 합류를 함께 보면, 주요 메타 프레임워크와 빌드 도구를 만드는 팀이 배포 플랫폼 기업 안으로 들어가는 흐름이 뚜렷합니다. 각 팀은 하나같이 라이선스와 중립성 유지를 약속했지만, 이 약속의 이행 여부는 커뮤니티가 확인할 부분입니다.

SolidStart의 은퇴

Solid의 메타 프레임워크 SolidStart는 2024년 5월 1.0을 냈고, 2026년 8월 4일 Vinxi(Vite와 Nitro를 묶은 풀스택 SDK) 의존성을 제거하고 Vite 8의 Environment API 위로 옮긴 SolidStart 2.0을 정식 출시했습니다. 2.0은 Solid 1.x 앱을 위한 버전입니다. 그런데 8월 12일 npm에 게시된 Solid 2.0 RC와 함께 낸 발표문에서 Solid 팀은 SolidStart를 3.0으로 잇지 않고 은퇴시킨다고 밝혔습니다. Solid 2.0 개발 기간 동안 SolidStart가 맡던 기능이 모두 다른 곳으로 옮겨 갔기 때문입니다. 서버 함수('use server')는 코어의 @solidjs/web/server-functions로, 서버 실행 계층은 @solidjs/vite-plugin의 start 모드로, 파일 시스템 라우팅은 라우터와 무관한 별도 패키지로 이동했습니다. 발표문은 이를 "Start mode replaces SolidStart."로 정리했습니다. 운영 중인 SolidStart 앱은 계속 유지보수 릴리스를 받습니다.

// vite.config.ts
import { defineConfig } from 'vite';
import solid from '@solidjs/vite-plugin';

// start: true만 지정하면 SPA, ssr: true를 더하면 서버 렌더링 앱이 된다.
export default defineConfig({
  plugins: [solid({ start: true, ssr: true })],
});

빌드 결과의 서버 모듈은 웹 표준 fetch 핸들러를 내보내므로, Cloudflare, Netlify, Nitro의 Vite 플러그인이 Solid 전용 어댑터 없이 바로 배포합니다. Ryan Carniato는 10월 15일 ViteConf 2026 발표(영상)에서 메타 프레임워크는 프레임워크의 빈 곳을 채우려고 존재하며, 아래 계층이 좋아질수록 그 역할이 줄어든다고 설명했습니다. '메타 프레임워크와 서버로의 회귀' 절 첫머리에서 본 것처럼 다른 생태계에서는 메타 프레임워크가 출발점이 되었지만, Solid는 그 기능을 프레임워크와 Vite 플러그인으로 흡수하는 쪽을 택했습니다.

Qwik, htmx, Alpine.js, Hotwire

하이드레이션 비용을 없애는 재개 가능성(resumability)을 내세운 Qwik은 2.0 RC를 진행 중이지만, State of JS 2025 사용률은 3%에 머물고 유지 의향도 2024년 74%에서 2025년 64%로 내려갔습니다.

2020년 글이 마지막에 소개한 Stimulus의 문제의식, 즉 JSON 대신 HTML을 주고받고 JavaScript는 최소한으로 쓰자는 생각은 htmx로 더 넓게 퍼졌습니다. htmx는 HTML 속성만으로 서버 요청과 DOM 교체를 기술합니다. 2026년 8월 28일 htmx 4.0이 정식 출시되었습니다. 4.0은 XMLHttpRequest 대신 fetch()를 쓰고 스트리밍 응답과 모핑(morphing) 방식의 DOM 교체를 기본으로 넣었습니다(참고: The fetch()ening). htmx 2.x는 계속 지원되며, npm의 기본(latest) 태그는 아직 2.x(2.0.11)를 가리키므로 4.0은 htmx.org@next로 설치합니다. htmx의 State of JS 사용률은 9%로 Svelte의 3분의 1 수준이지만 2024년 7%에서 늘었습니다.

<button hx-post="/clicked" hx-target="#result" hx-swap="innerHTML">
  클릭
</button>
<div id="result"></div>

htmx가 서버와 주고받는 일을 HTML 속성으로 옮겼다면, Alpine.js는 클라이언트 쪽의 상태와 동작을 HTML 속성으로 옮겼습니다. PHP 프레임워크 Laravel용 풀스택 UI 프레임워크인 Laravel Livewire의 제작자 Caleb Porzio가 만들었고, 공식 사이트는 Alpine.js를 "마크업 안에서 직접 동작을 조합하는 작고 견고한 도구"라고 소개합니다. HTML 속성 15개, 프로퍼티 6개, 메서드 2개로 이뤄져 있고 빌드 단계 없이 <script> 태그 하나로 쓸 수 있습니다. 3.0은 2021년 6월에 나왔고 2026년 10월 기준 최신 버전은 3.17.4입니다. Livewire는 Alpine.js를 기본으로 포함해 배포합니다(참고: Livewire: Alpine).

<div x-data="{ open: false }">
  <button x-on:click="open = !open">메뉴</button>
  <ul x-show="open">
    <li>설정</li>
  </ul>
</div>

Alpine.js의 State of JS 사용률은 2020년 3%에서 2025년 9%로 늘어 htmx와 같은 수준이 되었습니다. 유지 의향은 77%로 htmx(69%)보다 높습니다. 서버가 HTML을 렌더링하는 페이지에 드롭다운, 탭, 모달 같은 작은 상호작용을 더하는 용도로 쓰이며, 서버 요청은 htmx가, 화면 안의 상태는 Alpine.js가 맡는 식으로 함께 쓸 수도 있습니다.

Stimulus는 37signals(구 Basecamp)의 Hotwire 묶음 안에서 Turbo, Hotwire Native와 함께 쓰입니다. 서버 컴포넌트, 아일랜드, htmx와 Alpine.js는 출발점이 다르지만 '클라이언트로 보내는 JavaScript를 줄인다'라는 같은 방향을 가리킵니다.

TanStack: 프레임워크를 가리지 않는 도구 모음

2020년 무렵 react-query와 react-table은 Tanner Linsley가 만든 React 전용 라이브러리였습니다. 2026년에는 두 라이브러리가 TanStack이라는 이름 아래 라우터, 풀스택 프레임워크, 폼, 클라이언트 데이터베이스까지 포함하는 제품군의 일부가 되었습니다. tanstack.com은 라이브러리를 프레임워크(Start, Router), 데이터와 상태(Query, DB, Store, AI), UI(Table, Charts, Form 등), UX(Virtual, Pacer, Hotkeys), 개발 도구(Devtools, Config, CLI 등)로 나누어 소개합니다.

앞의 절들이 프레임워크마다 일어난 변화를 다뤘다면, TanStack은 반대쪽에서 접근한 사례입니다. 프레임워크와 무관한 코어 하나를 여러 프레임워크용 어댑터로 연결해, 어떤 프레임워크를 고르든 같은 도구를 쓸 수 있게 합니다.

표 4 TanStack 주요 패키지의 npm 주간 다운로드 수(출처: npm registry API, 패키지별 조회, 2026년 9월 28일~10월 4일)

패키지 2020년 11월 1일~7일 2026년 9월 28일~10월 4일
@tanstack/react-query(2020년은 react-query) 157,286 82,757,109
@tanstack/react-virtual - 31,748,429
@tanstack/react-table(2020년은 react-table) 499,101 26,587,277
@tanstack/react-router - 25,131,681
@tanstack/react-start - 16,584,007
@tanstack/react-form - 4,236,975
@tanstack/react-db - 1,101,372
@tanstack/react-charts - 69,289

@tanstack/react-query의 다운로드 수는 같은 주 react(표 1)의 약 37%입니다. 표 1과 마찬가지로 CI 환경의 반복 설치와 의존성 설치가 섞인 수치이지만, React 앱에서 서버 데이터를 다루는 기본 선택지가 되었다는 점은 분명합니다.

개명과 헤드리스 코어

전환점은 2022년입니다. 그해 7월 TanStack Query v4 발표에서 React Query는 TanStack Query로 이름을 바꾸고 저장소를 모노레포로 재구성했습니다. 발표문은 이 재구성으로 "react-query의 즐거움을 vue, svelte, solid 같은 다른 프레임워크로 가져갈 수 있게 되었다"라고 설명했습니다. 발표 시점에 나온 어댑터는 React뿐이었고, 이후 Solid(2022년 9월), Vue(2022년 10월), Svelte(2023년 1월) 어댑터가 차례로 나왔습니다. Angular 어댑터는 2026년 10월에도 패키지 이름에 experimental이 붙은 실험 단계입니다.

react-table도 같은 해 6월 v8에서 @tanstack/react-table로 옮기면서, 프레임워크와 무관한 @tanstack/table-core에 프레임워크별 어댑터를 연결하는 구조로 바뀌었습니다. Table은 마크업과 스타일 없이 정렬, 필터, 페이지 나누기 같은 표의 상태 로직만 제공하고 렌더링은 사용하는 쪽에 맡기는 헤드리스 라이브러리입니다. 2026년 8월 4일 공개된 Table v9는 2년 넘게 개발한 메이저 릴리스로, 표의 상태를 TanStack Store 위에 다시 만들고 기능을 트리 셰이킹할 수 있는 플러그인으로 나눴습니다. 발표문은 각 어댑터가 "프레임워크 무관 코어를 프레임워크 고유의 반응성 모델에 연결"할 수 있게 되었고, 특히 시그널, ref, 룬에 더 직접 연결되어 Signals 기반 프레임워크에서 성능이 좋아졌다고 설명합니다. v9는 table-core와 별도로 프레임워크 어댑터 10개를 제공합니다. 앞의 'Signals로의 수렴' 절에서 다룬 흐름이 라이브러리 내부 설계에도 반영된 사례입니다.

TanStack Query v5(2023년 10월 17일)는 함수 오버로드를 없애고 옵션 객체 하나만 받도록 API를 통일했으며, 번들 크기를 v4보다 약 20% 줄였습니다. cacheTime은 gcTime으로, loading 상태는 pending으로 이름이 바뀌었고, Suspense와 함께 쓰는 useSuspenseQuery가 정식 기능이 되었습니다. 2026년 10월 기준 최신 버전은 5.104.5입니다.

import { useQuery } from '@tanstack/react-query';

function Todos() {
  // v4까지는 useQuery(['todos'], fetchTodos, options)처럼 인자를 나눠 받을 수 있었다.
  const { data, isPending } = useQuery({
    queryKey: ['todos'],
    queryFn: fetchTodos,
    staleTime: 5000,
  });
  if (isPending) return <p>불러오는 중</p>;
  return <ul>{data.map(todo => <li key={todo.id}>{todo.title}</li>)}</ul>;
}

Router와 Start: 타입 안전 라우팅에서 풀스택 프레임워크로

TanStack Router는 2023년 12월 23일 v1.0.0을 npm에 게시했습니다. 경로 매개변수, 검색 매개변수(search params), 로더 데이터의 타입을 모두 추론하는 타입 안전 라우팅이 특징입니다. 문서는 검색 매개변수를 "애플리케이션 전체에서 가장 강력한 상태 관리자"라고 부르며, 문자열 덩어리로 다루던 URL 쿼리를 타입이 있는 상태로 검증하고 갱신하게 합니다.

TanStack Start는 Router 위에 서버 렌더링, 스트리밍, 서버 함수를 더한 풀스택 프레임워크입니다. 2024년 11월 베타를 시작했고, 2025년 6월 v1.121.0에서 Vinxi 의존성을 제거하고 Vite 플러그인 방식으로 바꿨습니다. 2025년 9월 23일 v1 RC를 공개하며 "1.0으로 내보낼 것으로 예상하는 빌드"라고 밝혔습니다. 짧은 마무리 기간을 예상했던 RC는 1년 넘게 이어졌고, 2026년 10월 13일 TanStack Start 1.0이 정식 출시되었습니다. Tanner Linsley는 이미 많은 팀이 RC 단계에서 운영에 써 왔지만, 정식 버전은 지금의 API를 유지하겠다는 공식 약속이라고 설명했습니다. React와 Solid를 지원합니다.

import { createServerFn } from '@tanstack/react-start';

// 서버에서만 실행된다.
export const getServerTime = createServerFn().handler(async () => {
  return new Date().toISOString();
});

// 컴포넌트, 로더, Hook 어디에서든 함수처럼 호출한다.
const time = await getServerTime();

서버 함수는 React의 'use server' 지시어 대신 createServerFn이라는 함수로 서버 코드의 경계를 표시합니다. React 서버 컴포넌트를 받아들이는 방식도 다릅니다. TanStack 팀은 2026년 4월 13일 React Server Components Your Way에서 실험 기능으로 서버 컴포넌트 지원을 소개하며, 서버가 트리 전체를 소유하는 기존 방식 대신 서버 컴포넌트를 "클라이언트에서 언제든 가져오고 캐시하고 렌더링할 수 있는 데이터 스트림"으로 다루겠다고 밝혔습니다. Query로 데이터를 가져오듯 필요한 부분만 서버 컴포넌트로 받는 방식입니다. tanstack.com에 적용한 결과 블로그와 문서 페이지의 클라이언트 JavaScript가 gzip 기준 약 153KB 줄었다고 합니다.

State of JS 2025에서 TanStack Start는 설문 당시 베타였기 때문에 정식 순위에 포함되지 않았지만, '그 밖의 메타 프레임워크' 응답에서 235건으로 1위였습니다. 설문 측은 다음 해 정식 순위에 강하게 등장할 것이라고 전망했습니다. 2026년 5월 13일에는 Lovable이 새 프로젝트의 기본 프레임워크를 TanStack Start로 바꿨습니다(뒤의 '생성형 UI 도구가 정한 기본값' 절 참고).

Form, DB, AI, Charts: 넓어지는 제품군

  • Form: 2025년 3월 3일 v1을 내며 React, Vue, Angular, Solid, Lit 다섯 프레임워크를 지원했습니다. 제네릭을 직접 넘기지 않아도 필드 값과 오류의 타입을 추론하고, Zod, Valibot, ArkType 같은 검증 라이브러리를 Standard Schema(검증 라이브러리들이 공통으로 구현하는 인터페이스 명세)로 별도 패키지 없이 쓸 수 있습니다. 2026년 8월 6일 공개한 v2 알파는 검증 함수를 여러 실행 시점(change, blur 등)에 연결하는 파이프라인 구조로 바꾸고, 스키마를 타입의 기준으로 삼는 옵션을 추가했습니다. 알파는 React 어댑터부터 진행하며, 정식 출시 일정은 밝히지 않았습니다.
  • DB: 2025년 7월 30일 0.1로 공개한 "TanStack Query를 위한 내장형 반응형 클라이언트 데이터베이스"입니다. 2026년 10월 기준 0.x 베타 단계입니다.
  • AI: 2026년 8월 21일 RC를 공개한 AI 기능 개발용 라이브러리로, 24개 LLM 제공자를 지원하고, 에이전트와 UI 사이의 통신 규약인 AG-UI도 지원합니다. 뒤의 '프레임워크 위에서 AI 기능 만들기' 절에서 다루는 Vercel AI SDK와 같은 영역입니다.
  • Charts: 2026년 7월 29일 npm에 0.0.0을 게시하고 두 달여의 알파 기간을 거쳐 10월 3일 1.0.0을 게시했습니다(발표문은 10월 5일, 2026년 10월 기준 최신 버전은 1.1.0). Tanner Linsley가 예전에 만든 React 전용 react-charts와 달리, 마크, 스케일, 변환, 인터랙션을 조합하는 프레임워크 무관 차트 문법 위에 React, Vue, Angular, Svelte, Solid, Preact, Lit 어댑터를 연결합니다. 기본 렌더러는 SVG이고, 데이터가 많은 차트는 별도로 가져오는 Canvas 렌더러로 그립니다. 문서는 2026년 8월 측정 기준 번들 크기를 약 29KB(gzip)로, Recharts(97KB)와 Apache ECharts(157KB)보다 작다고 소개합니다. 코어 패키지 @tanstack/charts의 주간 다운로드는 383,410회입니다(2026년 9월 28일~10월 4일).

후원으로 운영되는 오픈소스

Tanner Linsley는 2025년 11월 24일 전업 2년 회고에서 파트너사 16곳의 후원으로 핵심 기여자 약 12명을 매달 후원하고 있으며, 라이브러리 13개의 누적 다운로드가 40억 회를 넘었다고 밝혔습니다. 2026년 9월 8일에는 Vercel이 Gold 파트너로 합류했고, 같은 등급에 Netlify, Cloudflare, Render, Railway, Lovable, CodeRabbit이 있습니다(참고: TanStack Partners). 앞의 'Astro' 절에서 본 것처럼 메타 프레임워크 팀이 배포 플랫폼 기업에 합류하는 흐름과 달리, TanStack은 여러 플랫폼의 후원을 동시에 받는 방식을 택했습니다.

규모가 커진 만큼 공격 대상도 되었습니다. 2026년 5월 11일 Router와 Start 저장소의 GitHub Actions에서 pull_request_target 설정, 캐시 오염, OIDC(OpenID Connect) 토큰 탈취를 연쇄로 악용한 공격으로 @tanstack 패키지 42개에 악성 버전 84개가 게시되었습니다(참고: Postmortem: TanStack npm supply-chain compromise). 공격 경위는 2편 브라우저 밖의 JavaScript의 'npm: 공급망 공격의 해' 절에서 자세히 다뤘습니다. 9월 30일에는 Start의 서버 함수 응답 처리에서 인증 없이 악용할 수 있는 반사형 크로스 사이트 스크립팅(XSS) 취약점(CVE-2026-102989, Critical)이 공개되어 @tanstack/react-start 1.168.60 등에서 수정되었습니다(참고: TanStack Start security update: CVE-2026-102989). 이 취약점은 Start를 기본 프레임워크로 쓰는 Lovable이 찾아 제보했습니다.

상태 관리: 서버 상태와 클라이언트 상태의 분리

2020년 글은 상태 관리를 Recoil 중심으로 다뤘습니다. Recoil이 어떻게 되었는지는 앞의 React 절 'Recoil의 결말'에서 보았습니다. 6년 동안 이 영역에서 일어난 가장 큰 변화는 새 라이브러리의 등장보다 역할의 분리입니다. 예전에는 API 응답을 Redux 저장소에 넣고 로딩, 오류, 캐시 무효화를 직접 구현하는 경우가 많았습니다. 지금은 TanStack Query, SWR, RTK Query 같은 데이터 가져오기 라이브러리가 서버에서 가져온 데이터(서버 상태)의 캐시와 재요청을 맡고, 상태 관리 라이브러리는 화면에서만 쓰는 클라이언트 상태를 담습니다.

표 5 State of React 2025 상태 관리와 데이터 가져오기 라이브러리 사용률과 유지 의향(출처: State of React 2025: State Management, Data Loading)

라이브러리 분류 2025 사용률 2025 유지 의향
Redux 상태 관리 75% 34%
Redux Toolkit 상태 관리 54% 57%
Zustand 상태 관리 50% 94%
Jotai 상태 관리 18% 92%
MobX 상태 관리 15% 43%
XState 상태 관리 10% 60%
Recoil 상태 관리 9% 47%
TanStack Query 데이터 가져오기 68% 97%
SWR 데이터 가져오기 30% 74%
RTK Query 데이터 가져오기 22% 75%

설문 주최 측은 "Redux와 그 후속인 Redux Toolkit이 오랫동안 가장 널리 쓰였지만 Zustand가 빠르게 따라잡고 있다"라고 요약했습니다. 써 본 비율은 아직 Redux가 높지만, 다시 쓰겠다는 비율은 Zustand(94%)와 Jotai(92%)가 Redux(34%)를 크게 앞섭니다. 상태 관리의 고충으로는 과도한 복잡성과 보일러플레이트가 1, 2위였습니다. 데이터 가져오기 영역에서는 TanStack Query가 사용률 68%, 유지 의향 97%로 가장 높았습니다.

npm 다운로드에서는 순위가 이미 바뀌었습니다.

표 6 상태 관리 라이브러리의 npm 주간 다운로드 수 비교(출처: npm registry API, 패키지별 조회, 2026년 9월 28일~10월 4일)

패키지 2020년 11월 1일~7일 2026년 9월 28일~10월 4일
@tanstack/react-query(2020년은 react-query) 157,286 82,757,109
zustand 27,968 71,534,632
redux 4,765,375 54,483,616
@reduxjs/toolkit 325,150 38,307,471
jotai 1,038 8,027,138
mobx 513,213 4,697,299
recoil 41,163 555,138

2020년에 redux의 약 170분의 1이던 zustand의 다운로드 수는 2026년에 redux를 앞질렀습니다. 주요 라이브러리의 메이저 버전도 같은 방향으로 정리되었습니다.

  • Redux Toolkit 2.0(2023년 12월 4일): Redux 5.0, React-Redux 9.0과 함께 나왔습니다(참고: Redux Toolkit v2.0.0). Redux 팀은 새 코드에 redux 코어 패키지를 쓰지 말고 Redux Toolkit을 쓰라고 권장하며, 코어 패키지를 "지금은 낡은 것(obsolete)"으로 본다고 밝혔습니다. 서버 데이터는 Redux Toolkit에 포함된 RTK Query로 다루도록 안내합니다(참고: Why Redux Toolkit is How To Use Redux Today).
  • Zustand v5(2024년 10월): React 18 미만 지원을 끊고, 외부 패키지 대신 React의 useSyncExternalStore를 직접 쓰도록 바꿨습니다(참고: Announcing Zustand v5). 앞의 'Recoil의 결말' 절에서 본 외부 저장소 연결 API가 상태 관리 라이브러리의 기본 구현이 되었습니다.
  • Jotai v3(2026년 9월 8일): 대부분의 API를 그대로 두고 레거시 지원과 비권장 API를 제거했습니다(참고: Jotai v3.0.0). Recoil과 같은 원자(atom) 단위 상태 모델을 이어 가는 대표 라이브러리입니다.
import { create } from 'zustand';

// 저장소는 컴포넌트 트리 밖에 있고, 컴포넌트는 필요한 값만 골라 구독한다.
const useCartStore = create((set) => ({
  items: [],
  add: (item) => set((state) => ({ items: [...state.items, item] })),
}));

function CartCount() {
  const count = useCartStore((state) => state.items.length);
  return <span>{count}</span>;
}

다른 프레임워크에서는 상태 관리가 프레임워크 안으로 들어왔습니다. Vue는 공식 상태 관리 라이브러리를 Vuex에서 Pinia로 바꾸었고, Vuex 저장소는 "Vuex 3과 4는 계속 유지보수하지만 새 기능이 추가될 가능성은 낮다"라고 안내합니다. 2026년 10월 첫 주 다운로드는 pinia가 약 632만, vuex가 약 187만이었습니다. Angular, Svelte, Solid는 앞의 'Signals로의 수렴' 절에서 본 것처럼 프레임워크의 반응성 원시 기능만으로 공유 상태를 다룰 수 있게 되었습니다.

React 쪽의 Zustand가 쓰는 선택적 구독, Jotai의 원자 단위 상태, 프레임워크의 Signals는 모두 상태를 컴포넌트 트리 밖에 두고 필요한 곳만 다시 그리게 합니다. 2020년 글이 Recoil로 소개한 문제의식은 Recoil이 아닌 다른 이름으로 이어지고 있습니다.

빌드 도구: webpack에서 Vite로, 그리고 Rust로

2020년 글의 Angular v11 절에는 '실험적 Webpack 5 지원'이 있었고, SvelteKit 절에는 개발 중에는 번들링하지 않는 언번들(unbundled) 개발 방식이 각광을 받기 시작했다는 설명이 있었습니다. 6년 사이 이 두 흐름의 승패가 갈렸습니다.

표 7 State of JS 빌드 도구 사용률과 유지 의향(출처: State of JS 2025: Build Tools)

도구 2025 사용률 2025 유지 의향
webpack 87% 26%
Vite 84% 98%
esbuild 54% 88%
Rollup 47% 84%
Turbopack 28% 66%
Bun 25% 91%
Rolldown 10% 94%
Rspack 7% 87%

webpack은 여전히 가장 많은 개발자가 써 본 도구지만, 다시 쓰겠다는 비율은 2020년 87%에서 26%로 떨어졌습니다. Vite는 사용률에서 webpack을 거의 따라잡았고 유지 의향은 98%입니다. 2026년 10월 첫 주 npm 다운로드는 vite가 약 2억 3,215만, webpack이 약 6,722만이었습니다. Angular v17(esbuild와 Vite 기반 빌더 기본화), Angular v22(webpack 빌더 비권장), CRA의 비권장(Vite 등 권장), Next.js 16(Turbopack 기본화)이 모두 같은 방향입니다.

4-12

그림 16 State of JS 빌드 도구 만족도(유지 의향) 추이(2016년~2025년)(출처: State of JS 2025: Build Tools)

Vite 8, Rolldown, Oxc와 VoidZero

Vite는 개발 서버에 esbuild를, 배포 빌드에 Rollup을 쓰는 이중 구조였습니다. Evan You가 세운 회사 VoidZero는 Rust로 작성한 번들러 Rolldown과 파서, 린터, 포매터, 변환기를 묶은 Oxc 도구 모음을 만들어 이 구조를 하나로 합쳤습니다.

Vite 8(2026년 3월 12일)은 Rolldown을 단일 번들러로 쓰며, Rollup 플러그인 호환성을 유지하면서 빌드를 최대 10~30배 빠르게 만들었습니다. 프로젝트 관리 서비스 Linear는 빌드 시간이 46초에서 6초로 줄었다고 밝혔습니다. Rolldown 1.0은 5월 7일 출시되었습니다. React용 플러그인(@vitejs/plugin-react v6)도 상태를 유지한 채 수정한 컴포넌트만 교체하는 빠른 새로고침(Fast Refresh) 변환을 Babel 대신 Oxc로 처리합니다.

4-13

그림 17 Vite 8 발표 이미지(출처: Vite 8.0 is out!)

2026년 6월 4일 VoidZero는 Cloudflare에 합류했습니다. Vite, Vitest, Rolldown, Oxc, Vite+는 MIT 라이선스와 벤더 중립성을 유지하고, Cloudflare는 Vite 생태계 기금으로 100만 달러를 내놓았습니다. 9월 28일 공개된 합류 4개월 보고에 따르면 Vite 8, Vitest 5, Rolldown, Oxlint, Oxfmt를 하나의 설정으로 묶은 Vite+가 1.0이 되었고, Oxc로 옮긴 React Compiler는 Babel판보다 10배 빠르게 컴파일합니다.

4-14

그림 18 Vite+의 작업 실행 명령이 캐시를 재사용해 빌드 단계를 건너뛰는 화면(출처: Four months of VoidZero at Cloudflare)

10월 15일 ViteConf 2026(영상)에서 VoidZero는 Void를 MIT 라이선스로 공개했습니다. Void는 Vite 앱의 서버 코드, 데이터베이스, 스토리지, 배포를 한 패키지로 묶은 SDK, CLI, 배포 플랫폼입니다. 코드에서 가져다 쓴 데이터베이스나 스토리지를 보고 필요한 리소스를 추론해, void deploy 명령 하나로 Cloudflare에 리소스를 만들고 배포합니다. React, Vue, Svelte, Solid 어댑터를 제공하고, TanStack Start, React Router, Astro, SvelteKit, Nuxt 위에도 붙여 쓸 수 있습니다. 빌드 도구는 벤더 중립을 유지하고, Cloudflare로 이어지는 배포 경로는 그 위에 별도 제품으로 만드는 구조입니다.

10월 20일에는 Cloudflare와 VoidZero가 TypeScript 컴파일러를 Rust로 옮긴 tsrs를 실험 버전으로 공개했습니다. 1편 JavaScript(ECMAScript)에서 다룬 Go 기반 TypeScript 7을 다시 Rust로 옮기는 작업으로, 레스토랑용 온라인 주문·마케팅 서비스 Owner.com의 Max Schwenk가 함께하고, TypeScript 팀과 협업하며 Oxc 도구 모음 안에서 진행합니다. 발표 팀은 TypeScript를 포크하는 것이 아니며 언어에 대한 결정은 TypeScript 팀이 내린다고 밝혔습니다. tsrs는 같은 수의 타입 검사 워커로 비교했을 때 TypeScript 7.0보다 최대 8배 빠르고 메모리는 약 70% 적게 씁니다. 일부 최적화는 TypeScript에도 반영되어 TypeScript 7.1 베타는 7.0보다 최대 2.5배 빨라졌습니다. 발표문은 지금 이 작업이 가능해진 이유로 최신 AI 모델이 대규모 이식을 며칠 만에 거의 독자적으로 해낼 수 있게 된 점을 들었습니다. 1편에서 소개한 Ladybird의 LibJS 이식, Bun의 Rust 이식과 같은 흐름입니다. npx tsrs로 실행해 볼 수 있습니다.

Turbopack, Rspack, Biome

Next.js 팀은 webpack을 Rust로 옮기는 대신 새로 설계한 Turbopack을 택했습니다. 2024년 10월 개발 모드가 안정화되었고, Next.js 16에서 배포 빌드까지 기본 번들러가 되었습니다.

ByteDance의 Rspack은 반대로 webpack API 호환을 목표로 한 Rust 번들러입니다. 2026년 4월 22일 2.0이 나왔고, 주간 다운로드는 1.0 시점의 10만에서 2.0 시점 500만으로 늘었습니다. 기존 webpack 설정과 플러그인을 크게 고치지 않고 옮길 수 있다는 점이 강점입니다.

4-15

그림 19 Rspack npm 주간 다운로드 추이(2024년~2026년 4월)(출처: Announcing Rspack 2.0)

린터와 포매터도 Rust로 옮겨 가고 있습니다. Biome 2(2025년 6월 17일)는 TypeScript 컴파일러 없이 타입 정보를 쓰는 린트 규칙을 처음 제공했고, Next.js 16은 next lint 명령을 없애며 Biome나 ESLint를 직접 쓰라고 안내했습니다.

2020년 글의 Angular v11 절에서 소개한 TSLint에서 ESLint로의 이동처럼 도구 계층의 교체 주기는 프레임워크보다 빠릅니다. 2026년의 교체는 JavaScript로 만든 도구에서 Rust나 Go 같은 네이티브 언어로 만든 도구로의 이동입니다.

테스트 도구: Jest에서 Vitest로, Cypress에서 Playwright로

빌드 도구가 Vite로 옮겨 가면서 테스트 도구도 함께 바뀌었습니다. Vite 설정을 그대로 쓰는 Vitest가 단위 테스트에서 Jest를, 여러 브라우저 엔진을 하나의 API로 다루는 Playwright가 E2E(end-to-end) 테스트에서 Cypress를 따라잡았습니다.

표 8 State of JS 테스트 도구 사용률과 유지 의향(출처: State of JS 2025: Testing)

도구 2020 사용률 2025 사용률 2025 유지 의향
Jest 68% 75% 65%
Storybook 42% 56% 69%
Vitest - 54% 97%
Playwright 3% 50% 94%
Cypress 35% 47% 57%
Mocha 52% 44% 55%
Testing Library 26% 41% 89%
Node.js 테스트 러너 - 12% 84%
bun test - 10% 93%

Jest는 여전히 가장 많이 쓰인 도구지만 유지 의향은 2020년 96%에서 2025년 65%로 내려갔습니다. 설문 주최 측은 "Vitest가 빠르게 순위를 올리고 있어 내년에 Jest를 앞질러도 놀랍지 않다"라고 평가했습니다. npm 다운로드는 이미 역전되어, 2026년 10월 첫 주 vitest가 약 1억 4,214만, jest가 약 5,682만이었습니다. E2E 영역에서는 @playwright/test가 약 8,616만으로 cypress(약 737만)의 10배를 넘었습니다.

응답자가 써 본 테스트 도구는 평균 4.4개로, 프런트엔드 프레임워크(2.6개)를 비롯한 다른 분야보다 훨씬 많았습니다. 주최 측은 이를 "완벽한 테스트 러너를 아직 찾고 있다는 신호"로 해석했습니다. 가장 큰 고충은 모킹(mocking)이었고 설정과 초기 구성이 뒤를 이었습니다.

Vitest

Vitest는 Vite의 설정과 플러그인, 변환 파이프라인을 그대로 쓰는 테스트 러너입니다. Jest와 비슷한 API(describe, it, expect, vi.fn)를 제공해 옮겨 가기 쉽고, 빌드와 테스트가 같은 변환 규칙을 쓰므로 설정을 두 번 맞출 필요가 없습니다. '빌드 도구' 절에서 본 것처럼 VoidZero가 개발하며 Vite+에 포함됩니다.

  • Vitest 4(2025년 10월 22일): 실제 브라우저에서 테스트를 실행하는 Browser Mode가 실험 단계를 벗어났습니다. toMatchScreenshot으로 스크린숏을 비교하는 시각적 회귀 테스트도 추가되었습니다.
  • Vitest 5(2026년 9월 3일): 성능에 집중한 버전으로 VM 풀의 테스트 실행이 최대 53%, Browser Mode 테스트가 16~18% 빨라졌습니다. Browser Mode에는 모든 상호작용과 단언을 DOM 스냅숏으로 기록해 단계별로 다시 볼 수 있는 실행 추적 화면(Trace View)이 추가되었습니다. Node.js 22.12 이상이 필요합니다.

Jest

Meta는 2022년 5월 Jest를 OpenJS Foundation으로 이관했습니다. 3년 만의 메이저 버전인 Jest 30(2025년 6월 4일)은 Node.js 14, 16, 19, 21 지원을 끊고 TypeScript 최소 버전을 5.4로 올렸습니다. 모듈 해석기를 unrs-resolver로 바꿔, 한 대형 TypeScript 애플리케이션의 서버 테스트는 실행 시간이 약 1,350초에서 850초로, 최대 메모리가 7.8GB에서 1.8GB로 줄었습니다. Node.js의 타입 스트리핑(type stripping)을 쓸 때는 TypeScript 변환기를 불러오지 않습니다. 다만 ESM 지원은 여전히 실험 단계여서(참고: Jest: ECMAScript Modules), ESM과 TypeScript를 기본으로 쓰는 프로젝트가 Vitest로 옮겨 가는 이유가 되고 있습니다.

Playwright

Microsoft의 Playwright는 Chromium, Firefox, WebKit을 같은 API로 제어하는 E2E 테스트 도구입니다. State of JS 사용률이 2020년 3%에서 2025년 50%로 늘었고 유지 의향은 94%를 유지했습니다. 같은 기간 Cypress의 유지 의향은 93%에서 57%로 떨어졌습니다.

Playwright는 AI 에이전트가 브라우저를 다루는 도구로도 쓰입니다. Playwright MCP는 스크린숏 대신 접근성 트리 스냅숏으로 LLM이 웹 페이지를 조작하게 하는 MCP(Model Context Protocol) 서버입니다. MCP는 AI 도구가 외부 도구와 데이터에 접근하는 프로토콜입니다. 2025년 10월 6일 출시된 Playwright 1.56은 앱을 탐색해 테스트 계획을 쓰는 planner, 계획을 테스트 코드로 바꾸는 generator, 실패한 테스트를 고치는 healer 세 가지 테스트 에이전트 정의를 추가했습니다.

Node.js와 Bun의 내장 테스트 러너도 각각 12%, 10%의 사용률을 기록했고, 설문 선택지에 없던 Deno의 테스트 러너는 주관식 응답 1위였습니다.

웹 표준이 라이브러리를 대체하는 흐름

2020년 글의 Vue 3 Teleport 예시는 모달 레이어를 부모의 position: relative에서 벗어나게 하려고 <body> 아래로 옮기는 기능이었습니다. 툴팁, 드롭다운, 모달은 프레임워크마다 포털(portal), 텔레포트 같은 이름의 기능과 위치 계산 라이브러리가 필요한 영역이었습니다. 이 영역을 브라우저가 직접 제공하기 시작했습니다.

  • Popover API: popover 속성을 붙인 요소는 최상위 레이어(top layer)에 표시되어 부모의 overflow나 z-index의 영향을 받지 않습니다. 2025년 1월 Baseline(주요 브라우저 최신 버전 모두 지원)이 되었습니다. Angular CDK 오버레이도 v21에서 브라우저 내장 popover를 쓰도록 바뀌었습니다.
  • CSS 앵커 위치 지정(anchor positioning): 툴팁을 기준 요소에 붙이는 위치 계산을 CSS로 처리합니다. 2026년 10월 기준 Baseline에는 아직 포함되지 않습니다(참고: webstatus.dev).
  • 사용자 정의 select(customizable select): appearance: base-select로 기본 <select>의 내부를 CSS로 꾸밉니다. Chrome 135에서 시작해 지원 범위가 넓어지고 있지만 아직 Baseline이 아닙니다(참고: webstatus.dev).
  • View Transition API: 같은 문서 안의 화면 전환은 2025년 10월 Firefox 144 지원으로 Baseline이 되었습니다(참고: webstatus.dev). React 19.3의 <ViewTransition>, Angular 라우터의 withViewTransitions가 이 API 위에서 동작합니다. React Router는 8.5(2026년 10월 16일)에서 viewTransition 옵션, useViewTransitionState 같은 자체 view transition API를 비권장으로 지정하고 React의 <ViewTransition>을 쓰라고 안내했습니다. 기존 API는 v9에서 제거됩니다. 라우터마다 따로 감싸던 표준 API를 React가 한 번 감싸는 구조로 정리되고 있습니다.

4-16

그림 20 Web Platform Status에서 Limited availability로 표시된 CSS 앵커 위치 지정(2026년 10월 1일 기준)(출처: Web Platform Status: Anchor positioning)

<button popovertarget="menu" class="trigger">메뉴</button>
<div id="menu" popover>
  <a href="/profile">프로필</a>
  <a href="/logout">로그아웃</a>
</div>

<style>
  .trigger { anchor-name: --menu-trigger; }
  #menu {
    position-anchor: --menu-trigger;
    position-area: bottom span-right; /* 버튼 아래에 붙인다. */
  }
</style>

다음 개념도는 같은 메뉴를 일반 요소로 띄울 때와 popover로 띄울 때를 비교합니다.

concept-popover-top-layer

그림 21 일반 드롭다운과 popover의 차이: 부모 요소에 잘리는 경우와 최상위 레이어에 그려지는 경우(개념도)

JavaScript 없이 열고 닫기, 바깥 클릭 시 닫기, ESC 키 처리가 동작하고, 앵커 위치 지정을 지원하는 브라우저에서는 위치 계산까지 동작합니다. MDN은 사용자 정의 select 문서에서 일부 프레임워크가 이 기능을 막거나 서버 렌더링 하이드레이션 오류를 낸다고 경고합니다. 표준이 앞서 나가고 프레임워크가 따라가는 경우도 나타나고 있습니다.

4-17

그림 22 appearance: base-select로 꾸민 <select>의 드롭다운 목록(Chrome에서 실행)(출처: MDN: Customizable select elements)

웹 컴포넌트도 조용히 자리를 넓혔습니다. 2020년 글은 컴포넌트 기반 개발이 "웹 컴포넌트가 그토록 달성하고자 했던 모습"이라고 썼습니다. 웹 컴포넌트 라이브러리 Lit은 2025년 10월 OpenJS Foundation에 합류했고, State of JS 사용률은 5%에서 10%로 늘었습니다. 프레임워크를 대체하기보다는 디자인 시스템처럼 여러 프레임워크에서 함께 쓰는 컴포넌트를 만드는 용도로 쓰입니다.

반대 방향의 시각도 있습니다. Salesforce의 웹 컴포넌트 기반 프레임워크 LWC(Lightning Web Components) 개발에 참여하며 오랫동안 웹 컴포넌트를 옹호해 온 Nolan Lawson은 2026년 10월 19일 글에서, 에이전트가 최신 브라우저 기능을 쓰도록 안내하는 Chrome 팀의 지침(Modern Web Guidance)도 웹 컴포넌트를 적극 권하지 않는다고 지적했습니다. 그는 웹 컴포넌트가 사람이 HTML을 직접 쓰고 코드가 귀해서 재사용이 중요하던 시기를 전제로 설계되었고, 에이전트가 UI를 처음부터 생성하는 환경에서는 "공통 표준으로 만들어 재사용하기 쉽다"라는 장점이 약해졌다고 보았습니다. 다만 여러 팀이나 에이전트가 화면 영역을 나눠 맡는 마이크로 프런트엔드, 프레임워크와 무관하게 배포하는 독립 위젯에서는 여전히 쓸모가 있다고 덧붙였습니다. 앞에서 본 디자인 시스템 용도와 같은 영역입니다.

AI 도구로 인한 변화

2020년 글은 프레임워크 선택의 고민을 '개발자가 무엇을 고를 것인가'의 문제로 다루었습니다. 2026년에는 이 선택의 상당 부분을 AI 코딩 도구가 대신하거나, 적어도 기본값을 정합니다. 이 절에서는 확인된 사실을 중심으로 세 가지 변화를 정리합니다.

생성형 UI 도구가 정한 기본값

프롬프트로 화면과 앱을 만드는 도구들의 공식 문서를 보면, React, Tailwind CSS, shadcn/ui가 기본값이나 기본 제공 선택지로 반복해서 등장합니다.

  • Vercel은 v0가 React 코드를 생성할 때 shadcn/ui를 기본 스택으로 쓴다고 밝혔습니다. shadcn/ui는 컴포넌트를 패키지로 설치하는 대신 소스 코드를 프로젝트에 추가하는 방식으로 씁니다.
  • Lovable은 2026년 5월 13일 이전에 만든 앱은 React와 Vite, 이후 새 앱은 TanStack Start(서버 렌더링)를 쓰며, 스타일은 Tailwind CSS로 작성합니다.
  • bolt.new는 어떤 JavaScript 프레임워크든 지원하지만, 기본 제공 디자인 시스템으로 Chakra, Material UI, shadcn/ui를 내세웁니다.

프레임워크의 기본 템플릿도 같은 방향입니다. Next.js 16의 create-next-app은 Tailwind CSS를 기본 템플릿에 포함했습니다.

이 조합이 기본값이 된 이유를 각 도구가 공식적으로 설명하지는 않았습니다. 다만 React가 가장 많이 쓰이는 만큼(표 1, 표 2) 학습 데이터에도 React 코드가 많고, 유틸리티 클래스 기반 스타일은 별도의 CSS 파일 없이 마크업 안에서 완결되며, 소스 코드를 복사하는 shadcn/ui는 모델이 직접 읽고 고칠 수 있다는 점이 맞물린 결과로 보입니다. 개발자가 프레임워크를 고르기 전에 도구가 먼저 고르는 상황에서는, React의 점유율이 스스로를 강화할 가능성이 큽니다.

다른 프레임워크도 이 흐름에 대응하고 있습니다. Angular 팀은 v22 발표에서 Google AI Studio와 Gemini Canvas에서 Angular를 지정해 앱을 생성하는 과정을 소개했습니다.

프레임워크가 LLM을 사용자로 대하기 시작했다

LLM의 학습 데이터는 특정 시점에 멈춰 있습니다. 1편 JavaScript(ECMAScript)의 '학습 데이터의 시차' 절에서 언어 기능을 예로 다룬 이 문제는 프레임워크에서 더 크게 나타납니다. 프레임워크가 빠르게 바뀔수록 AI 도구는 오래된 API를 쓰는 코드를 만듭니다. Svelte 5의 룬, Angular의 Signal Forms, Next.js의 Cache Components처럼 최근 2년 안에 나온 API는 특히 그렇습니다. 프레임워크들은 이 문제를 문서 제공 방식의 변화로 풀고 있습니다.

표 9 주요 프레임워크의 LLM 대응(2026년 10월 기준, 각 공식 문서에서 확인)

프레임워크 llms.txt 공식 MCP 서버 그 밖의 대응
React 제공(한국어판 포함) 확인되지 않음 -
Next.js 제공 next-devtools-mcp AGENTS.md, 번들 문서, 스킬
Angular 제공 Angular CLI MCP Agent Skills, WebMCP 실험 지원
Vue 제공 확인되지 않음 -
Nuxt 제공 Nuxt MCP -
Svelte 제공 @sveltejs/mcp 스킬, 서브에이전트
shadcn/ui 제공 shadcn MCP -

llms.txt는 사이트의 문서를 LLM이 읽기 좋은 마크다운 목차와 본문으로 제공하는 관례입니다. Svelte는 분량별로 llms-small.txt, llms-medium.txt, llms-full.txt를 나누어 제공합니다.

프레임워크의 MCP 서버가 제공하는 기능은 두 종류입니다. 하나는 최신 문서 검색과 권장 작성 방식 안내(Angular의 search_documentation, get_best_practices)이고, 다른 하나는 실행 중인 개발 서버의 상태를 에이전트에게 보여 주는 기능입니다. Angular v22의 MCP 서버는 개발 서버를 시작하고 빌드 결과를 기다리는 devserver.start, devserver.wait_for_build를 제공해, 에이전트가 빌드 오류를 읽고 스스로 고치는 반복을 돌릴 수 있게 합니다. 기존 앱을 OnPush와 zoneless로 옮기는 계획을 세우는 onpush_zoneless_migration 도구처럼, 마이그레이션 도구도 에이전트를 사용자로 가정하고 만들어지기 시작했습니다.

가장 적극적인 쪽은 Next.js입니다. Next.js 16.3부터 next dev는 AI 코딩 에이전트를 감지하면 프로젝트의 AGENTS.md에 학습 데이터와 버전이 다를 수 있으니 node_modules/next/dist/docs의 문서를 먼저 읽으라는 안내 블록을 자동으로 기록합니다. 버전에 맞는 문서를 패키지에 함께 넣어 배포하는 방식입니다. 문서가 에이전트에게 직접 전달되면서 Next.js 팀은 지식 전달용 스킬과 MCP의 지식 검색 도구를 없앴습니다. 대신 여러 단계의 작업을 이끄는 스킬(next-dev-loop 등)을 새로 제공하고, MCP 서버에는 프로젝트 전체의 컴파일 오류를 확인하는 get_compilation_issues처럼 실행 상태를 보여 주는 도구를 추가했습니다. Next.js 팀은 2026년 2월 글에서 브라우저 안에서 동작하는 자체 에이전트를 만들었다가 접은 경험을 소개하며, 결론을 "에이전트를 Next.js의 일급 사용자로 대하는 것"으로 정리했습니다.

4-18

그림 23 에이전트가 next-dev-loop 스킬로 코드를 고친 뒤 컴파일, 새로고침, 결과 확인을 반복하는 화면(출처: Next.js 16.3: AI Improvements)

4-19

그림 24 Next.js 팀이 만들었다가 접은 브라우저 내 에이전트 Vector의 오류 진단 화면(출처: Building Next.js for an agentic future)

Remix 3는 설계 원칙에 '모델 우선'을 두었고, Astro 7은 에이전트용 백그라운드 개발 서버와 JSON 로그를, Angular v22는 웹 페이지가 브라우저 안의 에이전트에게 도구를 노출하는 WebMCP 실험 지원을 추가했습니다.

라이브러리 쪽에서는 TanStack이 Intent를 만들었습니다. 메인테이너가 에이전트용 사용 지침(스킬)을 npm 패키지에 함께 넣어 배포하면, 패키지를 설치할 때 그 버전에 맞는 지침도 함께 설치됩니다. 9월 30일 공개된 0.5는 스킬 문서 안의 코드 예시를 TypeScript 컴파일러로 검사하고, 소스가 바뀌면 영향을 받는 스킬을 찾아 검토하게 하는 기능을 더했습니다. Next.js가 버전에 맞는 문서를 패키지에 넣어 배포한 방식을 다른 라이브러리도 쓸 수 있게 한 도구입니다.

이런 대응이 실제 비용 차이로 이어지는지 측정한 사례가 있습니다. Nolan Lawson은 2026년 10월 28일 블로그에서 같은 포켓몬 도감 앱을 12개 스택으로 각각 5번씩 Claude Code(Opus 5.5)에게 만들게 하고 비용을 비교했습니다. 중앙값은 Hono+htmx $2.67, Astro $2.76, Next.js $3.14, SvelteKit $4.28, Angular $4.97였습니다. SvelteKit은 학습 데이터에 없는 v3 마이그레이션 가이드를 매번 읽었고, Angular는 코드량이 가장 많았습니다(약 2,000줄, Hono+htmx는 약 1,370줄). 공식 MCP나 스킬을 설치해도 에이전트가 쓰지 않는 경우가 많았습니다. Next.js는 AGENTS.md를 읽은 실행이 5번 중 2번, 스킬 파일을 읽은 실행이 1번이었고, 에이전트는 Nuxt MCP를 한 번도 쓰지 않았습니다. 다만 이는 개인이 콘텐츠 중심의 작은 앱 하나와 모델 하나로 측정한 결과입니다. 스택마다 비용 범위도 겹치므로 프레임워크를 고르는 기준으로 삼기는 어렵습니다.

빌드 도구도 에이전트를 사용자로 보기 시작했습니다. VoidZero는 Cloudflare 합류 4개월 보고에서 "추론이 빨라질수록 타입 검사, 린트, 빌드 속도가 다시 병목이 된다"라고 썼습니다. 에이전트가 코드를 고칠 때마다 빌드와 테스트를 반복하므로, Rust 기반 도구의 속도 차이는 사람이 쓸 때보다 더 크게 누적됩니다. Evan You는 ViteConf 2026 기조연설에서 에이전트가 개발 도구의 주 사용자가 된다는 전제로, 검사 결과를 터미널 텍스트 대신 구조화된 진단으로 돌려주고 린트, 테스트, 빌드가 한 번 파싱한 결과를 공유하는 도구 체인을 앞으로의 연구 방향으로 제시했습니다.

프레임워크 위에서 AI 기능 만들기

반대 방향의 변화도 있습니다. 웹 앱 안에 채팅이나 에이전트 기능을 넣는 일이 흔해지면서, 이를 위한 JavaScript 라이브러리가 프레임워크 생태계의 일부가 되었습니다. Vercel의 AI SDK는 여러 LLM 제공자를 같은 API로 다루는 TypeScript 도구 모음으로, React, Vue, Svelte용 UI Hook(useChat 등)을 제공합니다. AI SDK 6(2025년 12월 22일)은 에이전트 추상화와 도구 실행 전 사람의 승인을 받는 기능을 넣었고, AI SDK 7(2026년 6월 25일)은 Claude Code, Codex 같은 기존 에이전트 실행 도구(하네스)를 같은 인터페이스로 실행하는 HarnessAgent를 추가했습니다. npm의 ai 패키지는 2026년 10월 첫 주에 약 3,449만 회 다운로드되어, 같은 주 Vue(약 2,040만)보다 많았습니다.

정리하면 AI 도구는 프레임워크 생태계를 세 방향에서 바꾸고 있습니다. 이미 많이 쓰이는 조합(React, Tailwind CSS, shadcn/ui)을 더 강화하고, 모든 프레임워크가 '기계가 읽을 수 있는 최신 문서'와 '에이전트가 확인할 수 있는 실행 환경'을 갖추게 하며, AI 기능을 만드는 라이브러리를 생태계의 새 영역으로 만들고 있습니다. 두 번째 변화는 학습 데이터에 없는 새 프레임워크와 새 API가 그 공백을 극복하는 수단이기도 합니다.

마치며

2020년 글은 "앞으로 몇 년간은 이들의 체제가 그대로 유지될 것으로 보이지만 그 누구도 장담할 수는 없다"라고 끝맺었습니다. 6년이 지난 지금 React, Angular, Vue, Svelte는 모두 건재합니다. 체제는 무너지지 않았지만, 무게중심은 React 쪽으로 크게 기울었습니다. 그리고 각 프레임워크의 안을 들여다보면 거의 모든 것이 바뀌었습니다. Angular는 NgModule과 Zone.js를 내려놓았고, Vue는 VDOM 없는 모드를 준비하고 있으며, Svelte는 반응성 모델을 처음부터 다시 썼고, React는 서버와 컴파일러로 영역을 넓혔습니다. 그리고 이들은 Signals, 서버 렌더링, Vite, 웹 표준이라는 같은 지점을 향해 모이고 있습니다.

이 수렴은 프레임워크 위주로 접근하기보다 기본 기술을 깊게 이해해야 한다는 2020년 글의 주장을 오히려 강하게 만듭니다. 반응성 그래프가 어떻게 의존성을 추적하는지, 서버와 클라이언트가 어디서 경계를 나누는지, 브라우저가 popover와 view transition으로 무엇을 대신해 주는지를 이해하면 프레임워크의 이름이 바뀌어도 같은 지식을 그대로 쓸 수 있습니다. Recoil의 API는 5년 만에 아카이브되었지만, Recoil이 풀려던 문제를 이해한 지식은 Signals를 읽는 데 그대로 쓰입니다.

AI 도구는 이 판단을 한 번 더 시험합니다. 코드는 점점 에이전트가 쓰고, 프레임워크는 에이전트가 고른 기본값으로 정해지는 경우가 늘고 있습니다. 이때 사람에게 남는 일은 에이전트가 만든 코드가 왜 그렇게 동작하는지, 그 선택이 서비스에 맞는지를 판단하는 일입니다. 그 판단의 근거는 여전히 JavaScript와 웹이라는 기본 기술입니다.

라이브러리와 프레임워크를 중심으로 2020년 이후 6년의 변화를 따라가 보았습니다. 네 편을 나란히 놓으면 같은 흐름이 보입니다. 라이브러리와 도구가 풀던 문제를 언어 표준과 런타임, 브라우저가 흡수하고, 도구는 Rust와 Go 같은 네이티브 언어로 옮겨 가며, 모든 계층에서 AI 에이전트가 새로운 사용자로 등장했습니다. 각자의 자리에서 다음 선택을 고민하는 이들에게 작은 기준점이 되었으면 합니다. 빠르게 바뀌는 생태계를 한 시점에 멈춰 기록해 두는 일이 다음 변화를 읽는 데 쓰이기를 바라며 네 편의 연재를 마칩니다.

← 목록으로