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

- Name
- Youngju Kim
- @fjvbn20031
프롤로그 — 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 1 | Deno 2 |
|---|---|---|
package.json | 무시 / 부분 지원 | 1급 — deno install이 읽음 |
node_modules | 의도적으로 없음 | 옵션 — nodeModulesDir: auto |
| npm 패키지 | npm: specifier | 동일 + package.json에서 자동 |
deno install | URL 기반 binary install | Node 호환 패키지 매니저 |
deno run npm:foo | 부분 지원 | 안정적, 광범위 호환 |
| workspace | 없음 | 1급 — deno.json의 workspace 필드 |
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의 베팅 명제는 이렇다.
- TS-native publishing — TS 소스를 그대로 publish. 받는 쪽이 빌드 도구를 골라 쓴다. (npm은 보통 컴파일된 JS+.d.ts 묶음.)
- 표준 ESM only — CJS 없음,
package.json의 미로 없음. - runtime-agnostic — Deno뿐 아니라 Node, Bun, browser에서 import 가능.
- 품질 점수 —
score로 문서·테스트·타입의 완성도 표시. - 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 detection —
islands/디렉토리의 컴포넌트만 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 | 지원 — 실시간 구독 |
| Limit | per-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.json의 workspace 필드가 추가됐다.
// 루트 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 통합, 빠른 install | task 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+ | Bun | Deno 2 |
|---|---|---|---|
| 채택률 | 1위 (압도적) | 2위 (개발 도구 중심) | 3위 (특정 영역) |
| 시작 시간 | 35~60ms | 10~20ms | 25~40ms |
| Node 호환 | 100% (본인) | 90~95% | 90~95% (Deno 2 이후) |
| TS native | --experimental-strip-types | 무설정 | 무설정 |
| 보안 모델 | 표준 (모두 허용) | 표준 | 기본 deny |
| 표준 라이브러리 | 큰 코어 | 작음 | @std 풍부 |
| 패키지 매니저 | npm/pnpm/yarn | bun install | deno install |
| 레지스트리 | npm only | npm only | npm + JSR |
| 풀스택 프레임워크 | Next/Astro/Remix | (그대로 Node 위의 것) | Fresh 2 |
| 내장 KV | 없음 | bun:sqlite | Deno KV |
| Edge 배포 | Vercel/Netlify | Cloudflare Workers는 별도 isolate | Deno Deploy |
| AI 에이전트 sandbox | 가능 (수동) | 가능 | 매우 적합 (권한 모델) |
의사결정 가이드
Deno 2가 맞는 곳:
- AI 에이전트 sandbox — 모델이 생성한 코드를 권한 제한해 실행. 이 영역에서 Deno는 분명한 1위.
- 고보안 / 정부 / 금융의 일부 워크로드 — permission 모델이 audit 추적에 의미 있음.
- 새 프로젝트의 빠른 prototype — 단일 파일 스크립트 + npm 의존성을 가장 매끄럽게.
- Deno Deploy 위의 작은 풀스택 — Fresh 2 + Deno KV.
@std중심의 backend 도구 — 표준 라이브러리의 안정성이 매력적.
Bun이 맞는 곳:
- CI 속도 (
bun install,bun test). - CLI 도구 (
bun build --compile). - Edge cold start.
- SQLite-heavy 작은 서비스.
Node 22+가 여전히 맞는 곳:
- 대부분의 enterprise production.
- APM/observability가 중요한 환경.
- 큰 monorepo with native addons.
- 회사 표준 런타임 — 사람을 뽑기 쉬움.
세 런타임은 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로 옮기는 단계
단계적 도입
deno fmt,deno lint만 도입 — 다른 도구 변경 없음. 무리 없는 첫 step.- CI에서
deno test— Vitest/Jest와 병행. Deno test의 속도와 무설정 매력 확인. - 단일 script를 Deno로 —
scripts/migrate.ts같은 일회성 스크립트부터. - 새 작은 서비스를 Deno로 — 신규 마이크로서비스 / 내부 도구.
deno install로 dep 관리 — Node 런타임 유지하면서 Deno의 install만 사용.- 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 run을nodedrop-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 공식 사이트 — https://deno.com/ — 최신 버전, 변경 사항.
- Deno 매뉴얼 — https://docs.deno.com/ — 런타임·CLI·표준 라이브러리.
- Deno GitHub — https://github.com/denoland/deno — issue·release notes.
- Deno blog (releases) — https://deno.com/blog — 메이저 버전별 변경 사항.
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
- Fresh 공식 — https://fresh.deno.dev/
- Fresh 2 마이그레이션 가이드 — Fresh 1에서 2로 옮기는 방법.
- Preact 공식 — https://preactjs.com/ — 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이 따르는 표준.