
요약
브라우저 밖의 JavaScript 동향을 마지막으로 다루었던 2019년 시점(1부, 2부)에서는 Node.js 12와 막 1년을 넘긴 Deno를 소개하며 "Node.js와 같은 성공을 거둘 수 있을지는 아직 미지수"라고 썼습니다. 패키지 관리자 영역은 "npm의 독주 체제"라고 표현했고 npm 회사의 불확실한 상황에 맞서 Entropic, Open-Registry, GitHub Package Registry 같은 도전자가 등장했다고 전했습니다. 7년이 지난 지금 Node.js는 연 1회 릴리스로 일정을 바꾸기로 했습니다. Node.js 호환을 목표로 삼게 된 Deno와 Bun은 각각 Cloudflare와 Anthropic에 합류했고, npm은 GitHub의 일부가 되어 공급망 공격과 싸우고 있습니다.
이번 연재는 다음 네 편으로 구성됩니다.
- 1편: JavaScript(ECMAScript)
- 2편: 브라우저 밖의 JavaScript
- 3편: WebAssembly
- 4편: 라이브러리와 프레임워크
이 글에서는 먼저 2019년 이후 7년의 변화를 짧게 정리합니다. 이어서 Node.js의 사용 현황과 릴리스 일정, 주요 기능, Deno와 Bun, 서버 런타임 표준인 WinterTC, 공급망 공격으로 크게 바뀐 패키지 관리자와 레지스트리, 데스크톱과 모바일 애플리케이션 개발 도구, PWA와 XR, OpenJS Foundation을 차례로 살펴봅니다. 마지막으로 AI 코딩 도구가 런타임과 패키지 생태계를 어떻게 바꾸었는지 정리합니다. 번들러와 브라우저 밖의 WebAssembly는 짧게 언급만 합니다. WASI와 엣지 플랫폼에서의 WebAssembly 실행은 3편 WebAssembly에서 자세히 다룹니다.
이 글의 내용은 2026년 10월을 기준으로 작성되었습니다. 글을 읽는 시점에 따라 글의 내용과 사실이 다를 수 있습니다.
2019년 이후 7년
2019년 글을 쓸 때 Node.js의 최신 버전은 12.13이었습니다. 2026년 10월 현재 최신 버전은 26.12이고 그사이 메이저 버전이 열네 번 나왔습니다(참고: Node.js 26.12.0 릴리스). 숫자보다 큰 변화는 런타임의 역할입니다. 2019년의 Node.js는 서버와 빌드 도구를 실행하는 런타임이었다면, 지금의 Node.js는 TypeScript 파일을 바로 실행하고 테스트 러너와 SQLite, WebSocket 클라이언트를 내장하며 권한 모델로 파일과 네트워크 접근을 제한합니다. 2019년에 별도 패키지를 설치해야 했던 기능 상당수가 런타임에 내장되었습니다.
경쟁 구도도 달라졌습니다. 2019년에는 Node.js와 Deno를 비교했지만 지금은 Bun까지 세 런타임이 Node.js 호환성을 두고 경쟁합니다. 다만 2026년 10월 Deno 팀이 Cloudflare에 합류하면서 Deno 런타임의 개발은 1년 뒤 끝나게 되었습니다.
패키지 생태계에서는 2020년 GitHub이 npm을 인수하면서 2019년 글이 걱정한 "기술 외적인 불확실성"이 해소되었습니다. 그 대신 2025년부터는 공급망 공격이 가장 큰 문제가 되었습니다. 메인테이너 계정을 탈취해 악성 버전을 올리는 공격이 반복되었고 스스로 퍼지는 웜까지 등장했습니다. npm과 pnpm은 설치 스크립트를 기본으로 실행하지 않도록 바꾸었습니다.
표 1 2019년 이후 브라우저 밖의 JavaScript 주요 사건
| 시기 | 사건 |
|---|---|
2020년 3월 | GitHub, npm 인수 발표(4월 인수 완료) |
2021년 9월 | Electron, 8주 릴리스 주기로 전환(Electron 15) |
2024년 10월 | |
2024년 12월 | |
2025년 1월 | WinterCG가 Ecma TC55(WinterTC)로 이동, pnpm 10에서 의존성 설치 스크립트 기본 미실행 |
2025년 9월 | |
2025년 11월 | |
2025년 12월 | |
2026년 3월 | |
2026년 7월 | |
2026년 8월 | |
2026년 10월 | Deno 팀, Cloudflare 합류, Deno 런타임 개발 사실상 종료(1년간 보안 업데이트 후 종료), Deno Deploy 6개월 뒤 종료 |
Node.js
2019년 글은 마무리에서 "Node.js는 주요 개발 선택 사항 중 하나로 당당하게 인정받고 있다"고 평가했습니다. 7년 뒤의 지표를 보면 이 평가는 더 굳어졌습니다. 그사이 Node.js는 ESM과 TypeScript 지원에서 큰 진전을 이뤘고 릴리스 방식도 바꾸었습니다.
지표로 보는 Node.js
Stack Overflow 2025 개발자 설문에서 Node.js는 '웹 프레임워크와 기술' 항목 1위를 차지했습니다. 전체 응답자의 48.7%, 전문 개발자의 49.1%가 Node.js를 사용한다고 답했습니다. 같은 항목에서 Deno는 4%였고, Bun은 '클라우드 개발' 항목에서 5.5%였습니다(참고: Stack Overflow Developer Survey 2025: Technology).
State of JS 2025의 JavaScript 런타임 문항(응답자 11,141명)에서도 순서는 같습니다(표 2). 조사 측은 "Bun의 3위는 프로젝트 성장의 좋은 신호"라고 평했습니다(참고: State of JS 2025: Other Tools).
표 2 State of JS 2025 JavaScript 런타임 사용 응답 수(출처: State of JS 2025)
| 런타임 | 응답 수 |
|---|---|
Node.js | 10,062 |
브라우저 | 9,682 |
Bun | 2,321 |
Service Workers | 1,660 |
Cloudflare Workers | 1,294 |
Deno | 1,244 |
이 설문에서 Node.js의 사용 응답 수는 Bun과 Deno 각각의 네 배 이상입니다. 다만 Bun과 Deno가 Node.js 호환을 목표로 삼으면서 Node.js 코드를 실행할 수 있는 런타임이 Node.js만은 아니게 되었습니다.
릴리스 관리와 새 연간 일정
2019년 글에서 설명한 연 2회 메이저 릴리스(짝수 버전은 장기 지원(LTS), 홀수 버전은 단기 지원)는 2026년까지 유지되었습니다. Node.js는 2026년 3월 릴리스 일정 개편을 발표했습니다(참고: Evolving the Node.js Release Schedule). 약 10년간 이어 온 연 2회 메이저 릴리스를 Node.js 27부터 연 1회로 바꿉니다.
- 매년 4월 메이저 버전을 출시하고 10월에 LTS로 전환합니다. 홀짝 구분 없이 모든 버전이 LTS가 됩니다.
- 메이저 출시 전 6개월 동안 하위 호환을 깨는 변경(semver-major)을 허용하는 알파 채널(
27.0.0-alpha.1형식)을 운영합니다. - 버전 번호를 출시 연도에 맞춥니다. 27.0.0은 2027년, 28.0.0은 2028년에 나옵니다.
그림 1 Node.js 24부터 30까지의 릴리스 일정(27부터 새 일정 적용, 출처: Evolving the Node.js Release Schedule)
발표문은 개편 이유로 홀수 버전의 채택률이 매우 낮았다는 데이터와, 대부분 자원봉사자인 메인테이너가 네다섯 개의 릴리스 라인에 보안 패치를 동시에 내보내는 부담을 들었습니다.
표 3 Node.js 릴리스 현황(2026년 10월, 출처: nodejs/Release)
| 버전 | 상태 | 주요 내용 |
|---|---|---|
22(Jod) | Maintenance LTS, 2027년 4월 종료 |
|
Active LTS, 10월 20일 Maintenance 전환 | V8 13.6, | |
Current, 10월 28일 LTS 전환 예정 | V8 14.6, Temporal 기본 활성, | |
27 | 10월 28일 알파 시작 예정, 2027년 4월 출시 | 새 일정이 적용되는 첫 버전 |
그림 2 2026년 7월부터 2027년 7월까지의 Node.js 릴리스 일정(출처: nodejs/Release)
단기 지원 버전으로 나온 마지막 릴리스인 Node.js 25는 2025년 10월 출시되어 2026년 6월 지원이 끝났습니다(참고: Node.js 25.0.0 릴리스).
require(esm)
2019년 글은 Node.js Modules 팀이 4단계 계획에 따라 ESM 지원을 진행하고 있다고 전했습니다. ESM은 Node.js 12 시기에 플래그 없이 쓸 수 있게 되었지만 ESM 전환을 가로막던 가장 큰 문제는 그 뒤에도 남았습니다. CommonJS 코드에서 ESM을 동기적으로 불러올 수 없다는 점입니다. 라이브러리가 ESM 전용으로 바뀌면, 그 라이브러리를 쓰는 CommonJS 프로젝트는 동적 import()로 코드를 고치거나 업데이트를 포기해야 했습니다. 그래서 많은 라이브러리가 CommonJS와 ESM을 모두 배포하는 듀얼 패키지 방식을 택했습니다.
Node.js 팀의 Joyee Cheung이 주도한 require(esm)은 top-level await가 없는 ESM 모듈을 require()로 불러올 수 있게 했습니다. 2024년 10월 Node.js 23.0과 12월 22.12에서 플래그 없이 쓸 수 있게 되었고 2025년 3월 20.19에도 백포트되었습니다. 현재 지원되는 모든 Node.js 버전에서 쓸 수 있으며 25.4와 24.15에서는 실험 기능 표시도 사라졌습니다(참고: Node.js Modules: CommonJS modules).
// CommonJS 파일에서 ESM 전용 패키지 불러오기
const { format } = require("esm-only-package");
다음 개념도는 같은 require() 호출이 require(esm) 이전과 이후에 어떻게 처리되는지 보여 줍니다.
그림 3 CommonJS의 require()로 ESM 패키지를 불러올 때 require(esm) 이전과 이후의 차이(개념도)
이 변화로 라이브러리 저자들이 ESM 전용 배포를 택할 근거가 생겼습니다. Anthony Fu는 2025년 2월 "Move on to ESM-only"라는 글에서 2022년의 듀얼 패키지 지지 입장을 바꾸어 새 패키지는 ESM 전용으로 배포하자고 제안했습니다.
타입 스트리핑
Node.js 22.6.0에 실험 기능으로 추가된 타입 스트리핑(type stripping)은 TypeScript 파일에서 타입 표기만 지우고 바로 실행합니다. 2025년 1월 Node.js 23.6.0에서 기본으로 켜졌고 2025년 11월 25.2.0과 12월 24.12.0에서 안정(Stable) 기능이 되었습니다(참고: Node.js: Modules: TypeScript).
node app.ts
타입 스트리핑은 타입 검사를 하지 않고 tsconfig.json도 읽지 않습니다. 타입 표기를 공백으로 바꾸는 방식이라 소스 맵이 필요 없다는 장점이 있지만 지울 수 없는 문법은 지원하지 않습니다. enum, 런타임 코드가 있는 namespace, 클래스 생성자의 매개변수 속성 같은 문법이 여기에 해당합니다. 이런 문법까지 변환하던 --experimental-transform-types 플래그는 Node.js 26.0.0에서 제거되었습니다(참고: Node.js 26.0.0 릴리스). Node.js는 TypeScript의 지울 수 있는 문법만 쓰라는 방향을 정한 것으로 보입니다. TypeScript도 5.8에서 지울 수 없는 문법을 컴파일 단계에서 오류로 잡는 --erasableSyntaxOnly 옵션을 추가했습니다.
다음 개념도는 타입 스트리핑이 소스를 바꾸는 방식을 보여 줍니다. 타입 표기가 있던 자리는 같은 길이의 공백이 되고, 나머지 코드는 위치가 바뀌지 않습니다.
그림 4 타입 스트리핑이 타입 표기를 공백으로 바꾸는 방식과 지울 수 없는 문법(enum)의 처리(개념도)
권한 모델
2019년 글은 Deno의 첫 번째 차이점으로 보안성을 꼽았습니다. 코드를 샌드박스에서 실행하고 파일 시스템이나 네트워크에 접근하려면 --allow-write 같은 플래그로 허용해야 한다는 설명이었습니다. Node.js도 비슷한 장치를 갖추었습니다. 권한 모델(Permission Model)은 Node.js 20에서 실험 기능으로 추가되었고 23.5.0과 22.13.0에서 안정 기능이 되었습니다(참고: Node.js: Permissions).
# 모든 리소스 접근을 막고, 지정한 경로의 읽기만 허용 node --permission --allow-fs-read=/app/config index.js # 막지 않고 위반 사항만 기록하는 감사 모드 node --permission-audit index.js
--allow-fs-read, --allow-fs-write, --allow-child-process, --allow-worker, --allow-addons, --allow-wasi에 이어 25.0에서 네트워크 접근을 제어하는 --allow-net이 추가되었습니다. 설정 파일을 읽은 뒤 그 경로의 권한을 되돌릴 수 없게 버리는 process.permission.drop()도 있습니다(참고: Node.js 25.0.0 릴리스, Node.js: Permissions).
다만 문서는 이 모델을 안전벨트에 비유하며 "악성 코드로부터 보호하지 않는다"고 분명히 밝힙니다. 실행하는 코드는 신뢰한다는 전제에서 실수로 인한 접근을 막는 장치이고 심볼릭 링크로 경로 제한을 우회할 수 있으며, 워커 스레드를 만들 때 execArgv를 직접 지정하면 권한 설정이 이어지지 않습니다(참고: Node.js: Permissions). 신뢰할 수 없는 코드를 격리하는 용도라면 뒤에서 다룰 Deno Sandbox나 3편에서 다룰 WebAssembly 샌드박스 같은 별도 장치가 필요합니다.
런타임 안으로 들어온 기능
Node.js 18 이후 별도 패키지가 필요하던 기능이 차례로 내장되었습니다. 2019년 글의 "논의 중인 새로운 기능"에 있던 항목도 이 흐름 속에서 결말을 맞았습니다.
표 4 Node.js에 내장된 주요 기능(출처: Node.js 문서)
| 기능 | 추가 | 안정화 | 대체하던 패키지 |
|---|---|---|---|
| 17.5.0 | 21.0.0 | node-fetch, axios |
| 18.0.0 | 20.0.0 | Jest, Mocha |
| 21.0.0 | 22.4.0 | ws |
| 22.5.0 | 25.7.0에서 Release Candidate | better-sqlite3 |
타입 스트리핑 | 22.6.0 | 25.2.0 | ts-node, tsx |
권한 모델 | 20.0.0 | 23.5.0 | 해당 없음 |
fetch는 undici 기반이며 브라우저와 같은 Request, Response, Headers를 제공합니다. 2026년에는 Axios 코드를 fetch로 옮기는 공식 코드모드(codemod) npx codemod @nodejs/axios-to-whatwg-fetch도 나왔습니다(참고: Node.js: Axios to WHATWG Fetch). node:test는 목(mock), 스냅숏 테스트, 감시 모드, 코드 커버리지를 지원하고(참고: Node.js: Test runner), node:sqlite는 동기 API인 DatabaseSync를 제공합니다(참고: Node.js: SQLite).
import test from "node:test";
import assert from "node:assert";
import { DatabaseSync } from "node:sqlite";
test("sqlite", () => {
const db = new DatabaseSync(":memory:");
assert.strictEqual(db.prepare("SELECT 1 + 2 AS n").get().n, 3);
});
2019년 글이 소개한 TSC의 전략적 계획 중 몇 가지는 이렇게 정리되었습니다.
- Core Promise API:
fsPromise API는 11.14.0과 10.17.0에서 실험 기능 표시가 사라졌고 14.0.0부터require('fs/promises')로 불러올 수 있습니다(참고: Node.js: File system). - 비동기 훅(async hooks): 2019년에 실험 API였던
async_hooks는 지금도 실험 상태이며 문서는 "가능하면 이 API에서 옮겨 가라"고 안내합니다. 대신 비동기 문맥을 전달하는AsyncLocalStorage가 16.4.0에서 안정 기능이 되었습니다. 이 개념은 TC39의 AsyncContext 제안으로 이어지고 있습니다. - QUIC:
node:quic모듈이 23.8.0에 추가되었지만 아직 초기 개발(Early development) 단계입니다.
2026년에도 새 기능은 계속 추가되었습니다. 26.4.0(6월)에는 모듈 해석 경로를 직접 지정하는 패키지 맵(package maps)과 최소 기능의 가상 파일 시스템 node:vfs가 추가되었습니다(참고: Node.js 26.4.0 릴리스). node:vfs가 추가되기까지의 논쟁은 "AI 도구로 인한 변화" 절에서 다룹니다.
Deno 2와 Bun
Deno: npm과의 화해
2019년 글은 Deno를 "V8과 Rust, Tokio로 개발된 JavaScript와 TypeScript 런타임"으로 소개하고 Node.js와의 차이로 보안성과 URL 기반 모듈 로딩을 들었습니다. package.json과 node_modules가 필요 없고 npm 같은 중앙 집중화된 레지스트리 없이 원하는 곳에서 모듈을 배포할 수 있다는 점을 강조했습니다.
Deno는 그 뒤 방향을 일부 바꾸었습니다. 2024년 10월 출시된 Deno 2는 package.json과 node_modules를 지원하고 Node.js, npm과의 하위 호환을 전면에 내세웠습니다(참고: Announcing Deno 2). 기존 Node.js 프로젝트를 그대로 실행하면서 Deno의 도구를 점진적으로 도입하는 방식입니다.
그림 5 npm 패키지와 Deno 패키지가 함께 들어 있는 Deno 2 모노레포의 예(출처: Announcing Deno 2)
2026년 5월 출시된 Deno 2.8은 이 방향을 수치로 보여 줍니다. Node.js 자체 테스트 묶음의 통과율이 Deno 2.7의 약 42%에서 2.8의 76.4%(4,457개 중 3,405개)로 올랐고 deno add, deno install에서 npm: 접두사 없이 npm 패키지를 추가하는 npm 우선 기본값이 적용되었습니다. deno audit fix, deno ci, deno pack, deno why 같은 패키지 관리 명령도 추가되었습니다(참고: Deno 2.8).
# Deno 2.8: npm: 접두사 없이 npm 패키지 추가 deno add express deno run --allow-net server.ts
Deno 회사의 수익 모델인 Deno Deploy는 2026년 2월 정식 출시(GA)되었습니다. 같은 날 공개한 Deno Sandbox는 1초 안에 부팅되는 Linux 경량 가상 머신(microVM)에서 신뢰할 수 없는 코드를 실행하는 서비스입니다. 발표문은 LLM이 생성해 사람의 리뷰 없이 바로 실행되는 코드를 대상으로 들었습니다. API 키는 샌드박스 안에서 자리표시자(placeholder)로만 보이고 승인된 호스트로 요청할 때만 실제 값으로 바뀌며 허용되지 않은 호스트로의 송신은 막습니다(참고: Introducing Deno Sandbox, Deno Deploy is GA).
Deno: Cloudflare 합류와 개발 종료
2026년 10월 9일 Ryan Dahl은 Deno 팀 전원이 Cloudflare에 합류한다고 발표했습니다. 별도의 런타임과 호스팅 서비스를 계속 개발하는 대신 Cloudflare Workers, Durable Objects 팀과 함께 만드는 공동 플랫폼에 개발 역량을 모으겠다는 결정입니다. 발표문이 밝힌 계획은 다음과 같습니다(참고: Deno is joining Cloudflare).
- Deno 런타임: 1년 동안 버그 수정과 보안 업데이트를 담은 월간 릴리스를 낸 뒤 개발을 끝냅니다. Deno는 오픈소스로 남고 개발을 이어 갈 사람을 환영한다고 밝혔습니다.
- Deno Deploy: 6개월 동안 운영한 뒤 종료합니다. 유료 고객이 Cloudflare Workers로 옮기도록 이전을 지원합니다.
- JSR: 계속 운영하며 인프라를 Cloudflare로 옮깁니다.
- rusty_v8: 지원을 이어 가며 Cloudflare Workers의 오픈소스 런타임인 workerd에 통합하는 작업을 진행합니다.
Ryan Dahl은 Deno에서 Deno Deploy, 그리고 Workers 프로그래밍 모델 위에서 분산 애플리케이션을 만드는 celld로 이어진 흐름을 합류 이유로 들었습니다. Cloudflare Workers를 처음 설계한 Kenton Varda(Workers 기술 책임자, Protocol Buffers 2의 주 저자, Cap'n Proto 개발자)와 함께 쓴 공동 발표문은 workerd와 celld를 합치고, workerd를 자체 인프라에서 운영(self-hosting)하는 방식을 정식으로 지원하겠다고 밝혔습니다(참고: Deno joins Cloudflare). 2월에 정식 출시된 Deno Deploy는 8개월 만에 종료가 예고되었고 Deno Sandbox의 향후 계획은 두 발표문 모두 언급하지 않았습니다.
발표 직후 Hacker News에 "Cloudflare acquires Deno"라는 제목으로 올라온 글은 2026년 10월 12일 기준 1,300점 넘는 추천과 700개 넘는 댓글을 받았습니다(참고: Hacker News). 가장 위에 오른 댓글은 Deno 런타임 개발 종료 대목을 그대로 인용하며 다른 누군가가 개발을 이어받지 않으면 Deno 지원은 끝난다고 지적했고, Cloudflare 쪽 발표문에는 이 내용이 없다는 답글이 뒤따랐습니다. "Cloudflare의 인재 영입(acquihire)으로 Deno 개발이 사실상 종료되었다"가 더 정확한 제목이라는 댓글도 있었습니다.
반응은 대체로 아쉬움이었고 원인을 보는 시각은 두 가지로 나뉘었습니다. 한쪽은 Deno가 npm 호환을 우선순위로 올리면서 처음의 단순함을 잃었다고 보았고, 다른 쪽은 Node.js 호환을 앞세운 Bun의 빠른 확산이 Deno를 그 방향으로 밀어붙였다고 반박했습니다. 벤처 투자를 받은 런타임 회사가 수익 모델을 찾기 어렵다는 지적과, 런타임 지원 1년과 Deno Deploy 운영 6개월이라는 기간이 Deno 위에서 서비스를 운영하는 팀에 부담이 된다는 지적도 많았습니다. 그러면서도 Deno가 먼저 보여 준 기능을 Node.js가 받아들였으니 적어도 더 나은 Node.js는 남았다는 평가가 여러 댓글에서 나왔습니다. Kenton Varda도 댓글로 workerd와 celld를 합쳐 자체 인프라에서 운영할 수 있는 오픈소스 런타임을 만드는 것이 이번 결정의 핵심이라고 설명했습니다.
Bun: 하나의 바이너리, 그리고 Anthropic
Bun은 2019년 글 이후에 등장한 런타임입니다. JavaScriptCore 엔진 위에서 런타임, 패키지 관리자, 번들러, 테스트 러너를 하나의 바이너리로 제공하는 도구로 빠르게 사용자를 늘렸습니다. 2025년 10월 출시된 Bun 1.3은 HTML 파일을 바로 실행하는 개발 서버, MySQL과 PostgreSQL, SQLite를 하나의 API로 다루는 Bun.SQL, 설치 시점에 패키지를 검사하는 Security Scanner API를 추가했습니다(참고: Bun 1.3).
2025년 12월 Bun은 Anthropic에 인수되었습니다(참고: Bun is joining Anthropic). Anthropic의 AI 코딩 도구인 Claude Code가 Bun으로 빌드한 단일 실행 파일로 배포되고 있었다는 점이 배경입니다. Bun은 MIT 라이선스의 오픈소스로 유지됩니다.
2026년 8월 출시된 Bun 1.4는 구현 언어를 Zig에서 Rust로 바꾼 첫 버전입니다. Node.js 테스트 묶음에서 통과하는 테스트가 1,517개 늘었고 릴리스 노트는 이를 "Bun 1.0 이후 가장 큰 Node.js 호환성 향상"이라고 설명했습니다(참고: Bun 1.4). Node Weekly는 Bun 1.4가 Node.js 테스트 묶음의 80%를 통과한다고 전했습니다(참고: Node Weekly 639호, Bun: Node.js test suite tracker). Bun.Image, Bun.WebView, Bun.cron() 같은 API도 내장되었습니다. Rust 재작성이 AI 도구로 진행된 과정은 "AI 도구로 인한 변화" 절에서 다룹니다.
그림 6 Bun 1.2.0부터 1.4.0까지 통과한 Node.js 테스트 묶음 파일 수(출처: Bun 1.4)
세 런타임의 공통점
세 런타임 모두 TypeScript를 직접 실행하고 ESM을 지원하며 웹 표준 API(fetch, Request, Response, Web Streams 등)를 제공합니다. 2019년에 Node.js와 Deno의 차이로 꼽히던 부분은 대부분 사라졌습니다.
남은 차이는 기본값과 범위입니다. Node.js는 호환성과 안정성을, Deno는 권한 기본 차단과 통합 도구를, Bun은 속도와 내장 기능의 폭을 앞세웁니다. 세 런타임이 서로의 장점을 흡수하는 사이, 런타임 사이의 공통 API를 표준으로 정하려는 움직임도 생겼습니다.
WinterTC: 서버 런타임을 위한 표준
Node.js, Deno, Bun, Cloudflare Workers 같은 서버 런타임이 늘어나면서 어느 런타임에서나 같은 웹 API를 쓸 수 있도록 맞추려는 움직임이 시작되었습니다. 2022년 W3C 커뮤니티 그룹으로 시작한 WinterCG는 2025년 1월 Ecma International의 기술위원회 TC55(WinterTC)로 옮겨 갔습니다(참고: Goodbye WinterCG, welcome WinterTC). ECMAScript를 만드는 TC39와 같은 Ecma 안에 언어 바깥의 런타임 API를 다루는 위원회가 만들어졌습니다.
TC55의 첫 결과물인 ECMA-429 "Minimum Common Web API" 1판은 2025년 12월 Ecma 총회에서 승인되었습니다. 브라우저와 서버 런타임이 공통으로 제공해야 하는 웹 플랫폼 API의 최소 집합을 정의한 표준으로, 매년 스냅숏 형태로 개정할 계획입니다. fetch, Request, Response, URL, URLPattern, Web Streams, TextEncoder, CompressionStream, crypto.subtle, structuredClone, AbortController, WebAssembly JavaScript API 등이 포함되어 있습니다(참고: Minimum Common Web API).
이 표준이 정착하면 라이브러리 작성자는 'Node.js용'과 '브라우저용'을 따로 만들지 않고 WinterTC 호환 API만으로 코드를 작성할 수 있을 것입니다. isomorphic-fetch 같은 폴리필 패키지가 필요했던 시절과 비교해 달라지는 점입니다.
번들러
2019년 글 2부는 webpack 5, Parcel 2, @pika/web을 소개했습니다. 여기서는 이 영역의 변화를 결과 위주로 정리합니다. State of JS 2025에서 webpack을 다시 쓰겠다는 비율은 26%로 떨어졌고 사용률에서도 Vite(84.4%)가 webpack(86.4%)을 거의 따라잡았습니다(참고: State of JS 2025: Build Tools). Vite 8은 Rust로 작성한 Rolldown을 단일 번들러로 쓰고 Next.js는 Turbopack을, ByteDance는 사내 대형 프로젝트의 빌드 성능 문제를 풀기 위해 webpack 호환 Rust 번들러 Rspack을 만들었습니다(참고: Rspack 소개).
2019년 글이 소개한 @pika/web의 후속 프로젝트인 Snowpack은 2022년 4월 "더 이상 적극적으로 유지보수하지 않는다"고 공지하며 Vite를 대안으로 안내했습니다(참고: Snowpack). 개발 중에 번들링하지 않는 언번들(unbundled) 방식은 Vite가 이어받았습니다.
브라우저 밖의 JavaScript 관점에서 눈에 띄는 점은 JavaScript 도구를 JavaScript가 아닌 언어로 다시 만드는 흐름이 번들러에서 끝나지 않았다는 점입니다. TypeScript 컴파일러는 Go로, Bun은 Rust로 옮겨 갔습니다. pnpm도 Rust로 다시 작성되었고 Yarn 6도 Rust로 개발되고 있습니다. JavaScript 생태계의 도구 계층이 JavaScript 바깥으로 빠르게 이동하고 있습니다. 빌드 도구는 4편 라이브러리와 프레임워크의 빌드 도구 절에서 자세히 다룹니다.
패키지 관리자와 레지스트리
2019년 글은 이 영역을 "큰 변화 없이 npm의 독주 체제가 계속 유지되는 영역"이라고 설명했습니다. 그리고 npm 회사의 해고와 경영진 교체, 자금 사정을 "기술 외적인 불확실성"으로 짚었습니다. 7년 뒤 npm의 독주는 그대로지만 불확실성의 성격이 바뀌었습니다. 회사의 존속 문제는 GitHub 인수로 사라졌고 그 자리를 공급망 공격이 차지했습니다.
2019년의 도전자들은 어떻게 되었나
2019년 글이 소개한 도전자들의 결말부터 정리합니다.
- GitHub의 npm 인수: 2020년 3월 16일 GitHub이 npm 인수를 발표했고 4월 15일 인수를 마쳤습니다(참고: npm has joined GitHub). GitHub은 "공개 npm 레지스트리는 항상 무료로 제공될 것"이라고 약속했습니다(참고: npm is joining GitHub).
- GitHub Package Registry: 2019년 5월 베타로 발표된 GitHub Package Registry는 GitHub Packages가 되었습니다. npm 인수 발표문은 npm의 유료 private 패키지를 GitHub Packages로 옮길 수 있게 하겠다고 밝혔습니다.
- tink: npm 8에 통합될 계획이었던 tink는 통합되지 않았고 저장소는 보관(archived) 처리되었습니다(참고: npm/tink).
- Entropic과 Open-Registry: CJ Silverio가 발표한 연합 패키지 레지스트리 Entropic은 2019년 12월 31일 커밋을 마지막으로 개발이 멈추었고 entropic.dev와 Open-Registry의 open-registry.dev 도메인은 2026년 10월 현재 모두 접속되지 않습니다(참고: entropic-dev/entropic).
중앙 레지스트리에 대한 반발에서 시작한 프로젝트는 대부분 사라졌지만, '레지스트리를 누가 운영하는가'라는 질문은 뒤에서 볼 JSR과 vlt로 이어졌습니다.
npm: 공급망 공격의 해
2025년은 npm 생태계에 공급망 공격이 집중된 해였습니다. 주요 사건은 다음과 같습니다.
표 5 2025~2026년 주요 npm 공급망 공격(출처: Nx 사후 분석, Socket, GitHub, Datadog Security Labs, Axios 사후 분석, TanStack 사후 분석)
| 시기 | 사건 | 방식과 규모 |
|---|---|---|
2025년 8월 26일 | Nx(s1ngularity) | GitHub Actions의 |
2025년 9월 8일 | chalk, debug 등 19개 패키지 | npm 지원팀을 사칭한 피싱( |
2025년 9월 14일 | Shai-Hulud | 탈취한 계정으로 |
2025년 11월 24일 | Shai-Hulud 2.0 |
|
2026년 3월 31일 | Axios | 메인테이너 PC를 사회공학과 원격 접속 트로이 목마(RAT)로 장악, |
2026년 5월 11일 | TanStack |
|
그림 7 chalk, debug 메인테이너에게 발송된 npm 지원팀 사칭 피싱 메일(출처: npm Author Qix Compromised via Phishing Email in Major Supply Chain Attack)
Shai-Hulud가 이전 공격과 달랐던 점은 스스로 퍼진다는 점입니다. 감염된 패키지를 설치한 개발자의 환경에서 npm 토큰을 찾으면, 그 개발자가 관리하는 다른 패키지에 악성 코드를 넣어 다시 배포했습니다. 2.0은 피해자 한 명당 최대 100개 패키지에 백도어를 넣었습니다. Datadog은 Bun 런타임을 쓴 이유를 Node.js 중심의 감시를 피하기 위한 것으로 추정했습니다(참고: Datadog Security Labs).
2026년에도 비슷한 웜이 이어졌습니다. 8월에는 감염된 keyv 6.0.0 릴리스로 400개 이상의 패키지가 감염되었고(참고: JFrog Security Research, Node Weekly 636호), 8월 말에는 Shai-Hulud를 복제한 'Mini Shai-Hulud' 웜을 퍼뜨린 TeamPCP의 일원으로 지목된 두 명이 호주에서 체포되어 기소되었습니다(참고: Help Net Security, Aikido, Node Weekly 640호). Endor Labs는 5월의 TanStack 공격도 같은 Mini Shai-Hulud 캠페인으로 분석했습니다(참고: Endor Labs).
그림 8 Shai-Hulud 2.0의 실행, 자격 증명 수집, 유출, 원격 제어, 자기 복제 단계(출처: The Shai-Hulud 2.0 npm worm: analysis, and what you need to know)
TanStack 사후 분석은 세 가지 취약점이 연결되어야 공격이 성립했다며 "각각은 필요하지만 어느 하나만으로는 충분하지 않다"고 정리했습니다(참고: TanStack 사후 분석).
npm의 대응: 토큰을 없애는 방향
GitHub은 2025년 9월 Shai-Hulud 직후 npm 보안 강화 계획을 발표했습니다. 로컬에서 게시할 때 2단계 인증(2FA)을 필수로 하고 쓰기 권한 토큰의 수명을 짧게 제한하며 CI에서는 토큰 대신 신뢰할 수 있는 게시(trusted publishing)를 쓰게 한다는 내용이었습니다(참고: Our plan for a more secure npm supply chain). 계획 발표보다 앞서 7월에 정식 출시된 신뢰할 수 있는 게시를 중심으로, 그 뒤 1년 동안 나머지 계획이 차례로 적용되었습니다.
- 신뢰할 수 있는 게시: 2025년 7월 정식 출시되었습니다. CI에서 OpenID Connect(OIDC)로 인증해 장기 토큰 없이 게시하고 출처 증명(provenance)도 자동으로 생성합니다(참고: npm trusted publishing with OIDC is generally available).
- classic 토큰 폐기: 2025년 11월 5일 classic 토큰 생성이 중단되었습니다. 기존 토큰의 전체 폐기는 처음에 11월 19일로 예고되었으나, 실제로 완료된 날짜는 12월 9일입니다. 쓰기 권한이 있는 granular 토큰은 2FA가 기본이 되었고 수명은 최대 90일로 제한되었습니다(참고: npm 토큰 변경 사전 공지, classic 토큰 폐기 완료 공지).
- 단계적 게시(staged publishing): 2026년 5월 npm 11.15.0과 함께 출시되었습니다.
npm stage publish로 올린 패키지는 메인테이너가 2FA로 승인해야 공개됩니다(참고: Staged publishing). - 게시 시점 악성 코드 검사: 2026년 7월부터 새로 게시된 패키지는 설치할 수 있게 되기 전에 자동으로 검사됩니다(참고: npm publish-time malware scanning).
# 단계적 게시: CI는 스테이징까지만, 공개는 사람이 2FA로 승인 npm stage publish npm stage list my-package npm stage approve <stage-id>
그림 9 npmjs.com에서 단계적 게시로 올라온 패키지를 승인하거나 거부하는 화면(출처: Staged publishing for npm packages)
설치하는 쪽의 변화는 npm 12에서 나왔습니다. 2026년 7월 출시된 npm 12는 의존성의 preinstall, install, postinstall 스크립트와 암묵적인 node-gyp 빌드를 기본으로 실행하지 않습니다. npm approve-scripts --allow-scripts-pending으로 승인 대기 중인 패키지를 확인하고, 필요한 패키지를 npm approve-scripts로 허용 목록에 추가해 package.json에 커밋합니다. Git 의존성과 원격 URL 의존성도 각각 --allow-git, --allow-remote를 지정해야 설치됩니다(참고: npm v12: install-time security). Shai-Hulud가 퍼진 경로가 바로 설치 스크립트였습니다.
다음 개념도는 설치 스크립트가 실행될 때 Shai-Hulud 같은 웜이 퍼지는 경로와, npm 12의 기본값이 그 경로를 끊는 지점을 보여 줍니다.
그림 10 설치 스크립트를 통해 계정에서 계정으로 퍼지는 웜과, npm 12가 설치 스크립트를 기본으로 막을 때의 차이(개념도)
다만 npm 12는 현재 Node.js 버전에는 포함되지 않습니다. Node.js 릴리스 워킹 그룹은 npm 12가 Node.js 22, 24, 26에 넣기에는 "지나치게 큰 변화(far too disruptive)"라고 판단했고 Node.js 27부터 포함하기로 했습니다(참고: nodejs/Release#1161, Node Weekly 641호). Node.js 24, 26에 포함된 npm 11은 11.16부터 package.json의 allowScripts와 strict-allow-scripts 설정으로 npm 12와 같은 정책을 미리 적용할 수 있습니다(참고: npm v12: install-time security). Node.js 22에 포함된 npm 10에서는 --ignore-scripts 설정으로 설치 스크립트를 막을 수 있습니다. 다만 이 설정은 의존성뿐 아니라 자기 프로젝트의 package.json에 있는 설치 단계 스크립트도 실행하지 않으므로 필요한 스크립트는 npm run으로 따로 실행해야 합니다(참고: npm config: ignore-scripts).
신뢰할 수 있는 게시에 대한 과신을 경계하는 목소리도 있습니다. William Woodruff는 "신뢰할 수 있는 게시는 인증 방식일 뿐이며, 패키지가 안전하거나 품질이 좋다는 것을 알려 주지 않는다"고 지적했습니다(참고: You shouldn't trust Trusted Publishing, Node Weekly 632호). TanStack 사례처럼 CI 자체가 뚫리면 게시용 OIDC 토큰도 탈취됩니다.
pnpm, Yarn, Corepack
2019년 글보다 한 해 앞선 2018년 JavaScript의 동향 글("2018년과 이후 JavaScript의 동향 - 브라우저 밖의 JavaScript")이 "그 외 패키지 관리자"로 짧게 소개한 pnpm은 대형 프로젝트의 기본 선택지가 되었습니다. State of JS 2025 모노레포 도구 문항에서 pnpm을 쓴다는 응답은 3,940명으로, npm Workspaces(2,129명)와 Yarn Workspaces(1,341명)를 앞섰습니다(참고: State of JS 2025: Other Tools).
pnpm은 보안 기본값을 바꾸는 데 npm보다 빨랐습니다. 2025년 1월 출시된 pnpm 10은 의존성의 설치 스크립트를 기본으로 실행하지 않도록 바꾸고 허용할 패키지를 따로 지정하게 했습니다(참고: pnpm 10.0.0). Bun은 처음부터 이 방식이었습니다. 인기 패키지 일부를 기본 허용 목록으로 두고 나머지는 trustedDependencies에 적은 패키지만 설치 스크립트를 실행합니다(참고: Bun: Lifecycle scripts). npm 12까지 오면서 주요 패키지 관리자의 기본값이 모두 같은 방향으로 맞춰졌습니다. 2026년 4월 pnpm 11은 게시된 지 하루가 지나지 않은 패키지 버전을 설치하지 않는 minimumReleaseAge를 기본값(1,440분)으로 켰습니다. pnpm 문서는 "대부분의 경우 악성 릴리스는 한 시간 안에 발견되어 레지스트리에서 제거된다"고 이 설정의 근거를 설명합니다(참고: pnpm: minimumReleaseAge). 저장소 인덱스는 수백만 개의 JSON 파일에서 하나의 SQLite 데이터베이스로 바뀌었습니다(참고: pnpm 11.0).
# pnpm-workspace.yaml: pnpm 11의 기본값과 빌드 허용 목록을 명시한 예 minimumReleaseAge: 1440 # 게시 후 24시간이 지난 버전만 설치 allowBuilds: esbuild: true # 설치 스크립트를 허용할 패키지
2026년 8월 26일 출시된 pnpm 12는 Rust로 다시 작성되었습니다. 기존 lockfile은 그대로 동작하고 대부분의 명령도 호환되면서 순환 의존성이 많은 대형 워크스페이스에서 peer 의존성 해석이 2~3배 빨라지고 메모리를 약 25% 덜 씁니다(참고: pnpm 12.0).
Yarn은 2019년 글에서 소개한 Yarn 2(Berry) 계열이 4.x로 이어졌습니다. 2026년 10월 최신 버전은 4.18.1입니다(참고: yarnpkg/berry 릴리스). Yarn 6부터는 Rust 기반의 새 저장소(zpm)에서 개발되며 2026년 10월 현재 릴리스 후보(6.0.0-rc.23) 단계입니다(참고: yarnpkg/zpm).
패키지 관리자 버전을 프로젝트별로 고정해 주던 Corepack은 낮은 채택률 등을 이유로 Node.js 25부터 함께 배포되지 않습니다(참고: nodejs/TSC#1697 투표 결과, Socket, nodejs/corepack#783).
JSR, vlt: 새 레지스트리
Deno 팀이 2024년 3월 1일 공개 베타로 선보인 JSR은 ESM 형식의 JavaScript와 TypeScript만 받는 패키지 레지스트리입니다. TypeScript 소스를 그대로 올리면 레지스트리가 타입 선언과 문서를 생성하고 npm 호환 계층을 통해 Node.js, Bun, pnpm, Yarn에서도 설치할 수 있습니다. 2025년 2월에는 독립 거버넌스 이사회가 꾸려졌습니다. Evan You, Isaac Schlueter(npm 창시자), James Snell, Luca Casonato, Ryan Dahl이 이사이며 재단에 가입하거나 별도 비영리 법인을 세우는 것을 목표로 합니다(참고: JSR has an open governance board). Deno 팀이 Cloudflare에 합류한 뒤에도 JSR은 계속 운영되며 인프라는 Cloudflare로 옮겨집니다(참고: Deno is joining Cloudflare).
그림 11 JSR 첫 화면, 2026년 10월 1일 캡처(출처: JSR)
# JSR 패키지를 npm 프로젝트에 추가 npx jsr add @std/path
vlt는 GitHub에서 npm CLI 팀을 이끌던 Darcy Clarke와 Isaac Schlueter, Node.js TSC 멤버 Ruy Adorno가 세운 회사의 패키지 관리자와 레지스트리입니다(참고: vlt: Introducing our team). 2026년 8월 1.0을 출시했습니다. CSS 선택자와 비슷한 문법으로 의존성 그래프를 조회하는 vlt query가 특징이고 60여 개의 선택자 중 약 30개가 악성 코드, CVE, 라이선스 같은 보안 항목입니다. 설치 스크립트를 실행하지 않고 내려받기만 하는 단계적 설치도 지원합니다. 호스팅 레지스트리는 npm API와 호환되어 npm, pnpm, Yarn, Bun, Deno에서 그대로 쓸 수 있습니다(참고: vlt 1.0).
# 악성 코드로 표시된 의존성 찾기 vlt query ':malware'
Isaac Schlueter가 JSR 이사회와 vlt 창업팀에 모두 이름을 올렸다는 점이 흥미롭습니다. 2019년의 도전자들이 npm을 대체하려 했다면, 2026년의 새 레지스트리는 npm과 호환되는 길을 택하고 그 위에서 TypeScript 지원이나 보안 기능으로 차별화합니다.
데스크톱 애플리케이션 개발 도구
Electron
2019년 글은 데스크톱 영역에서 "Electron이 계속 독주하고 있다"고 했습니다. 이 평가는 지금도 유효합니다. State of JS 2025의 모바일과 데스크톱 문항에서 Electron 앱을 개발한다는 응답은 1,746명으로, React Native(2,212명) 다음이었습니다(참고: State of JS 2025: Other Tools).
2019년 글을 쓸 때 Electron의 최신 버전은 6.0.10이었고 12주마다 메이저 버전을 냈습니다. Electron은 2021년 9월 Electron 15부터 릴리스 주기를 8주로 줄였습니다. Chromium이 4주 단위 마일스톤으로 바뀌면서 8주 단위 Extended Stable 릴리스를 함께 도입했고, Microsoft Store가 Chromium 기반 앱에 최신 버전에서 두 메이저 버전 이내를 유지하도록 요구했기 때문입니다. Electron은 새 주기를 Chromium의 Extended Stable에 맞추었습니다(참고: Electron moves to 8-week release cadence). 그 결과 2026년 10월 현재 최신 버전은 Electron 44(8월 24일 출시, 출시 당시 Chromium 152, Node.js 24.18)입니다(참고: Electron Releases).
그림 12 Electron 릴리스 페이지에 표시된 버전별 Chromium, Node.js 버전, 2026년 10월 1일 캡처(출처: Electron Releases)
2026년 6월 30일 출시된 Electron 43은 시작 속도 개선에 집중했습니다. 메인 프로세스가 내장된 Node.js 시작 스냅숏에서 부팅하고 프레임워크 번들과 프리로드 스크립트를 컴파일된 V8 바이트코드로 캐시합니다(참고: Electron 43.0.0).
Tauri, Electrobun
2019년 글이 소개한 React Desktop, Proton Native, Yue, NodeGUI는 Electron의 대안으로 자리 잡지 못했습니다. 대신 운영체제의 웹뷰를 쓰는 방식이 대안으로 자리 잡았습니다. Chromium을 앱마다 싣는 Electron과 달리 macOS의 WebKit, Windows의 WebView2 같은 시스템 웹뷰로 화면을 그려 앱 크기를 줄입니다.
Tauri는 백엔드를 Rust로 작성하고 화면은 시스템 웹뷰로 그리는 프레임워크입니다. 2024년 10월 출시된 Tauri 2.0은 iOS와 Android를 지원 대상에 더했고 기능을 플러그인으로 나누었으며 기존 허용 목록(allowlist) 방식을 권한(permission), 범위(scope), 기능 묶음(capability)으로 이루어진 접근 제어 모델로 바꾸었습니다(참고: Tauri 2.0 Stable Release). State of JS 2025에서는 978명이 Tauri를 쓴다고 답했습니다(참고: State of JS 2025: Other Tools).
그림 13 시스템 웹뷰의 프런트엔드와 Tauri 코어가 프로세스 간 통신(IPC)으로 통신하는 신뢰 경계 구조(출처: Tauri 2.0 Stable Release)
// src-tauri/capabilities/main.json: main 창에 허용할 권한만 지정
{
"identifier": "main-capability",
"windows": ["main"],
"permissions": ["core:window:default", "core:window:allow-set-title"]
}
2026년 2월 1.0을 출시한 Electrobun은 런타임으로 Bun을, 화면에 시스템 웹뷰를 씁니다. TypeScript로 앱을 작성하고 내부는 Zig와 C++로 구현되었으며 bsdiff의 Zig 포트로 변경분만 내려받는 업데이트를 지원합니다(참고: Electrobun v1). Electron이 Node.js를 앱에 넣었듯이, 새 런타임이 데스크톱 프레임워크의 기반이 되는 사례입니다.
모바일 애플리케이션 개발 도구
2019년 글은 모바일 영역을 "React Native 대 NativeScript의 구도"로 정리하면서도, React Native가 "아직 메이저 버전이 릴리스되지는 않았다"며 안정성을 과제로 꼽았습니다. 2026년 현재 React Native는 여전히 0.x 버전이지만 2019년 로드맵에 있던 새 아키텍처와 Hermes 전환은 모두 끝났습니다.
React Native: 새 아키텍처와 Hermes V1
2019년 글이 향후 계획으로 소개한 JSI(JavaScript Interface)는 Fabric 렌더러, TurboModules와 함께 '새 아키텍처'가 되었습니다. 6년의 개발 끝에 2024년 10월 React Native 0.76에서 새 프로젝트의 기본값이 되었고(참고: React Native 0.76), 2025년 10월 0.82는 새 아키텍처로만 동작하는 첫 버전이 되었습니다. newArchEnabled=false 설정은 무시됩니다(참고: React Native 0.82).
다음 개념도는 JavaScript에서 네이티브 기능을 호출할 때 브리지와 JSI가 어떻게 다른지 보여 줍니다.
그림 14 이전 아키텍처의 비동기 브리지와 새 아키텍처의 JSI가 네이티브 기능을 호출하는 방식(개념도)
2019년 7월 Android용으로 발표된 Hermes는 0.70부터 기본 엔진이었습니다. 0.82에서 실험 기능으로 추가된 Hermes V1은 2026년 2월 0.84에서 iOS와 Android의 기본 엔진이 되었고 같은 버전에서 레거시 아키텍처 코드도 빌드에서 제거되었습니다(참고: React Native 0.84). Meta는 JavaScript를 C 코드로 컴파일한 뒤 LLVM으로 기계어를 만드는 Static Hermes도 개발하고 있습니다. Devon Govett은 Less.js를 C 라이브러리로 컴파일해 Rust에서 호출하는 예를 공개했습니다(참고: How to Compile JavaScript to C with Static Hermes).
2026년 8월에 나온 0.87은 소스에서 생성한 엄격한 TypeScript API를 기본으로 바꾸어 react-native/Libraries/* 같은 깊은 경로 import를 타입 오류로 처리하고 CocoaPods 대신 Swift Package Manager를 쓰는 방식을 실험 기능으로 추가했습니다(참고: React Native 0.87). 2019년 글에서 주요 불만으로 소개한 CocoaPods 문제에 대한 또 하나의 답입니다.
그림 15 React Native 0.87의 엄격한 TypeScript API에서 TextInput의 타입 정보와 문서가 표시되는 화면(출처: React Native 0.87)
Expo
React Native 생태계에서 2019년 글 이후 가장 크게 성장한 것은 Expo입니다. React Native 공식 문서는 새 프로젝트에 Expo 같은 프레임워크를 쓰도록 권장하고 State of JS 2025에서 Expo를 쓴다는 응답은 1,513명으로 Electron 바로 뒤였습니다. 2026년 2월 Expo SDK 55는 레거시 아키텍처 지원을 끝냈고 Hermes 바이트코드의 차이만 내려보내는 무선(OTA) 업데이트 방식을 선택 기능으로 추가했습니다. Expo는 이 방식으로 업데이트 다운로드 시간이 약 75% 줄어들 것으로 추정했고 SDK 56부터 기본값으로 켜기로 했습니다(참고: Expo SDK 55). 6월 SDK 57에서는 큰 변경 없는 업그레이드를 더 자주 내는 새 릴리스 주기를 검토하기 시작했습니다(참고: Expo SDK 57).
NativeScript, Lynx, Capacitor
NativeScript는 2025년 11월 9.0에서 iOS와 Android 런타임이 ESM을 직접 이해하게 했고 Vite 기반 빌드를 추가했습니다(참고: NativeScript 9). 2026년 8월 9.1에서는 V8 14.9, require(esm), 웹 표준 오류 모델과 이벤트 루프, structuredClone이나 AbortController 같은 표준 전역 객체를 갖추었습니다(참고: NativeScript 9.1). 다만 State of JS 2025에서 NativeScript 사용 응답은 228명으로, 2019년의 'React Native 대 NativeScript' 구도는 React Native 쪽으로 기울었습니다.
새로운 선택지로는 ByteDance가 2025년 3월 공개한 Lynx가 있습니다. 메인 스레드에서 자체 엔진 PrimJS로 UI 작업을 처리하고 사용자 코드는 백그라운드 스레드에서 실행하는 듀얼 스레드 구조로, 첫 화면을 그릴 때까지 메인 스레드를 잠시 막아 빈 화면을 없앱니다. TikTok의 검색, Shop, LIVE 같은 기능에 쓰이며, ByteDance에 따르면 Lynx로 옮긴 웹 화면은 여는 속도가 2~4배 빨라졌습니다(참고: Lynx: Unlock Native for More). 웹뷰 기반의 Capacitor는 8이 안정판이고 2026년 5월 공개된 9 알파에서는 Cordova 호환 계층을 선택 사항으로 바꾸고 있습니다(참고: Capacitor 9 Starts Here).
그림 16 Lynx로 만든 TikTok의 LIVE, TikTok Studio, Shop, 검색 화면(출처: Lynx: Unlock Native for More)
PWA
2019년 글은 PWA가 데스크톱과 앱스토어로 영역을 넓히고 있지만 "iOS 등 PWA 지원이 미흡한 플랫폼"이 있어 "네이티브 앱을 대체할 수 있을 것이란 처음의 기대에는 아직 못 미치고 있다"고 했습니다. 7년 동안 가장 큰 변화는 바로 그 iOS에서 일어났습니다.
- iOS 16.4(2023년): 홈 화면에 추가한 웹 앱에서 Web Push, Badging API, 매니페스트의
id를 지원했습니다. 서드파티 브라우저에서도 홈 화면에 웹 앱을 추가할 수 있게 되었습니다(참고: Web Push for Web Apps on iOS and iPadOS). - iOS 17.4(2024년): Apple은 EU 디지털 시장법(DMA) 대응으로 EU에서 홈 화면 웹 앱을 없애려 했다가, 반발이 커지자 2024년 3월 1일 "EU에서 기존 홈 화면 웹 앱 기능을 계속 제공한다"며 계획을 철회했습니다(참고: 9to5Mac).
- iOS 26(2025년): 홈 화면에 추가한 모든 웹 사이트가 기본으로 웹 앱으로 열립니다. 매니페스트나
apple-mobile-web-app-capable메타 태그가 없어도 되고 사용자가 '웹 앱으로 열기'를 끌 수 있습니다(참고: News from WWDC25: WebKit in Safari 26 beta).
그림 17 iOS 26의 홈 화면에 추가 화면과 웹 앱으로 열기 설정(출처: News from WWDC25: WebKit in Safari 26 beta)
데스크톱에서는 2019년 글이 소개한 Chrome의 주소창 설치 버튼과 Microsoft Store 배포에 이어, Firefox가 2025년 9월 Firefox 143에서 Windows 작업 표시줄에 웹 사이트를 고정해 별도 창으로 실행하는 웹 앱 기능을 추가했습니다(참고: Firefox 143.0 Release Notes). 매니페스트 없이도 웹 앱이 되는 iOS 26 이후로는, 설치 자체보다 오프라인 동작과 알림 같은 기능을 점진적으로 더하는 일이 PWA 개발의 중심이 될 것으로 보입니다.
증강 현실과 가상 현실
2018년 JavaScript의 동향 글은 WebVR이 WebXR Device API로 바뀌는 과정을 소개하며 "아직 기술의 표준화가 성숙한 단계에 진입하지 못한 상태"라고 했습니다. WebXR Device API는 2026년 6월 9일 자 문서 기준으로 W3C 후보 권고안 초안(Candidate Recommendation Draft) 단계입니다(참고: WebXR Device API).
8년 사이 달라진 점은 지원 기기입니다. Apple Vision Pro의 Safari는 2024년 9월 visionOS 2에서 WebXR의 immersive-vr 세션과 핸드 트래킹, 시선과 손가락 집기로 입력하는 transient-pointer 입력 방식을 지원했습니다(참고: WebKit Features in Safari 18.0). Android XR의 Chrome은 AR 모듈, 히트 테스트, 앵커, 깊이 감지까지 지원합니다(참고: Develop for the web on Android XR). 웹 밖에서는 React Native가 2026년 2월 Meta Quest를 공식 지원한다고 밝혔습니다. Meta Quest의 Horizon OS가 Android 기반이라 기존 Android 도구를 거의 그대로 쓰고 Expo Go로 헤드셋에서 바로 실행해 볼 수 있습니다(참고: React Native Comes to Meta Quest).
그림 18 visionOS의 Safari에서 시선과 손가락 집기로 말을 옮기는 WebXR 체스 데모(출처: WebKit Features in Safari 18.0)
그림 19 Meta Quest 헤드셋에서 실행한 React Native 앱(출처: React Native Comes to Meta Quest)
OpenJS Foundation
2019년 글은 Node.js Foundation과 JS Foundation이 합병해 OpenJS Foundation이 출범했고 32개 프로젝트가 소속되어 있다고 전했습니다. 2026년 현재 프로젝트 페이지에는 Node.js, Electron, webpack, Express, jQuery, Appium, Dojo가 영향력이 큰 Impact 프로젝트로 올라 있고 그 밖에 20여 개의 At-Large 프로젝트와 인큐베이션 프로젝트가 있습니다(참고: OpenJS Foundation Projects). 2025년 10월에는 Google이 소유하던 웹 컴포넌트 라이브러리 Lit이 합류했습니다(참고: Lit is Joining the OpenJS Foundation!).
그림 20 OpenJS Foundation 프로젝트 페이지의 Impact 프로젝트 목록, 2026년 10월 1일 캡처(출처: OpenJS Foundation Projects)
재단의 최근 활동은 보안과 유지보수 부담에 집중되어 있습니다. 재단은 2025년 CVE 번호 발급 기관(CNA)이 되었는데, 2026년 9월 17일부터 10월 6일까지 이 업무를 쉬었고 10월 7일 재개를 예고했습니다. AI로 만든 저품질 취약점 보고가 크게 늘어 소수의 자원봉사자가 감당할 수 없었다는 이유입니다(참고: The OpenJS Foundation CNA is taking a coordinated break). Node.js의 버그 바운티는 외부 자금(Internet Bug Bounty)이 끊겨 2026년 4월 일시 중단되었습니다. 발표문은 "자원봉사로 운영되는 오픈소스 프로젝트로서 Node.js는 바운티를 유지할 자체 예산이 없다"고 밝혔습니다(참고: Security Bug Bounty Program Paused Due to Loss of Funding).
AI 도구로 인한 변화
AI 코딩 도구는 언어와 표준을 만드는 방식에도 영향을 주었지만, 브라우저 밖의 JavaScript에서는 영향이 더 직접적입니다. AI 도구 자체가 Node.js와 npm 위에서 만들어지고 배포되며 그 때문에 런타임과 패키지 레지스트리가 AI 도구의 공급망이 되었습니다.
AI 도구의 배포 경로가 된 런타임과 npm
에이전트가 외부 도구와 데이터에 접근하는 표준인 MCP(Model Context Protocol)의 공식 TypeScript SDK(@modelcontextprotocol/sdk)는 9월 28일부터 10월 4일까지 한 주 동안 npm에서 약 7,623만 번 내려받았습니다. 1년 전 같은 주(약 715만)의 10배가 넘고 같은 시기 PyPI의 Python SDK(mcp, 약 5,979만)보다 많습니다(참고: npm 다운로드 통계, PyPI Stats). MCP 공식 참조 서버 저장소도 대부분 TypeScript와 JavaScript로 작성되어 있습니다(참고: modelcontextprotocol/servers).
터미널에서 동작하는 AI 코딩 도구도 npm으로 배포됩니다. 같은 주 npm 다운로드는 Anthropic의 Claude Code(@anthropic-ai/claude-code)가 약 1,479만, OpenAI의 Codex CLI(@openai/codex)가 약 2,561만이었습니다. Google의 Gemini CLI는 TypeScript로 작성되어 번들된 JavaScript를 Node.js로 실행합니다. 반면 Codex CLI 저장소의 주 언어는 Rust이고 Claude Code는 Bun으로 빌드한 단일 실행 파일입니다(참고: Bun is joining Anthropic). 두 패키지는 운영체제와 CPU별 네이티브 바이너리를 optionalDependencies로 나누어 두고 설치 시점에 맞는 바이너리를 고르는 구조입니다(참고: @anthropic-ai/claude-code, @openai/codex, openai/codex). npm이 JavaScript 패키지가 아닌 실행 파일의 배포 채널로도 쓰입니다.
Anthropic이 Bun을 인수한 이유도 이 흐름 위에 있습니다. Bun을 만든 Jarred Sumner는 인수 발표 글에서 "새로운 코드의 대부분이 AI 에이전트에 의해 작성되고 테스트되고 배포된다면" 런타임의 안정성과 성능이 그만큼 중요한 인프라가 된다고 설명했습니다(참고: Bun is joining Anthropic). Deno가 LLM이 생성한 코드를 실행하는 Deno Sandbox를 내놓은 것도 같은 수요를 겨냥합니다. Ryan Dahl은 Cloudflare 합류 발표에서도 저렴한 서버리스 실행, 영속 상태, WebSocket을 함께 갖춘 Durable Objects가 에이전트 실행 환경(agent harness)에 특히 유용하다며 가장 기대하는 분야로 AI 에이전트를 꼽았습니다(참고: Deno is joining Cloudflare).
AI 도구를 노리는 공급망 공격
AI 도구가 개발자 PC에 설치되면서 공급망 공격은 그 도구를 이용하기 시작했습니다. 2025년 8월 Nx 패키지 공격(s1ngularity)에서 악성 postinstall 스크립트는 개발자 PC에 설치된 Claude, Gemini, Amazon Q의 CLI를 찾아 실행했습니다. Wiz의 분석에 따르면 악성 코드는 각 도구의 확인 절차를 건너뛰는 플래그(--dangerously-skip-permissions, --yolo, --trust-all-tools)를 붙여 파일 시스템의 비밀값을 찾게 했고 수백 건에서 성공했으며 일부는 AI 제공자의 안전장치가 막았습니다(참고: Nx 사후 분석, Wiz). 사람이 쓰는 명령을 대신 실행해 주는 에이전트가 공격자에게는 이미 설치된 정찰 도구가 되었습니다.
그림 21 피해자 PC의 AI CLI(Claude, Gemini, Q)로 민감 정보를 찾은 Nx 공급망 공격(s1ngularity)의 흐름(출처: s1ngularity: supply chain attack leaks secrets on GitHub: everything you need to know)
학습 데이터의 공백도 보안 문제로 이어집니다. Socket이 소개한 2026년 연구는 다섯 개의 최신 LLM이 생성한 약 20만 개의 코드 응답을 분석했는데, 모델에 따라 4.62~6.10%의 응답에 존재하지 않는 패키지 이름이 들어 있었습니다. 다섯 모델이 공통으로 지어낸 이름이 127개였고 그중 53개(npm 12개, PyPI 41개)는 누구나 등록할 수 있는 상태였습니다(참고: Slopsquatting Targets Across Frontier LLMs). 공격자가 이 이름으로 악성 패키지를 올리면 여러 모델의 사용자가 한꺼번에 피해를 볼 수 있습니다. 이런 공격을 슬롭스쿼팅(slopsquatting)이라고 부릅니다. 에이전트가 npm install을 직접 실행하는 환경이라면, 앞에서 본 설치 스크립트 차단과 minimumReleaseAge 같은 기본값이 사람뿐 아니라 에이전트에게도 안전장치가 됩니다.
런타임을 다시 쓰는 AI
AI 코딩 도구는 런타임을 만드는 데에도 쓰이기 시작했습니다. Anthropic에 인수된 뒤인 2026년 7월, Jarred Sumner는 Zig로 작성된 Bun 코드 535,496줄을 Rust로 옮긴 과정을 공개했습니다(참고: Rewriting Bun in Rust). Claude Code에서 약 50개의 워크플로를 11일(5월 3일~14일) 동안 계속 돌렸고 Claude 인스턴스를 구현자와 리뷰어로 나누어 서로의 코드를 검토하게 했습니다. 병합된 변경량은 100만 줄이 넘었지만 건너뛰거나 삭제한 테스트는 없었습니다. Rust로 옮긴 Bun 1.4.0은 1.3.14에서 재현되던 버그 128개를 고쳤습니다. 글 첫머리에는 Bun이 Anthropic에 인수되었고 저자가 Anthropic에서 일한다는 사실이 밝혀져 있습니다.
그림 22 Bun의 Rust 이식 브랜치에 올라온 시간대별 커밋 수(출처: Rewriting Bun in Rust)
Wasmer가 Codex로 Node.js 호환 런타임 Edge.js를 만든 사례도 있습니다(참고: Wasmer: Edge.js). 두 사례 모두 Node.js 테스트 묶음처럼 결과를 판정할 기준이 분명한 작업이었고, 이런 작업에서 AI 도구의 효과가 크게 나타났습니다.
오픈소스 프로젝트의 AI 정책
Node.js에서는 AI로 만든 기여를 두고 논쟁이 벌어졌습니다. 2026년 1월 Node.js 코어에 가상 파일 시스템(node:vfs)을 추가하는 PR(올라올 당시 약 1만 9천 줄)이 올라왔는데, 작성자가 "Claude Code 토큰을 상당히 많이 써서 만들었다"고 밝힌 것이 계기였습니다. Node.js 코어 기여자 Fedor Indutny는 Node.js 코어에서 AI 보조 개발을 허용하지 말자는 청원을 시작했고 기여 출처 확인서(DCO, Developer Certificate of Origin) 요건을 충족하는지, 리뷰어가 기계가 만든 코드를 검증할 수 있는지 같은 문제를 제기했습니다(참고: No AI code in Node.js Core). 같은 작성자가 범위를 줄여 올린 최소 기능 버전이 5월 병합되어 Node.js 26.4.0에 포함되었고 원래 PR은 9월 병합되지 않은 채 닫혔습니다(참고: nodejs/node#61478, nodejs/node#63115).
이후 Node.js는 2026년 8월 AI 사용 정책을 문서로 정리했습니다. 요지는 다음과 같습니다(참고: Node.js AI use policy and guidelines).
- AI 도구 사용을 금지하지 않습니다. 다만 사용했다면 그 사실과, 생성된 결과를 직접 어떻게 검증했는지 밝혀야 합니다.
- 기여자가 직접 이해하고 테스트하고 검증하지 않은 AI 생성 코드는 리뷰 없이 닫을 수 있습니다.
- 사전 승인 없이 자동화 도구가 PR을 여는 것을 금지합니다.
- 'good first issue'를 AI로 자동 수정하는 것을 금지합니다. 이런 이슈는 사람인 새 기여자가 코드베이스를 익히도록 남겨 둔 것이기 때문입니다.
이 문서는 OpenJS Foundation의 AI Coding Assistants Policy에 맞춘다고 밝혔습니다. 재단 차원의 논의는 2025년 6월 "AI 보조 개발을 허용하는가"라는 이슈에서 시작되었습니다(참고: openjs-foundation/cross-project-council#1509).
보안 보고도 한계에 부딪혔습니다. Node.js 보안 팀은 저품질 보고가 "감당할 수 있는 수준을 넘었다"며 2026년 1월부터 HackerOne 평판 점수(Signal) 1.0 이상인 연구자만 보고하게 했고, 2월에는 점수가 없는 신규 연구자도 HackerOne으로는 보고할 수 없게 했습니다(참고: Node.js: HackerOne Signal requirement). 앞에서 본 OpenJS Foundation CNA의 휴식 공지는 원인을 이렇게 설명했습니다.
AI는 보안 보고를 만드는 문턱을 낮췄지만, 그것을 처리하는 비용은 낮추지 않았습니다.
AI has lowered the barrier to generating security reports, but not the cost of handling them.
AI 도구는 Bun 53만 줄을 11일 만에 옮길 만큼 코드를 만드는 비용을 낮추었습니다. 그러나 그 코드와 보고를 검토하는 사람의 시간은 그대로입니다. 브라우저 밖의 JavaScript 생태계에서 2026년의 병목은 코드를 만드는 일이 아니라 검증하는 일로 옮겨 가고 있습니다.
마치며
2019년 글은 Deno를 두고 "Node.js와 같은 성공을 거둘 수 있을지는 아직 미지수"라고 썼습니다. 7년 뒤의 답은 예상과 달랐습니다. Deno도 Bun도 Node.js를 대체하지 않았습니다. Bun은 Anthropic에 인수되었고 Deno 팀은 Cloudflare에 합류하며 Deno 런타임 개발을 1년 뒤 끝내기로 했습니다. 그사이 세 런타임 모두 Node.js 호환과 웹 표준 API로 수렴했고 Node.js는 Deno가 제기한 문제(TypeScript 직접 실행, 권한 모델, 내장 도구)를 차례로 받아들였습니다. 경쟁의 결과가 한쪽의 승리가 아니라 공통 기반의 확장으로 나타났고 WinterTC는 그 공통 기반을 표준으로 만들고 있습니다.
패키지 영역에서 2019년의 걱정은 npm이라는 회사의 존속이었습니다. 지금의 걱정은 레지스트리가 아니라 그 위의 계정과 CI, 그리고 설치하는 순간 실행되는 코드입니다. 10년 넘게 당연하던 postinstall 기본 실행이 npm 12, pnpm, Bun에서 모두 꺼졌다는 사실은, 생태계가 편의보다 안전을 기본값으로 택하기 시작했다는 뜻으로 읽힙니다. 에이전트가 사람 대신 npm install을 실행하는 시대에 이 기본값의 무게는 더 커질 것입니다.
2019년 글 1부는 오픈소스에 보상을 돌려주지 않는 문제를 고민해 보자는 말로 끝났습니다. 2026년 Node.js의 버그 바운티는 자금이 끊겨 일시 중단되었고 재단의 보안 담당자들은 AI가 쏟아 낸 보고 때문에 휴식을 공지했습니다. AI가 코드를 만드는 비용을 낮출수록, 그 코드를 검토하고 책임지는 사람의 가치는 높아집니다. 브라우저 밖의 JavaScript가 다음 7년을 어떻게 보낼지는 런타임의 성능보다 그 사람들을 어떻게 지탱하느냐에 달려 있을 것입니다.





















