Skip to content
Published on

Deno 2·3 심층 분석 2026 — Node 호환의 시대, JSR·Fresh 2·Deno KV까지 (런타임 베팅이 어디로 갔나)

Authors

프롤로그 — Ryan Dahl의 두 번째 자기 부정

Ryan Dahl은 2009년 Node를 만들었고, 2018년 JSConf EU에서 "Node에서 후회하는 10가지"라는 유명한 발표를 했다. 그리고 Deno를 만들었다. 보안은 기본 deny, TS는 일급, 의존성은 URL import, package.json은 없다 — 모든 것이 Node에 대한 명시적인 답이었다.

그런데 2024년 9월, Deno 2가 나왔다. 가장 큰 변화는 자기 부정이다.

  • package.json 지원 — 1급 시민으로.
  • node_modules 디렉토리 지원 — 옵션이지만 활성화 가능.
  • npm 레지스트리에서 패키지 import — npm:/jsr: specifier로.
  • deno install을 npm 호환 패키지 매니저로.
  • workspace(모노레포) 지원.

Deno가 처음에 거부했던 거의 모든 Node의 디자인 결정을, 6년이 지나서 받아들였다. 자존심을 죽이고.

이건 후퇴인가, 진화인가. 둘 다다. 이상주의에서 실용주의로의 전환이고, 동시에 JS 생태계의 현실(npm은 사라지지 않는다)을 인정한 베팅이다.

이 글은 Deno 2 출시 후 약 20개월이 지난 2026년 5월 시점에서, Deno의 베팅이 어디까지 왔는지, Bun과 Node 22+와의 삼파전이 어떻게 정리됐는지, 그리고 보안 모델·JSR·Fresh 2·Deno KV가 현실에서 어떤 자리를 차지했는지를 정리한다.


1장 · Deno 2의 핵심 — Node 호환이 기본이 되다

Deno 1의 세계관, 그리고 그 한계

Deno 1은 순수한 세계를 그리려 했다.

  • URL import — import { foo } from "https://deno.land/std/...";
  • 명시적 권한 — deno run --allow-net=api.example.com server.ts
  • TypeScript 일급 — 설정 없이 .ts 실행.
  • node_modules 없음, package.json 없음.

문제는 단순했다. JS 세계의 90%가 이미 npm 위에 있었다. Express, React, Prisma, AWS SDK, Sentry, Stripe SDK — 다 npm. Deno는 처음에 호환 레이어로 npm: specifier를 추가했지만, 진짜 production에 가져가려면 부족했다. package.json에 적힌 의존성을 그대로 못 읽고, node_modules 풀스택 도구가 다 깨지고, monorepo 워크플로우가 어색했다.

Deno 2의 답은 명확했다. "Node가 했던 방식 그대로도 돈다."

무엇이 바뀌었나 (2024년 9월)

# Deno 2 — 기존 Node 프로젝트에서
deno install            # package.json 읽어서 node_modules 생성
deno run npm:express    # npm 패키지 직접 실행
deno task dev           # package.json의 scripts.dev 실행
영역Deno 1Deno 2
package.json무시 / 부분 지원1급 — deno install이 읽음
node_modules의도적으로 없음옵션 — nodeModulesDir: auto
npm 패키지npm: specifier동일 + package.json에서 자동
deno installURL 기반 binary installNode 호환 패키지 매니저
deno run npm:foo부분 지원안정적, 광범위 호환
workspace없음1급 — deno.jsonworkspace 필드

Deno 2의 모토는 더 이상 "Node를 대체한다"가 아니다. **"Node와 Deno 사이의 마찰을 0에 가깝게 만든다"**다.

마이그레이션이 쉬워졌나

실제로 기존 Node 프로젝트를 가져다 Deno로 도는지 시도해봤다.

  • 작은 Express API — 5분 안에 도는 경우 많음. deno run --allow-net --allow-read npm:tsx server.ts.
  • Next.js — 동작. 다만 next dev/next build는 Node를 직접 부르는 일이 많아 권한 모델의 의미가 흐려짐.
  • Prisma + Postgres — 동작. native binary 호환에 약간의 마찰이 있을 수 있음.
  • AWS SDK v3 — 거의 그대로 동작.

