
2026년 9월 기준으로 작성했습니다. 버전과 일정은 빠르게 바뀌므로, 글 끝의 공식 출처를 함께 확인하시길 권합니다.
2026년에는 JS/TS 생태계에 큰 릴리스가 몰렸습니다. TypeScript는 컴파일러를 통째로 바꿨고, NestJS는 ESM으로 넘어왔고, Node.js는 릴리스 정책을 고쳤습니다. 이 글에서는 여섯 개 스택의 최신 변화를 정리하고, 각 변화가 생태계 차원에서 무엇을 의미하는지 해석해 봅니다. "무엇이 바뀌었나"는 공식 릴리스 노트에 근거한 내용이고, "인사이트"는 그 변화에 대한 해석입니다.
| 스택 | 최신 버전 | 핵심 변화 |
|---|---|---|
| TypeScript | 7.0 | 컴파일러를 Go로 포팅해 약 10배 빨라짐 |
| React | 19.3 | View Transitions와 Fragment Refs가 stable |
| Next.js | 16.3 | Instant Navigations, dev 메모리 최대 90% 절감 |
| React Native | 0.86 / Expo SDK 57 | New Architecture 필수, Hermes V1 전환 |
| Node.js | 26 (10월 LTS 전환 예정) | Temporal 기본 활성화, 릴리스 정책 변경 |
| NestJS | 12 | ESM 패키지, Standard Schema 지원, CLI 재작성 |

