Skip to content

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

한국어
0%
정확도 0%
💡 왼쪽 원문을 읽으면서 오른쪽에 따라 써보세요. Tab 키로 힌트를 받을 수 있습니다.
원문 렌더가 준비되기 전까지 텍스트 가이드로 표시합니다.

프롤로그 — 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

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

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 스타일)

export const handler = define.handlers({

async GET(ctx) {

return new Response(JSON.stringify({ msg: "hello" }), {

headers: { "content-type": "application/json" },

});

},

});

// routes/index.tsx

export default define.page<{ now: string }>((props) => (

));

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가 맞는 곳:**

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 run`을 `node` 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 공식 사이트 — [https://deno.com/](https://deno.com/) — 최신 버전, 변경 사항.

- Deno 매뉴얼 — [https://docs.deno.com/](https://docs.deno.com/) — 런타임·CLI·표준 라이브러리.

- Deno GitHub — [https://github.com/denoland/deno](https://github.com/denoland/deno) — issue·release notes.

- Deno blog (releases) — [https://deno.com/blog](https://deno.com/blog) — 메이저 버전별 변경 사항.

Deno 2 출시 자료

- "Deno 2.0" 발표 글 — Node 호환과 `package.json` 지원의 베팅.

- Deno 2 RFC와 디자인 노트 — `nodeModulesDir`, workspace 도입 배경.

JSR

- JSR 공식 — [https://jsr.io/](https://jsr.io/) — 패키지 검색, score, 문서.

- JSR docs — TS-native publishing, scope 관리.

- "Why JSR" 글 — Deno 팀의 동기, 디자인 결정.

Fresh

- Fresh 공식 — [https://fresh.deno.dev/](https://fresh.deno.dev/)

- Fresh 2 마이그레이션 가이드 — Fresh 1에서 2로 옮기는 방법.

- Preact 공식 — [https://preactjs.com/](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](https://deno.com/deploy) — global isolate runtime.

- Deno Deploy 가격·제한 — 결제 플랜, per-key 제한, edge 제약.

Node.js (비교)

- Node.js 공식 — [https://nodejs.org/](https://nodejs.org/)

- Node `--experimental-strip-types` 문서 — TS 직접 실행.

- `node:test` 문서 — Node 22+ 기준의 native test runner.

Bun (비교)

- Bun 공식 — [https://bun.sh/](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/](https://wintercg.org/) — JS 런타임 간 호환 표준 그룹.

- Web-interoperable runtimes 명세 — Deno·Bun·Workers·Vercel이 따르는 표준.

현재 단락 (1/325)

Ryan Dahl은 2009년 Node를 만들었고, 2018년 JSConf EU에서 "Node에서 후회하는 10가지"라는 유명한 발표를 했다. 그리고 Deno를 만들었다. 보안은 ...

작성 글자: 0원문 글자: 15,348작성 단락: 0/325