처음 1년 마찰이 큰 영역은 native addon(sharp, canvas, bcrypt-native 같은 C++ 바인딩)이었고, 2025년 동안 N-API 호환이 점진적으로 좋아졌다. 2026년 mid 시점에서 일반 npm 패키지의 90% 이상은 별 문제 없이 Deno 2에서 돈다.


2장 · deno install — npm 호환 패키지 매니저

두 모드

deno install은 두 가지 모드로 동작한다.

# 글로벌 binary 설치 (Deno 1부터)
deno install -gA --name lint jsr:@std/cli/parser

# 프로젝트 의존성 설치 (Deno 2 신규)
deno install            # package.json 읽기, node_modules 생성
deno install --add npm:express@4   # 새 의존성 추가
deno install --add jsr:@hono/hono  # JSR 의존성 추가

두 번째 모드가 패러다임 전환이다. npm install, pnpm install, yarn install을 그대로 대체할 수 있는 명령이 된 것이다.

속도와 lockfile

hot cache, 500개 deps:
  npm install:    14s
  pnpm install:    4s
  bun install:     1.3s
  deno install:    2.1s

bun install만큼은 아니지만, pnpm install보다 빠르고, npm install보다는 한참 빠르다. lockfile은 deno.lock (텍스트 JSON)이고, 처음부터 diff-friendly로 설계됐다. Bun이 binary lockfile로 한 번 헛발 디딘 것과 대조적이다.

node_modules 모드

// deno.json
{
  "nodeModulesDir": "auto",   // 또는 "manual" 또는 false
  "lock": true
}

auto로 두면 package.json을 읽고 자동으로 node_modules를 만든다. manual은 npm/pnpm/yarn으로 깔린 기존 node_modules를 그대로 쓴다 (큰 monorepo 이전 시나리오). false이면 Deno 1 스타일의 글로벌 캐시만 사용.

이 옵션이 있다는 것 자체가 이상주의를 버리고 실용주의를 택한 증거다.


3장 · deno run으로 npm 패키지 직접 실행

npm: specifier의 진화

Deno 2의 모토 중 하나는 **"npm 패키지를 추가 설정 없이 import한다"**이다.

// app.ts
import express from "npm:express@4";
import { z } from "npm:zod";
import OpenAI from "npm:openai";

const app = express();
app.get("/", (_, res) => res.json({ ok: true }));
app.listen(3000);
deno run --allow-net --allow-read --allow-env app.ts

이게 그냥 돈다. package.json도 필요 없고, node_modules도 필요 없다 (글로벌 캐시에 가져옴). Bun과 Node가 package.json을 필수로 요구하는 것과 비교해, 단일 파일 스크립트에서 Deno가 가장 매끄럽다.

Bun과 Node와의 비교

# 단일 파일 npm 의존성 스크립트

# Deno
deno run --allow-net script.ts

# Bun
bun script.ts            # bun add 했어야 함, 또는 inline shebang trick

# Node
npm init -y && npm i express && node script.js

Quick script + npm 한두 개의 영역에서는 Deno가 dev 경험 우세. 이건 Deno 1부터 이어진 강점이 Deno 2에서도 살아남은 영역이다.


4장 · JSR — JavaScript Registry의 베팅

왜 또 다른 레지스트리

JSR(jsr.io)은 Deno 팀이 2024년 초 출시한 새 JavaScript 레지스트리다. npm이 이미 있는데 왜 또?

JSR의 베팅 명제는 이렇다.

  1. TS-native publishing — TS 소스를 그대로 publish. 받는 쪽이 빌드 도구를 골라 쓴다. (npm은 보통 컴파일된 JS+.d.ts 묶음.)
  2. 표준 ESM only — CJS 없음, package.json의 미로 없음.
  3. runtime-agnostic — Deno뿐 아니라 Node, Bun, browser에서 import 가능.
  4. 품질 점수score로 문서·테스트·타입의 완성도 표시.
  5. scope 1급 시민@scope/package 모델이 기본.