TypeScript 7.0: 새 문법이 하나도 없는 메이저 업데이트
무엇이 바뀌었나
6.0은 기존 JS 코드베이스로 만든 마지막 릴리스이고, 7.0부터는 Go로 작성한 코드베이스가 기반입니다. 네이티브 코드 속도와 공유 메모리 병렬 처리 덕분에 7.0은 6.0보다 보통 10배쯤 빠릅니다. 기존 코드를 Go로 포팅한 것이어서 타입 체크 동작과 의미론은 그대로 유지됩니다.
6.0은 그 전환을 위한 다리 역할의 버전이고, 기본값과 옵션이 크게 정리됐습니다.
strict: true,module: esnext,target: es2025가 기본값이 됐습니다.types의 기본값이[]가 됐습니다. 예전에는node_modules/@types전체를 자동으로 포함했는데, 이를 명시하는 것만으로 빌드가 20~50% 빨라진 프로젝트가 많았다고 합니다.rootDir의 기본값은 tsconfig.json이 있는 폴더입니다. 예전처럼 소스 파일들의 공통 경로에서 추론하지 않습니다.target: es5,moduleResolution: node(node10)와classic,module: amd/umd/systemjs,baseUrl,outFile,esModuleInterop: false가 deprecated됐습니다.import ... assert {}문법은with {}로 대체됩니다.- 6.0에서는
"ignoreDeprecations": "6.0"으로 경고를 무시할 수 있지만, 7.0은 deprecated된 옵션을 지원하지 않습니다. - 새 기능으로 Temporal과
Map.getOrInsert의 타입 내장,RegExp.escape,#/subpath import 지원이 추가됐습니다.
정리된 기본값을 반영하면 tsconfig는 아래처럼 짧아집니다.
// Node.js 앱 기준 tsconfig
{
"compilerOptions": {
"module": "nodenext", // 번들러 사용 시: "preserve" + "moduleResolution": "bundler"
"rootDir": "./src",
"outDir": "./dist",
"types": ["node"], // 필요한 전역 타입만 명시
"paths": {
"@app/*": ["./src/app/*"] // baseUrl 없이 전체 경로를 적는 방식
}
// strict, target은 기본값이 바뀌어 생략 가능
},
"include": ["./src"]
}
인사이트
언어가 성숙하면 경쟁력은 도구의 속도에서 나옵니다. 메이저 버전 두 개를 쓰면서 새 문법을 거의 추가하지 않았다는 점이 가장 눈에 띕니다. 타입 시스템의 표현력은 이미 충분하고, 지금 개발자가 불편해하는 지점은 "얼마나 빨리 피드백을 받느냐"라는 판단이 깔려 있는 것으로 보입니다. 이 방향은 AI 코딩 에이전트의 확산과도 맞물립니다. 에이전트는 코드를 생성하고 tsc를 돌리는 루프를 사람보다 훨씬 자주 반복하기 때문에, 타입 체크가 빨라지면 그 루프 전체가 빨라집니다.
기본값은 생태계가 합의한 내용을 보여 줍니다. TS 팀은 deprecation의 근거로 현실 인식을 직접 나열했습니다. 거의 모든 런타임이 evergreen이고, ES5 환경은 극히 드물며, 새 프로젝트는 번들러와 ESM을 가장 많이 타깃한다는 것입니다. strict가 기본이 되고 ES5 출력이 사라지는 것은 2012년의 가정을 공식적으로 폐기한다는 뜻입니다. IE와 AMD 시대의 흔적이 컴파일러에서 빠졌습니다.
전환 방식도 볼 만합니다. 5.9에서 7.0으로 바로 뛰지 않고, 6.0이라는 호환 버전을 먼저 두고 --stableTypeOrdering 같은 진단용 플래그까지 제공했습니다. 뒤에서 다룰 Node와 NestJS도 비슷한 방식을 택했습니다.
React 19.3: "어떻게 동작하나"에서 "어떻게 느껴지나"로
무엇이 바뀌었나
9월 9일에 나온 마이너 릴리스로 breaking change가 없고, 이번 사이클에 React 20은 예정에 없습니다.
<ViewTransition>이 stable이 됐습니다. 브라우저의 View Transition API로 요소의 enter, exit, update, share 애니메이션을 처리합니다. Transition으로 표시된 업데이트(startTransition, Suspense reveal,useDeferredValue)에서만 동작합니다.addTransitionType으로 같은 상태 변화에 원인별로 다른 애니메이션을 줄 수 있습니다.- Fragment Refs가 stable이 됐습니다.
<Fragment ref>로 자식 DOM 노드들을 그룹으로 다루며, 이벤트, 포커스, 옵저버, 측정과 스크롤 API를 제공합니다. ref를 걸기 위한 래퍼 요소가 필요 없습니다. use(browser())가 추가됐습니다. 서버에서는 Suspense를 트리거하고 클라이언트에서는 그대로 통과합니다.useEffect와mounted상태를 쓰던 패턴이나typeof window체크를 대체하는 공식 API입니다.- Server Component가
'use client'모듈의 Context를 Provider 래퍼 없이 직접 렌더할 수 있습니다. - Trusted Types를 지원하고, 느린 Transition이 무관한 Transition을 막지 않도록 독립적으로 렌더합니다.
ViewTransition에서 가장 헷갈리기 쉬운 부분은 "Transition으로 표시된 업데이트만 애니메이션된다"는 점입니다. 아래 코드에서 startTransition을 빼면 애니메이션이 일어나지 않습니다.
import { ViewTransition, startTransition, useState } from 'react';
function Panel() {
const [open, setOpen] = useState(false);
return (
<>
<button onClick={() => startTransition(() => setOpen(o => !o))}>
상세 보기
</button>
{open && (
<ViewTransition>
<Detail />
</ViewTransition>
)}
</>
);
}
browser()는 localStorage나 타임존처럼 브라우저에서만 의미 있는 값을 다루는 컴포넌트에 씁니다.
import { use, Suspense } from 'react';
import { browser } from 'react-dom';
function SavedTheme() {
use(browser()); // 서버에서는 suspend, 브라우저에서는 통과
return <p>{localStorage.getItem('theme')}</p>;
}
<Suspense fallback={<p>불러오는 중…</p>}>
<SavedTheme />
</Suspense>
기반 측면에서는 React Compiler 1.0이 stable이고 React 17까지 호환되며, 수동 메모이제이션의 대부분을 대체합니다. 거버넌스는 Linux Foundation 산하의 React Foundation으로 이관됐습니다.
인사이트
React가 "느낌"의 영역을 다루기 시작했습니다. 애니메이션, 포커스 관리, 뷰포트 관찰은 그동안 서드파티 라이브러리가 맡던 일이었습니다. 다만 접근 방식이 다릅니다. JS로 애니메이션 엔진을 새로 만드는 대신, 브라우저가 제공하는 View Transition API를 React의 렌더링 주기에 맞춰 조율합니다. React의 역할이 "UI를 그리는 라이브러리"에서 "브라우저 기본 기능들의 타이밍을 조율하는 코디네이터"로 옮겨 가는 모습입니다.
Transition이 성능 옵션에서 핵심 개념으로 올라왔습니다. startTransition은 "무거운 렌더를 뒤로 미루는 최적화 도구" 정도로 여겨졌습니다. 19.3에서는 애니메이션과 이미지·폰트 로딩 조율이 Transition과 Suspense 위에서 동작하고, use(browser())의 서버 렌더링 제외도 Suspense를 통해 처리됩니다. "급한 업데이트는 즉시 반영하고 급하지 않은 업데이트는 부드럽게 전환한다"는 구분이 React UX 모델의 중심이 됐습니다.
Compiler는 개발자에게 필요한 역량을 바꿉니다. useMemo의 의존성 배열을 정확히 맞추는 기술은 가치가 줄어듭니다. 대신 "렌더는 순수해야 한다"는 규칙이 권장 사항에서, 컴파일러가 전제로 삼는 계약으로 바뀌었습니다. 예전에는 규칙을 어겨도 그럭저럭 동작했지만, 이제는 최적화 대상에서 조용히 제외됩니다.
서버로 내려간 프론트엔드는 보안 책임도 함께 집니다. 2025년 12월에 React Server Components에서 인증 없이 가능한 원격 코드 실행 취약점이 공개됐고, 패치를 뚫으려는 시도 과정에서 추가 취약점 두 건이 더 발견됐습니다. React는 이제 서버 공격 표면을 가진 소프트웨어입니다.
릴리스 방식에도 의도가 읽힙니다. ViewTransition에 PR 56개, Fragment Refs에 27개가 들어간 뒤에야 stable이 됐습니다. 실험 채널에서 1년 넘게 다듬고 마이너 릴리스로 안정화하는 방식이 자리를 잡았고, 메이저 버전에 기능을 몰아넣는 일은 줄어들었습니다.
Next.js 16.3: 암묵적 캐싱을 되돌리는 릴리스
무엇이 바뀌었나
16.0 이후 가장 큰 업데이트입니다. 먼저 기존 앱에 자동으로 적용되는 개선입니다.
- Turbopack의 메모리 eviction과 디스크 캐시로
next dev의 메모리 사용이 최대 90% 줄었습니다. next build에 디스크 캐시가 기본 적용되어, 일부 프로젝트는 CI 빌드가 5.5배 빨라졌습니다.- 렌더링 계층을 web streams에서 Node 네이티브 스트림으로 교체해서 부하 시 처리량이 최대 22% 늘었습니다.
next build의 타입 체크에 TypeScript 7을 쓸 수 있습니다.- 새 API로
next/root-params,catchError(retry()로 Server Component 재렌더 가능), Vite 호환import.meta.glob이 추가됐습니다.
Instant Navigations는 opt-in 기능입니다. 동적 UI를 Suspense로 인라인 로딩 상태를 정의하거나 'use cache'로 프리렌더 가능하다고 표시하면, Next가 그 UI를 추출해서 내비게이션 전에 클라이언트에 로드합니다. 여기에 Partial Prefetching, 첫 방문에 shell을 보여 주고 백그라운드에서 프리렌더로 교체하는 ISR 개선, Instant Insights와 Navigation Inspector 개발 도구, Playwright용 instant() 헬퍼가 포함됩니다.
// next.config.ts
const config: NextConfig = {
cacheComponents: true,
partialPrefetching: true,
};
// app/products/[id]/page.tsx
async function ProductInfo({ id }: { id: string }) {
'use cache';
cacheLife('hours');
const product = await getProduct(id);
return <h1>{product.name}</h1>;
}
async function Stock({ id }: { id: string }) {
const stock = await getLiveStock(id); // 요청마다 다른 값
return <p>재고 {stock}개</p>;
}
export default async function Page({ params }: PageProps<'/products/[id]'>) {
const { id } = await params;
return (
<>
<ProductInfo id={id} />
<Suspense fallback={<p>재고 확인 중…</p>}>
<Stock id={id} />
</Suspense>
</>
);
}
인사이트
Next 팀이 자기 문제를 공개적으로 인정했습니다. 릴리스 노트에 Server Components가 내비게이션을 느리게 느껴지게 했고, 캐싱 모델은 암묵적이어서 혼란스러웠으며, prefetch는 지나치게 공격적이고 비용이 컸다고 직접 썼습니다. App Router 도입 이후 커뮤니티가 계속 제기해 온 불만입니다. 그리고 이 기능들이 향후 메이저 버전에서 기본값이 되며, 방향은 "기본은 동적, 숨은 캐싱 없음"이라고 밝혔습니다. 알아서 처리해 주는 자동화는 예측할 수 없게 되는 순간 부담이 된다는 교훈으로 읽힙니다.
서버 주도 아키텍처와 SPA의 반응성을 모두 잡으려 합니다. RSC는 데이터 fetching과 번들 크기에서는 이점이 있었지만, 링크를 클릭하는 순간의 반응성에서는 SPA에 밀렸습니다. Instant Navigations는 서버 중심 구조를 유지하면서 그 약점을 구조적으로 보완하려는 시도입니다.
성능을 관례가 아니라 테스트로 고정합니다. 공유 헤더에 cookies()를 읽는 컴포넌트가 추가되거나 Suspense 경계가 옮겨지면, 즉시 뜨던 페이지가 느려질 수 있습니다. instant() 테스트 헬퍼는 이런 회귀를 잡아냅니다. 성능을 "조심해야 할 것"에서 "CI가 검증하는 것"으로 옮기는 접근입니다.
AI 에이전트를 공식 사용자로 대우하기 시작했습니다. next dev가 프로젝트 버전에 맞는 문서를 가리키는 AGENTS.md 블록을 자동으로 관리합니다. "LLM이 학습한 프레임워크 지식은 늘 옛 버전"이라는 문제를, 설치된 패키지에 그 버전의 문서를 함께 넣는 방식으로 푼 것입니다. Instant Insights도 각 경고마다 에이전트에게 고치는 방법을 알려 주는 프롬프트를 함께 제공합니다.
Next.js는 이제 인프라로 취급됩니다. 보안 패치를 사전 공지와 함께 정기 릴리스로 내는 공식 프로세스로 전환했고, 8월 릴리스(16.3.3 / 15.5.24)에서는 Critical 취약점 두 건이 수정됐습니다. 운영체제나 DB와 비슷한 방식으로 운영하는 단계에 들어섰습니다.
React Native 0.86 / Expo SDK 57: 긴 전환이 끝난 뒤
무엇이 바뀌었나
- 0.82부터 New Architecture(JSI, Fabric, TurboModules)는 필수이고 끌 수 없습니다.
- Expo SDK 57은 RN 0.86을 가져오는 데 집중한 작은 릴리스입니다. 큰 릴리스 사이에 breaking change 없는 업그레이드를 끼워 넣는 새 릴리스 주기를 시험하는 성격도 있습니다. React는 SDK 56과 같은 19.2입니다.
- SDK 56에는
react-native-worklets와react-native-reanimated를 쓰는 앱에 영향을 주는 Hermes V1 메모리 회귀가 있었고, expo@57.0.17(RN 0.86.3)에서 해결됐습니다. 0.85~0.86까지는 레거시 Hermes도 함께 지원합니다. - SDK 56부터 Expo UI의 Jetpack Compose와 SwiftUI API가 stable입니다.
- 0.81 / SDK 54부터 iOS용 RN이 프리컴파일된 XCFramework로 제공되어, RNTester 기준 클린 빌드 시간이 약 120초에서 10초로 줄었습니다.
인사이트
대규모 생태계 마이그레이션이 어떻게 끝나는지 보여 준 사례입니다. New Architecture는 처음 발표된 뒤 필수가 되기까지 여러 해가 걸렸습니다. 전환이 끝까지 갈 수 있었던 이유 중 하나는 레거시 라이브러리를 그대로 돌려 주는 interop 계층입니다. 기존 라이브러리를 새 구조에서 돌려 주는 장치가 있었기에, 강제 없이 점진적으로 전환할 수 있었습니다.
Expo가 사실상 표준 프레임워크입니다. 이제 RN 릴리스는 대부분 Expo SDK를 통해 받게 됩니다. SDK 57의 "작은 릴리스" 실험은 RN 생태계의 오랜 고충이던 업그레이드 부담을 겨냥합니다. 기능 추가와 RN 버전 업그레이드를 분리해서 업그레이드 한 번의 크기를 줄이려는 의도로 보입니다.
JS 엔진 교체는 여전히 위험합니다. Hermes V1 회귀는 reanimated, worklets와의 조합에서 발생했습니다. 몇몇 핵심 라이브러리는 사실상 플랫폼의 일부이고, 엔진과 렌더러와 이 라이브러리들이 함께 움직여야 안정성이 확보됩니다.
Expo UI는 "직접 그리기"에서 "네이티브 컴포넌트 쓰기"로의 전환입니다. RN의 전통적인 방식은 View와 Text를 조합해 네이티브 UI를 흉내 내는 것이었습니다. SwiftUI와 Jetpack Compose가 둘 다 선언형이 되면서 React 문법과 자연스럽게 대응되고, 플랫폼의 실제 컴포넌트를 그대로 가져다 쓸 수 있게 됐습니다.
웹 React와의 시차는 여전히 있습니다. ViewTransition은 현재 DOM 전용이고 RN 지원은 작업 중입니다. "Learn once, write anywhere"는 개념 수준에서는 맞지만, 새 API가 RN에 들어오는 데는 늘 시간이 걸립니다.
Node.js 26: 생태계를 흡수하는 런타임
무엇이 바뀌었나
- Temporal API가 기본 활성화됐고, V8 14.6과 Undici 8.0이 들어갔으며, 레거시 API가 제거됐습니다. 10월에 LTS로 전환될 예정입니다.
- 새 메서드로
Map.getOrInsert(),getOrInsertComputed(),Iterator.concat()이 추가됐습니다. - 릴리스 정책이 바뀝니다. 27부터 메이저 릴리스는 연 1회가 되고, 모든 릴리스가 LTS가 되며, Alpha 채널이 생깁니다. 26이 기존 모델을 따르는 마지막 릴리스 라인입니다.
- 최근 몇 버전에 걸쳐
.ts직접 실행(type stripping),--watch,--env-file,node:test, 내장fetch,require(esm)이 누적됐습니다.
// Temporal: 불변 객체, 명시적 타임존, 날짜와 시각 타입의 분리
const now = Temporal.Now.zonedDateTimeISO('Asia/Seoul');
const nextMonth = now.add({ months: 1 });
const deadline = Temporal.PlainDate.from('2026-12-31');
const daysLeft = now.toPlainDate().until(deadline, { largestUnit: 'days' }).days;
// getOrInsert: has / get / set 세 줄이 한 줄로
const groups = new Map<string, string[]>();
groups.getOrInsert('admin', []).push('kim');
| 외부 도구 | Node 내장 기능 |
|---|---|
| ts-node, tsx | .ts 직접 실행 (type stripping) |
| nodemon | --watch |
| dotenv | --env-file |
| 테스트 러너 | node:test, node:assert |
| node-fetch | 내장 fetch (Undici) |
| ESM/CJS 이중 패키징 | require(esm) |
인사이트
런타임 간 경쟁의 영향이 보입니다. TS 직접 실행, 테스트 러너, watch 모드, env 파일 로딩은 Bun과 Deno가 "기본으로 다 된다"를 내세우며 차별화하던 기능입니다. Node가 공식적으로 밝힌 이유는 아니지만, 이 기능들이 하나씩 내장된 흐름에서 그 영향을 읽을 수 있습니다. 그만큼 ts-node, nodemon, dotenv 같은 오랜 필수 패키지의 자리가 줄었습니다.
릴리스 정책 변경은 오픈소스 지속 가능성의 문제입니다. 홀수 버전은 6개월만 유지되고 LTS로 승격되지 않는데도 릴리스와 백포트 비용은 들었습니다. 이 구조를 접었다는 것은 프로젝트가 관리 부담을 현실적으로 재조정했다는 뜻입니다. LTS만 따라가는 팀은 버전 번호 말고는 달라지는 게 거의 없다는 공식 안내도 이 해석과 맞아떨어집니다.
Temporal은 표준화가 얼마나 오래 걸리는지 보여 줍니다. Date의 결함은 JS 초창기부터 알려져 있었고, 그 빈자리를 moment, date-fns, dayjs가 세대를 바꿔 가며 메워 왔습니다. 이제 Node에서 Temporal이 기본 활성화됐고 TS 6.0에 타입이 내장됐습니다. 날짜 라이브러리의 역할은 "필수 인프라"에서 포맷팅 편의 기능 쪽으로 줄어들 가능성이 큽니다.
type stripping은 TypeScript의 방향에도 영향을 줍니다. Node의 방식은 타입을 "지우기만" 합니다. 그래서 enum, 파라미터 프로퍼티, 데코레이터처럼 런타임 코드를 생성하는 TS 고유 문법과는 맞지 않습니다. "TypeScript = JavaScript + 지울 수 있는 타입"이라는 관점이 런타임 차원에서 힘을 얻고 있고, tsconfig의 erasableSyntaxOnly 옵션이 이를 뒷받침합니다. 이 흐름은 데코레이터에 기반한 NestJS와는 결이 다릅니다.
NestJS 12: 가장 보수적이던 프레임워크의 현대화
무엇이 바뀌었나
8월 27일에 출시됐고, 프레임워크와 CLI, 기본 도구, 문서를 아우르는 수년 만의 가장 큰 업데이트입니다.
- ESM-first. 코어 패키지가 ESM으로 배포됩니다.
require(esm)덕분에 기존 CommonJS 프로젝트는 재작성 없이 동작하고, 애플리케이션 코드의 ESM 전환은 선택입니다. - Standard Schema를 지원합니다.
@Body(),@Query(),@Param()의schema옵션으로 Zod, Valibot, ArkType을 쓸 수 있습니다. 응답 직렬화와@nestjs/config에도 같은 방식이 적용됩니다. class-validator의 대체가 아니라 추가 옵션이고, 공식 문서는 여전히 class-validator를 기본으로 제안합니다. - 기본 도구가 바뀌었습니다. 새 ESM 프로젝트는 Vitest와 oxlint가, CJS 프로젝트는 Jest와 ESLint가 기본입니다. CLI에서 webpack은 deprecated됐고 모노레포의 기본 번들러는 Rspack이며, 일반 프로젝트의 기본 컴파일러는 여전히
tsc입니다. nest upgrade명령이 추가됐습니다. 패키지 업데이트와 기계적인 마이그레이션을 자동화하고 리포트를 출력하며,--dry-run을 지원합니다. ESM, Vitest, oxlint로의 전환은 의도적으로 하지 않습니다.- 운영 관련 기능이 추가됐습니다. 구조화 로깅, 에러 응답의
errorCode, 라우트 충돌 감지, Express 앱의 graceful shutdown, 공식 observability SDK인@nestjs/observe가 포함됩니다. - 마이크로서비스 쪽에서는 NATS v3 클라이언트로 교체됐고, Kafka 패턴이 정규식을 지원하며, gRPC 전용 exception filter가 추가됐습니다. GraphQL의 기본 IDE는 GraphiQL이 됐습니다.
- 실행 요구 사항은 Node.js 20.19 이상 또는 22.12 이상입니다.
import { z } from 'zod';
const createUserSchema = z.object({
email: z.string().email(),
age: z.number().int().min(14),
});
type CreateUserDto = z.infer<typeof createUserSchema>; // 타입을 스키마에서 추출
@Controller('users')
export class UsersController {
@Post()
create(@Body({ schema: createUserSchema }) dto: CreateUserDto) {
return this.usersService.create(dto);
}
}
// 구조화 로깅과 기계가 읽을 수 있는 에러 코드
this.logger.log('주문 생성', { orderId, userId });
throw new BadRequestException('재고 부족', { errorCode: 'ORDER-0042' });
인사이트
NestJS까지 넘어온 만큼 ESM 전환은 마무리 단계입니다. 엔터프라이즈 지향이고 보수적인 축에 속하던 프레임워크가 ESM-first가 됐습니다. 여기서 볼 점은 전환이 가능해진 원인입니다. 개발자에게 ESM을 강요해서가 아니라, Node의 require(esm)으로 CJS에서 ESM 패키지를 불러올 수 있게 됐기 때문입니다. 호환성 문제가 풀리자 라이브러리가 먼저 옮겨 갈 수 있었고, 애플리케이션은 각자의 속도로 따라가면 됩니다.
Standard Schema는 승자를 정하지 않고 인터페이스를 표준화했습니다. 검증 라이브러리들의 경쟁에서 하나가 이긴 것이 아니라 공통 스펙이 만들어졌고, 프레임워크는 특정 라이브러리가 아니라 그 스펙에 통합됐습니다. 그 결과 하나의 스키마를 프론트엔드 폼 검증과 백엔드 DTO 양쪽에 쓸 수 있습니다. 풀스택 TypeScript의 "타입 공유"가 "검증 로직 공유"로 확장되는 셈입니다.
클래스·데코레이터 기반과 스키마·함수 기반 사이에서 양쪽을 다 잡고 있습니다. NestJS의 정체성은 데코레이터와 클래스 기반 DI입니다. 반면 생태계의 흐름은 스키마 우선, 함수형, 지울 수 있는 타입 쪽으로 기울어 있습니다. Vitest로 옮기면서 데코레이터 지원을 위해 OXC를 붙여야 했던 것이 그 간극을 보여 주는 사례로 해석할 수 있습니다. v12는 기존 방식을 기본으로 유지하면서 새 방식을 선택지로 추가하는 절충을 택했습니다.
오픈소스 프레임워크의 수익 모델이 비슷한 형태로 모이는 것처럼 보입니다. @nestjs/observe는 app key와 secret으로 연결하는 대시보드형 서비스입니다. Next.js에는 Vercel이, Expo에는 EAS가 있다는 점을 떠올리면, "프레임워크는 무료로 배포하고 그 프레임워크를 가장 잘 아는 팀의 운영 서비스로 수익을 낸다"는 구도와 닮았습니다. 지속 가능성에는 도움이 되지만, 프레임워크 로드맵과 상업 서비스의 이해관계가 얽힐 수 있다는 점은 지켜볼 부분입니다.
scaffolding의 기본값은 영향력이 큽니다. nest new가 Vitest와 oxlint를 기본으로 제안하는 순간, 수많은 신규 프로젝트의 도구 선택이 사실상 정해집니다. Jest와 ESLint가 오래 누려 온 기본값 지위가 Rust 기반 도구로 넘어가고 있습니다.
여섯 개 릴리스를 관통하는 흐름
1. 성능은 네이티브로, 인터페이스는 JS로 갑니다. tsgo(Go), Turbopack, Rust로 포팅 중인 React Compiler, oxlint, Rspack이 모두 같은 방향에 있습니다. 개발자가 쓰는 API와 설정은 JS/TS로 남고, 그 아래의 무거운 작업은 네이티브 언어로 내려갑니다.
2. 마이그레이션은 선택할 수 있을 때 성공합니다. TS 6.0이라는 호환 버전, Node의 require(esm), RN의 interop 계층, ESM 전환을 일부러 하지 않는 nest upgrade까지, 올해의 큰 전환들은 모두 "기존 방식도 계속 동작한다"는 장치를 제공했습니다.
3. 기본값에는 의견이 담깁니다. TS의 strict: true와 ESM 기본값, NestJS의 Vitest 기본값, Next가 예고한 "기본은 동적"까지, 올해는 기능 추가보다 기본값 변경이 더 큰 의미를 가진 해였습니다. 기본값을 바꾼다는 것은 생태계가 어떤 논쟁을 끝냈다는 선언에 가깝습니다.
4. AI 에이전트가 DX의 새로운 대상이 됐습니다. Next.js는 버전에 맞는 문서를 에이전트에게 자동으로 전달하고, 경고에 프롬프트를 붙입니다. TS의 속도 개선도 에이전트의 작업 루프를 단축합니다. 프레임워크를 평가할 때 "에이전트가 얼마나 잘 다루는가"가 기준에 들어가기 시작했습니다.
5. 풀스택화는 책임의 확장입니다. RSC와 Next.js에서 연달아 나온 Critical 취약점은 프론트엔드 프레임워크가 서버 공격 표면이 됐음을 보여 줍니다. Next.js의 정기 보안 릴리스 체계는 그 현실에 맞춘 제도입니다.
6. 표준이 라이브러리를 대체합니다. Temporal은 날짜 라이브러리를, View Transition API는 애니메이션 라이브러리의 일부를, Standard Schema는 검증 라이브러리 간의 호환 계층을, Node 내장 기능은 개발 도구들을 대체합니다. 생태계가 성숙하면서 서드파티가 메우던 빈자리를 플랫폼과 표준이 하나씩 가져가고 있습니다.
참고한 공식 자료
- TypeScript 6.0: Announcing TypeScript 6.0
- TypeScript 7.0: Announcing TypeScript 7.0
- React 19.3: React 19.3
- React Compiler: React Compiler v1.0
- Next.js 16.3: Next.js 16.3
- React Native 0.86: React Native 0.86
- Expo SDK 57: Expo SDK 57 changelog
- Node.js 26: Node.js 26.0.0 (Current)
- Node.js 릴리스 정책: Node.js Moves to One Major Release Per Year (InfoQ)
- NestJS 12: NestJS v12 is Now Available, v12.0.0 릴리스 노트