JavaScript 런타임의 역사와 Node.js의 한계, Deno와 Bun의 등장 배경, WinterCG 표준화까지 현대 런타임 생태계를 조망합니다.
JavaScript는 더 이상 브라우저 안에만 머무르지 않습니다. 서버, CLI 도구, IoT 디바이스, 심지어 머신러닝 파이프라인까지 JavaScript가 닿지 않는 영역을 찾기 어려운 시대가 되었습니다. 이 모든 것을 가능하게 한 핵심 기술이 바로 런타임(Runtime) 입니다.
런타임은 JavaScript 코드를 실행하는 환경 그 자체입니다. 어떤 런타임을 선택하느냐에 따라 프로젝트의 성능, 보안, 개발 생산성이 근본적으로 달라집니다. 2024년 이후 JavaScript 런타임 생태계는 Node.js, Deno, Bun이라는 세 가지 선택지를 중심으로 재편되었고, 각각은 서로 다른 철학과 강점을 가지고 경쟁하고 있습니다.
이 시리즈에서는 그중에서도 Deno 2를 중심으로, 현대 JavaScript 런타임이 어떤 방향으로 진화하고 있는지를 깊이 있게 살펴봅니다.
2009년 Ryan Dahl이 발표한 Node.js는 JavaScript 생태계에 혁명을 일으켰습니다. Google의 V8 엔진 위에 이벤트 루프와 비동기 I/O를 결합한 이 런타임은, 프론트엔드 개발자들이 서버 개발까지 할 수 있는 길을 열었습니다.
1. V8 엔진 기반의 고성능 JavaScript 실행
2. 이벤트 기반 비동기 I/O (libuv)
3. npm을 통한 패키지 생태계
4. 단일 언어로 풀스택 개발 가능Node.js의 성공은 압도적이었습니다. npm은 세계 최대의 패키지 레지스트리로 성장했고, Express, Koa, NestJS 같은 프레임워크들이 등장하면서 서버 개발의 표준처럼 자리 잡았습니다.
그러나 Node.js의 창시자인 Ryan Dahl 본인이 2018년 JSConf EU에서 "10 Things I Regret About Node.js"라는 발표를 통해 Node.js의 근본적인 설계 결함을 인정했습니다.
Ryan Dahl이 지적한 주요 후회 사항은 다음과 같습니다. 보안 부재(기본적으로 모든 파일/네트워크 접근 허용), Promise 미도입(초기 설계에서 Promise를 제거한 결정), 빌드 시스템(GYP 의존), package.json의 과도한 역할, node_modules의 복잡성, require 확장자 생략, index.js 암묵적 해석 등이 있습니다.
이 발표는 단순한 회고가 아니었습니다. 그는 이 후회들을 바탕으로 새로운 런타임을 만들겠다고 선언했고, 그것이 바로 Deno입니다.
Node.js가 오랫동안 쌓아온 레거시는 몇 가지 구조적 문제를 안고 있습니다.
// CommonJS 방식
const express = require('express');
// ESM 방식
import express from 'express';
// 두 모듈 시스템이 공존하면서 발생하는 호환성 문제는
// 여전히 Node.js 생태계의 큰 고민거리입니다.보안 모델의 부재도 심각한 문제입니다. Node.js로 실행하는 스크립트는 기본적으로 파일 시스템, 네트워크, 환경 변수 등 모든 시스템 자원에 접근할 수 있습니다. npm 패키지를 설치하는 순간, 해당 패키지의 모든 코드가 시스템 전체에 대한 권한을 갖게 된다는 뜻입니다. 실제로 이 문제로 인한 공급망 공격(Supply Chain Attack)이 반복적으로 발생해 왔습니다.
Deno는 "Node"의 애너그램(anagram)이자, Node.js의 설계 결함을 처음부터 수정하겠다는 의지의 표현입니다. 2018년에 발표되고 2020년 1.0이 출시된 Deno는 다음과 같은 핵심 원칙을 내세웠습니다.
Deno 1.x는 혁신적이었지만, npm 생태계와의 단절이 가장 큰 진입 장벽이었습니다. 수백만 개의 npm 패키지를 사용할 수 없다는 것은 실무에서 치명적인 제약이었습니다.
2024년 출시된 Deno 2는 이 문제를 정면으로 해결했습니다.
Deno 2의 가장 큰 변화는 npm 패키지의 네이티브 지원입니다. npm: 접두사를 통해 npm 패키지를 직접 import할 수 있으며, node_modules 디렉토리 생성도 선택적으로 지원합니다. 이를 통해 기존 Node.js 프로젝트에서 Deno로의 마이그레이션 장벽이 크게 낮아졌습니다.
// npm: 접두사로 npm 패키지를 직접 사용
import express from "npm:express@4";
import chalk from "npm:chalk@5";
const app = express();
app.get("/", (_req, res) => {
res.send(chalk.green("Hello from Deno 2!"));
});
app.listen(3000);2022년 Jarred Sumner가 공개한 Bun은 완전히 다른 각도에서 런타임 전쟁에 뛰어들었습니다. "빠르게 만들 수 있으면 빠르게 만든다"라는 철학 아래, 성능을 최우선으로 설계된 런타임입니다.
Bun의 기술적 차별점은 명확합니다.
| 특성 | Node.js | Deno | Bun |
|---|---|---|---|
| JavaScript 엔진 | V8 | V8 | JavaScriptCore |
| 구현 언어 | C++ | Rust | Zig |
| 패키지 매니저 | npm/yarn/pnpm | deno add | bun install |
| TypeScript | 별도 설정 필요 | 기본 지원 | 기본 지원 |
| 번들러 내장 | 없음 | 없음 | 있음 |
Bun은 특히 패키지 설치 속도와 서버 시작 시간에서 압도적인 벤치마크를 보여주며 주목을 받았습니다. 하지만 안정성과 호환성 측면에서는 아직 성숙 과정에 있습니다.
세 런타임은 각기 다른 가치를 강조합니다.
Node.js는 압도적인 생태계와 검증된 안정성이 강점입니다. 대규모 프로덕션 환경에서의 실적이 풍부하고, 거의 모든 라이브러리와 프레임워크가 Node.js를 지원합니다.
Deno는 보안과 개발자 경험(DX)을 핵심 가치로 내세웁니다. 권한 기반 보안 모델, 웹 표준 API 준수, TypeScript 네이티브 지원, 내장 도구 체인이 특징입니다.
Bun은 극한의 성능을 추구합니다. 패키지 설치, 서버 시작, HTTP 처리 등 모든 영역에서 속도를 최적화하며, 번들러와 테스트 러너까지 내장합니다.
세 가지 런타임이 각자의 방식으로 발전하면서, 코드의 이식성(Portability)이 새로운 과제로 떠올랐습니다. Node.js에서 작동하는 코드가 Deno에서는 동작하지 않고, 그 반대도 마찬가지인 상황이 빈번했습니다.
이 문제를 해결하기 위해 등장한 것이 WinterCG(Web-interoperable Runtimes Community Group) 입니다.
WinterCG는 W3C 산하의 커뮤니티 그룹으로, 서버 사이드 JavaScript 런타임 간의 상호 운용성을 위한 표준을 정의합니다. Deno, Cloudflare Workers, Vercel Edge Runtime 등이 참여하고 있으며, 웹 브라우저의 표준 API를 서버 환경에서도 동일하게 사용할 수 있도록 하는 것을 목표로 합니다.
WinterCG가 정의하는 핵심 API는 다음과 같습니다.
// 이 코드는 Deno, Cloudflare Workers, Vercel Edge에서 동일하게 동작합니다
export default {
async fetch(request: Request): Promise<Response> {
const url = new URL(request.url);
if (url.pathname === "/api/data") {
const data = { message: "WinterCG 호환 API" };
return new Response(JSON.stringify(data), {
headers: { "Content-Type": "application/json" },
});
}
return new Response("Not Found", { status: 404 });
},
};Request, Response, URL, fetch, crypto 등 브라우저에서 이미 표준화된 API를 서버에서도 그대로 사용할 수 있게 하는 것이 WinterCG의 핵심 비전입니다. Deno는 처음부터 이 방향을 추구해 왔기에, WinterCG 호환성에서 가장 앞서 있습니다.
2026년 현재, Node.js는 여전히 압도적인 시장 지배력을 유지하고 있습니다. 그러나 새로운 프로젝트에서 Deno와 Bun의 채택률은 꾸준히 증가하고 있습니다.
Node.js
- 여전히 서버 사이드 JS의 표준
- Node 22+ LTS에서 ESM 기본 지원 강화
- Corepack으로 패키지 매니저 통합 관리
Deno 2.x
- npm 완전 호환으로 실용성 확보
- Deno Deploy를 통한 엣지 배포 생태계 구축
- JSR (JavaScript Registry)로 새로운 패키지 표준 제안
Bun 1.x
- macOS/Linux에서 안정적인 성능
- 번들러, 테스트 러너, 패키지 매니저 올인원
- Windows 지원 개선 진행 중런타임 선택은 프로젝트의 특성에 따라 달라져야 합니다.
기존 프로젝트를 유지보수하거나 대규모 팀에서 검증된 기술이 필요하다면 Node.js가 여전히 안전한 선택입니다. 보안이 중요하고 TypeScript를 기본으로 사용하며 깔끔한 개발 환경을 원한다면 Deno 2가 적합합니다. 빌드 속도와 서버 성능이 최우선이고, 얼리 어답터(Early Adopter) 성향이라면 Bun을 고려할 수 있습니다.
런타임 선택은 기술적 우열만으로 결정할 문제가 아닙니다. 팀의 경험, 프로젝트의 요구사항, 배포 환경, 장기적인 유지보수 계획 등을 종합적으로 고려해야 합니다.
이 시리즈에서는 Deno 2를 중심으로 현대 JavaScript 런타임을 깊이 있게 탐구합니다.
다음 장에서는 Deno 2의 내부 구조를 파헤치며, V8 엔진과 Rust 기반 아키텍처가 어떻게 조화를 이루는지 살펴봅니다.
이 글이 도움이 되셨나요?
Deno 2의 내부 아키텍처를 분석합니다. V8 엔진, Tokio 비동기 런타임, Rust 기반 구조, 단일 실행 파일 설계, 그리고 내장 도구 체인의 동작 원리를 살펴봅니다.
Deno의 권한 기반 보안 모델을 심층 분석합니다. 각 권한 플래그의 동작 원리, Node.js와의 보안 비교, 공급망 공격 방어, 그리고 실무 보안 모범 사례를 다룹니다.
Deno 2의 npm 호환성, JSR(JavaScript Registry), import map, deno add를 통한 패키지 관리, 그리고 Node.js에서 Deno로의 마이그레이션 전략을 다룹니다.