사용 예

// 그냥 import
import { parse } from "jsr:@std/cli/parser";
import { Hono } from "jsr:@hono/hono";
# package.json 스타일
deno install --add jsr:@hono/hono
# Node에서도 사용 가능
npx jsr add @hono/hono
# 또는 직접 — 빌드된 형태로 받음

채택 현실 — 2026 mid

카테고리JSR 채택
Deno 1st-party @std 라이브러리100% — @std의 새 home
Deno 생태계 도구광범위 — Hono, Fresh, Oak 등
일반 JS 라이브러리천천히 — npm도 같이 publish하는 경우 多
사용자 수npm의 작은 일부 — 단 빠르게 성장

JSR은 **"npm을 죽인다"**가 아니라 **"TS-first의 다른 옵션을 만든다"**이다. 그리고 일정 부분 성공했다 — Deno 생태계 안에서는 standard, 그 밖에서는 niche.

JSR이 가져온 변화

  • TS 라이브러리 저자가 빌드 도구 선택을 사용자에게 미룰 수 있게 됨. 그것만으로도 큰 단순화.
  • npm의 "exports" 미로(CJS/ESM/types 경로 매핑)를 우회할 수 있는 길이 생김.
  • semver/타입/문서가 통합된 score 시스템 — package 품질에 대한 첫 진지한 표준화 시도.

npm 쪽의 반응

흥미로운 디테일 하나. Deno는 2024년 npm CLI의 BSD 라이선스 fork를 만들었다 — 이름은 npm이 아니라 pkg 비슷한 다른 이름으로 (커뮤니티 가이드라인 준수 차원). 이게 작은 라이선스/네이밍 논쟁을 일으켰지만, npm Inc. 쪽에서 큰 법적 대응은 없었다. 결국 메시지는 "npm 호환이 우선이지, 적대가 우선이 아니다".


5장 · Fresh 2 — 아일랜드 아키텍처의 두 번째 라운드

Fresh 1의 약속

Fresh는 Deno의 공식 풀스택 프레임워크였다. 핵심 컨셉:

  • No build step — dev에서 곧바로 도는 SSR.
  • Islands architecture — 페이지의 일부만 hydrate(클라이언트 JS), 나머지는 정적 HTML.
  • JSX with Preact — React가 아닌 Preact, 가벼움 우선.
  • Deno-native — 라우팅·핸들러를 Deno의 Request/Response 표준으로.

훌륭한 베팅이었지만, 1.x 시기에는 routing 모델의 한계 (file-based + handler 분리)와 React 생태계 호환의 부재가 도입을 제한했다.

Fresh 2가 바꾼 것

// routes/api/hello.ts (Fresh 2 스타일)
import { define } from "$fresh/server.ts";

export const handler = define.handlers({
  async GET(ctx) {
    return new Response(JSON.stringify({ msg: "hello" }), {
      headers: { "content-type": "application/json" },
    });
  },
});
// routes/index.tsx
import { define } from "$fresh/server.ts";
import Counter from "../islands/Counter.tsx";

export default define.page<{ now: string }>((props) => (
  <main>
    <h1>현재 시각: {props.data.now}</h1>
    <Counter start={0} />
  </main>
));

Fresh 2의 주요 변경:

  • 타입 추론 개선define을 통해 핸들러/페이지의 데이터 타입이 자동 전파.
  • server components 비슷한 패턴 — async 컴포넌트, 페이지 단위 데이터 fetch.
  • better island detectionislands/ 디렉토리의 컴포넌트만 hydrate.
  • Tailwind 통합 개선 — 빌드 step 없이 dev에서 Tailwind 사용.
  • deno deploy 통합deno deploy로 한 줄 배포.

Fresh가 채택을 못 따라잡은 이유 (솔직히)

  • Next.js의 무게가 너무 크다. 풀스택을 시작한다면 90%는 Next.js로 간다.
  • Preact 선택이 React 생태계의 일부 라이브러리(특히 일부 Form/Data/Animation lib)와의 호환에서 마찰을 만든다.
  • Deno 외 런타임 미지원 — Vercel/Cloudflare처럼 다른 런타임에서 돌리고 싶을 때 어색.

Fresh 2는 Deno Deploy에 묶인 풀스택이라면 매우 좋은 선택. 그러나 풀스택의 default가 될 길은 좁다.


6장 · Deno KV — 내장 KV가 production-ready로

Deno KV의 정체

Deno KV는 Deno 런타임 안에 내장된 key-value 스토어다. SQLite와 비슷한 단일 노드 모드, 그리고 Deno Deploy 환경에서는 글로벌 분산 모드.

// kv.ts
const kv = await Deno.openKv();

// set
await kv.set(["users", "alice"], { name: "Alice", joined: Date.now() });

// get
const result = await kv.get<{ name: string }>(["users", "alice"]);
console.log(result.value?.name);  // "Alice"

// list (prefix query)
for await (const entry of kv.list({ prefix: ["users"] })) {
  console.log(entry.key, entry.value);
}

// atomic transaction
await kv.atomic()
  .check({ key: ["counter"], versionstamp: null })
  .set(["counter"], 1)
  .commit();

2026 시점의 상태

측면상태
Local (SQLite-backed)GA (production-ready)
Deno Deploy (FoundationDB-backed, global)GA
Cross-region replication자동
Atomic transactions지원
Queue API지원 (kv.enqueue)
Watch API지원 — 실시간 구독
Limitper-key 64KB value, 일부 결제 플랜 제한

Deno KV는 Cloudflare KV와 Workers KV의 자리를 노린 것이지만, Deno 생태계 안에 묶여 있는 만큼 포지셔닝이 더 빡빡하다. 그러나 "1줄로 시작 가능한 분산 KV"라는 슬로건은 진짜 작동한다.

어디서 잘 쓰이나

  • 세션 스토어 — JWT 대신 server-side 세션.
  • 피처 플래그 — 글로벌 분산이 의미 있는 작은 read-heavy 데이터.
  • queue / 작업 분배 — kv.enqueue + worker.
  • 캐시 — 짧은 TTL의 응답 캐시.

어디가 약한가

  • 본격 RDB 자리에는 안 맞음 — schema, join, 트랜잭션 범위가 좁음.
  • 외부 서비스에서 KV로 직접 접근하기 어려움 (반드시 Deno 런타임을 통과).
  • 대용량 value는 다른 곳에 두고 KV는 메타데이터만.

7장 · workspace — Deno의 monorepo 답

모노레포가 1급 시민이 된다

Deno 2에서 deno.jsonworkspace 필드가 추가됐다.

// 루트 deno.json
{
  "workspace": [
    "./packages/api",
    "./packages/web",
    "./packages/shared"
  ],
  "tasks": {
    "dev": "deno task --filter=* dev"
  }
}
// packages/api/deno.json
{
  "name": "@app/api",
  "version": "0.1.0",
  "exports": "./mod.ts",
  "tasks": {
    "dev": "deno run --watch --allow-net mod.ts"
  }
}

내부 패키지를 import { foo } from "@app/shared"로 import 가능. pnpm workspace나 Bun workspace와 거의 같은 모델인데, Deno의 lockfile/캐시 일원화 덕에 설치 시간이 매우 짧다.

Turborepo·Nx와의 비교

도구장점단점
Deno workspace무설정, lockfile 통합, 빠른 installtask orchestration이 단순
pnpm workspace광범위 호환, 모두 익숙install이 Deno보다 느림
Turborepo빌드 캐싱, 강력한 그래프설정 무게
Nx강력한 generator, 큰 모노레포 표준학습 곡선 큼

Deno workspace는 작은~중간 모노레포에서 매끄럽다. 빌드 그래프 캐싱이 필수가 되는 큰 모노레포는 Turborepo/Nx를 그대로 쓰는 게 안전.


8장 · 보안 모델 — 여전히 킬러 피처

Deno의 처음부터 끝까지 살아남은 차별점이 이거다. 기본 deny.

permission flag 한눈에

deno run script.ts                    # 거의 아무것도 못 함
deno run --allow-read script.ts       # 파일 읽기
deno run --allow-net script.ts        # 네트워크
deno run --allow-env script.ts        # 환경변수
deno run --allow-write=./data script.ts   # 특정 디렉토리만 쓰기

# Deno 2부터: 더 세밀한 지정
deno run --allow-net=api.example.com,db.internal:5432 script.ts
deno run --allow-env=DATABASE_URL,REDIS_URL script.ts

운영에서의 실제 의미

좋은 점:

  • 의존성에 악성 코드가 섞여 들어와도 폭주를 막을 수 있음 (supply chain attack 방어).
  • production 컨테이너의 권한을 OS 외에 런타임 레이어에서 한 번 더 좁힘.
  • AI 에이전트의 sandbox 런타임으로 매우 좋음 — 모델이 시킨 코드가 무엇을 할 수 있는지 명시적.

마찰:

  • 첫 1주는 매번 "어떤 권한이 필요한지" 추측해야 함.
  • --allow-all 또는 -A로 끄고 시작하는 사람이 많음. 그러면 효과가 0.
  • 개발 환경과 production 환경에서 다른 권한을 줘야 하는 경우 설정이 복잡.

Deno 2의 보안 개선

  • --allow-net 등에 CIDR/도메인 단위 지정 더 정교화.
  • --deny-net명시적 거부 플래그 추가 — allow 전체에서 일부만 제외.
  • production 모드 권장 — deno deploy 환경에서 자동 narrow permission.
  • audit/trace — 어떤 권한이 실제로 호출됐는지 로깅.

보안 모델은 소프트웨어 공급망 공격이 늘어나는 2025~2026 시기에 가치가 커진 영역이다. xz utils 사건, npm event-stream 사건 이후, "기본 deny"의 가치를 진지하게 보는 회사가 늘었다.


9장 · Deno 3는 어디에 있나

2026 mid 시점의 상태

Deno 3는 아직 공식 출시 전이다 (2026년 5월 기준). 로드맵 글과 RFC 토론에서 다음 방향이 보인다.

  • WinterCG 1.0 적합성 강화 — fetch, Streams, Response의 표준 일치.
  • TypeScript의 type-check 옵션의 default 재고 — Deno 2까지는 type check가 기본이었으나, 무거움 때문에 default off에 대한 논의가 있음.
  • Node API 호환의 마지막 빈틈cluster, dgram, 일부 inspector 영역.
  • JSR과의 더 깊은 통합 — score, security advisory 같은 메타데이터를 CLI에서 활용.
  • Deno Deploy의 isolate-per-region 모델 진화 — Cloudflare Workers와의 직접 경쟁.

진짜 큰 베팅이 나올지, 아니면 점진적인 업그레이드로 갈지는 아직 정해지지 않았다. Deno 2가 큰 자기 부정이었던 만큼, Deno 3는 보수적인 evolution일 가능성이 더 크다.


10장 · Deno vs Bun vs Node 22+ — 삼파전의 정리

2026 mid 시점의 자리

Node 22+BunDeno 2
채택률1위 (압도적)2위 (개발 도구 중심)3위 (특정 영역)
시작 시간35~60ms10~20ms25~40ms
Node 호환100% (본인)90~95%90~95% (Deno 2 이후)
TS native--experimental-strip-types무설정무설정
보안 모델표준 (모두 허용)표준기본 deny
표준 라이브러리큰 코어작음@std 풍부
패키지 매니저npm/pnpm/yarnbun installdeno install
레지스트리npm onlynpm onlynpm + JSR
풀스택 프레임워크Next/Astro/Remix(그대로 Node 위의 것)Fresh 2
내장 KV없음bun:sqliteDeno KV
Edge 배포Vercel/NetlifyCloudflare Workers는 별도 isolateDeno Deploy
AI 에이전트 sandbox가능 (수동)가능매우 적합 (권한 모델)

의사결정 가이드

Deno 2가 맞는 곳:

  1. AI 에이전트 sandbox — 모델이 생성한 코드를 권한 제한해 실행. 이 영역에서 Deno는 분명한 1위.
  2. 고보안 / 정부 / 금융의 일부 워크로드 — permission 모델이 audit 추적에 의미 있음.
  3. 새 프로젝트의 빠른 prototype — 단일 파일 스크립트 + npm 의존성을 가장 매끄럽게.
  4. Deno Deploy 위의 작은 풀스택 — Fresh 2 + Deno KV.
  5. @std 중심의 backend 도구 — 표준 라이브러리의 안정성이 매력적.

Bun이 맞는 곳:

  1. CI 속도 (bun install, bun test).
  2. CLI 도구 (bun build --compile).
  3. Edge cold start.
  4. SQLite-heavy 작은 서비스.

Node 22+가 여전히 맞는 곳:

  1. 대부분의 enterprise production.
  2. APM/observability가 중요한 환경.
  3. 큰 monorepo with native addons.
  4. 회사 표준 런타임 — 사람을 뽑기 쉬움.

세 런타임은 zero-sum이 아니다. 한 회사 안에서 Node (메인 서비스), Bun (CLI/CI), Deno (AI 에이전트 sandbox, 고보안 부분)을 섞는 패턴이 점점 흔하다.


11장 · npm 호환의 broken / over-delivered 영역

Over-delivered

  • deno install의 안정성 — Deno 1 사용자들이 의심하던 것보다 매끄럽게 들어옴.
  • npm: specifier 호환 — Express, Hono, Zod, Prisma client, AWS SDK 등 메이저 라이브러리 거의 다 OK.
  • deno deploy의 npm 패키지 지원 — Cloudflare Workers가 v8 isolate 제약으로 못 도는 일부 npm을 Deno Deploy는 돈다.
  • Deno KV의 GA — 초기 베타 시기 우려를 깨고 production-ready.
  • JSR의 score 시스템 — package 품질에 대한 첫 진지한 표준화 시도, 빠르게 자리 잡음.

Broken / 아직 약한

  • native addon (N-API) — sharp, canvas, bcrypt 같은 일부 모듈은 여전히 마찰. 점점 좋아지고 있지만 0이 아님.
  • APM auto-instrumentation — Datadog/NR의 Node-level instrumentation을 Deno에서 똑같이 받지 못함. 이건 Bun과 똑같이 약한 영역.
  • debugger 통합 — Chrome DevTools 프로토콜 호환은 있지만, VSCode 디버거 통합의 안정성은 Node보다 한 발 뒤.
  • Fresh 채택률 — Next.js의 무게를 못 깬다. Fresh 2가 좋아져도.
  • JSR 채택률 — Deno 생태계 밖으로 확장이 느림.
  • Deno 3 일정의 불투명 — 큰 다음 마일스톤이 아직 흐림.

12장 · 누가 production에서 Deno 2를 쓰나

케이스 A — AI 에이전트 sandbox

가장 분명한 win 영역. 모델이 생성한 코드를 실행할 때 권한을 좁히는 것이 중요한 환경:

  • e2b, Modal, Replit 같은 AI 인프라의 일부 옵션.
  • 자체 코드 인터프리터를 만드는 스타트업의 backend.
  • Claude / GPT의 tool use에서 코드 실행 도구를 self-host하는 경우.

케이스 B — Deno Deploy 풀스택

Fresh 2 + Deno KV로 만든 작은 풀스택:

  • 사내 dashboard, 마이크로 SaaS.
  • API + 정적 페이지의 결합형 서비스.
  • 글로벌 read 분산이 필요한 작은 데이터.

케이스 C — 표준 라이브러리 헤비한 backend 도구

@std/cli, @std/path, @std/fs, @std/encoding을 적극 쓰는 CLI 도구나 dev tool. 외부 의존성 최소화가 가치 있는 곳.

케이스 D — Slack/Discord bot, webhook handler

Deno.serve + Deno.openKv()로 작은 webhook 서비스. 권한 모델로 안전하게 좁힘, 글로벌 배포는 Deno Deploy로.

케이스 E — 거의 없음 — 대규모 enterprise 모놀리스

Bun과 같은 이유. APM, debugger, 사람의 익숙함, 기존 코드베이스의 무게.

명시적 사례 (공개 글 기준)

  • Netlify Edge Functions — Deno 기반 런타임.
  • Supabase Edge Functions — Deno 기반.
  • Slack/Salesforce의 일부 자동화 — Deno 권한 모델 활용.
  • Deno Deploy 자체 — eat your own dogfood.

13장 · 마이그레이션 — Node 프로젝트를 Deno 2로 옮기는 단계

단계적 도입

  1. deno fmt, deno lint만 도입 — 다른 도구 변경 없음. 무리 없는 첫 step.
  2. CI에서 deno test — Vitest/Jest와 병행. Deno test의 속도와 무설정 매력 확인.
  3. 단일 script를 Deno로scripts/migrate.ts 같은 일회성 스크립트부터.
  4. 새 작은 서비스를 Deno로 — 신규 마이크로서비스 / 내부 도구.
  5. deno install로 dep 관리 — Node 런타임 유지하면서 Deno의 install만 사용.
  6. production 런타임을 Deno로 — 가장 큰 step, 마지막.

도입 체크리스트

  • 우리 APM (Datadog/NR/Sentry)이 Deno를 지원하나? instrumentation 수준은?
  • native addon 의존성 (sharp, canvas, bcrypt)이 Deno에서 도나?
  • 우리 CI 이미지가 Deno를 받을 수 있나? denoland/deno 공식 이미지 활용.
  • 권한 모델을 production에서 진짜로 좁힐 의지가 있나? -A로 끄면 차별점이 사라짐.
  • Fresh 2 같은 Deno 1st-party 도구를 쓸 건가, 아니면 Hono/Express의 Deno 모드로 갈 건가?
  • rollback 시나리오 — Deno→Node로 돌아가는 비용은?

흔한 anti-pattern

  • -A로 모든 권한을 켜고 시작하고 그대로 두기. 권한 모델의 가치를 0으로 만듦.
  • Fresh를 풀스택 default로 강제. Next.js 생태계의 풍요를 포기하는 결정, 정말 이유가 있어야 함.
  • JSR-only로 publish. 사용자 기반의 80%가 npm 사용자. 둘 다 publish하는 게 안전.
  • Deno KV를 RDB 자리에 두기. 작은 read-heavy 영역에 맞고, 트랜잭션·조인이 복잡한 곳에는 부적합.
  • deno runnode drop-in으로 가정. 호환은 좋아졌지만 100%가 아님. 핵심 경로는 측정하자.
  • 벤치마크 차트만 보고 결정. 본인 워크로드에서 측정 필수.

에필로그 — 이상주의에서 실용주의로

Deno 1은 Node에 대한 명시적 반박으로 태어났다. Deno 2는 그 반박을 절반 거두고 실용주의를 택했다. 그 결과:

Deno는 "Node를 대체한다"는 narrative를 포기했고, 대신 "Node의 옆에서 의미 있는 자리를 만든다"는 narrative로 갔다. 그 자리가 AI 에이전트 sandbox, Deno Deploy, 표준 라이브러리 중심 도구다.

기억할 점:

  • Deno 2는 Node 코드의 마이그레이션을 어렵지 않게 만들었다. 90%는 그냥 돈다. 마찰은 native addon, APM, 일부 debugger.
  • JSR은 npm을 죽이지 못했지만, Deno 생태계의 default가 됐다. TS-native publish는 진짜 깔끔한 장점.
  • Fresh 2는 좋아졌지만 Next.js의 자리는 못 빼앗는다. Deno Deploy 묶음에서는 매력적.
  • Deno KV는 production-ready다. 작은 서비스의 1줄 KV로 충분히 가치 있음.
  • 보안 모델은 AI 시대에 가치가 커졌다. 모델이 생성한 코드 실행은 Deno의 자연스러운 home.
  • Deno 3는 아직 공식 발표 전. 큰 자기 부정 두 번은 어렵다, 점진적 evolution이 예상.

채택 체크리스트 (Deno를 도입하기 전)

  • 진짜 권한 모델이 필요한 워크로드인가, 아니면 -A로 끌 건가?
  • APM/observability 요구 수준이 어떤가? Datadog/NR 풀스택 instrumentation이 필수면 아직 Node 권장.
  • native addon 의존성을 다 확인했나?
  • CI 이미지·Dockerfile에 Deno를 추가할 준비가 됐나?
  • 새 작은 서비스부터 시작할 건가, 아니면 기존 코드 마이그레이션부터 할 건가? 전자가 거의 항상 옳음.
  • Deno Deploy를 쓸 건가, 아니면 자체 인프라(쿠버네티스/Fly)에 Deno 컨테이너를 둘 건가?

흔한 anti-pattern (재강조)

  • 권한 모델을 켜놓고 모든 권한을 허용해 가치를 0으로 만들기.
  • Fresh를 신규 프로젝트 default로 강요.
  • Deno KV를 RDB 자리에 두기.
  • JSR-only publish로 사용자 기반의 80%를 포기.
  • npm: import의 호환을 100%로 가정하기.
  • 본인 워크로드 측정 없이 벤치마크 차트를 인용.

다음 글 예고

  • "AI 에이전트 sandbox 런타임 비교 2026 — Deno, Bun, Firecracker microVM, gVisor" — 모델이 생성한 코드를 안전하게 실행하는 다섯 가지 옵션.
  • "Fresh vs Next.js vs Astro 2026 — islands architecture의 세 답" — SSR 풀스택의 자리 다툼.
  • "Deno Deploy vs Cloudflare Workers vs Vercel Edge" — Edge runtime 세 강자의 비교.

참고 / References

Deno 공식 자료

Deno 2 출시 자료

  • "Deno 2.0" 발표 글 — Node 호환과 package.json 지원의 베팅.
  • Deno 2 RFC와 디자인 노트 — nodeModulesDir, workspace 도입 배경.

JSR

  • JSR 공식 — https://jsr.io/ — 패키지 검색, score, 문서.
  • JSR docs — TS-native publishing, scope 관리.
  • "Why JSR" 글 — Deno 팀의 동기, 디자인 결정.

Fresh

Deno KV

  • Deno KV 문서 — Deno.openKv() API, 키 구조, atomic transaction.
  • Deno KV blog post (GA 발표) — production-ready 선언.
  • FoundationDB — Deno Deploy KV의 백엔드 기술.

Deno Deploy

  • Deno Deploy — https://deno.com/deploy — global isolate runtime.
  • Deno Deploy 가격·제한 — 결제 플랜, per-key 제한, edge 제약.

Node.js (비교)

  • Node.js 공식 — https://nodejs.org/
  • Node --experimental-strip-types 문서 — TS 직접 실행.
  • node:test 문서 — Node 22+ 기준의 native test runner.

Bun (비교)

  • Bun 공식 — https://bun.sh/
  • Bun 런타임 호환 매트릭스 — Node API 호환 상태.

보안 / 권한 모델

  • Deno permission system 문서 — --allow-* 플래그의 모든 옵션.
  • OWASP supply chain security — npm/JS 생태계의 위협 모델.
  • xz-utils 사건 회고 — 공급망 공격이 보안 모델 베팅에 미친 영향.

운영 채택 사례 (공개 글 기준)

  • Netlify Edge Functions 엔지니어링 블로그의 Deno 도입 글.
  • Supabase Edge Functions 아키텍처 — Deno 기반 런타임의 설계.
  • Slack 자동화에서 Deno를 채택한 사례 글.

비판적 시각 / 회고

  • "Why we did NOT pick Deno" 류의 startup 글 — 의도적으로 안 고른 회사들의 이유.
  • APM auto-instrumentation의 한계에 대한 운영팀 글.
  • Deno 2의 자기 부정에 대한 커뮤니티 반응 (forum, HackerNews, Reddit).

표준화 / WinterCG

  • WinterCG — https://wintercg.org/ — JS 런타임 간 호환 표준 그룹.
  • Web-interoperable runtimes 명세 — Deno·Bun·Workers·Vercel이 따르는 표준.