Deno 2.0 완벽 가이드 — npm 호환·JSR·워크스페이스·성능·Node 비교·마이그레이션

Deno 2.0 완벽 가이드 — npm 호환·JSR·워크스페이스·성능·Node 비교·마이그레이션

이 글의 핵심

Deno 2.0은 Node·npm과의 상호 운용을 전제로 한 메이저 전환입니다. package.json·node_modules·워크스페이스를 이해하고, JSR과 npm 명세자(specifier)로 의존성을 설계한 뒤, 공식 벤치마크와 한계(V8 포인터 압축 등)를 함께 보며 마이그레이션 순서를 잡을 수 있습니다.

이 글의 핵심

Deno 2.0(2024년 10월 공개)은 “기존 JavaScript 인프라와의 호환”과 “단일 실행 파일로 제공되는 올인원 도구체인”을 동시에 노리는 메이저 릴리스입니다. 이 글에서는 주요 변경사항, package.json·node_modules·npm 워크스페이스와의 정렬, npm:·JSR(jsr:) 의존성 모델, deno install / deno add / deno remove, Deno 워크스페이스와 모노레포, 공개 벤치마크와 해석 시 주의점, Node.js와의 역할 비교, 1.x·Node에서 넘어올 때의 실전 마이그레이션 순서를 한 흐름으로 정리합니다.

선행 지식: ECMAScript 모듈(ESM), package.json의 의존성 필드, 모노레포에서의 워크스페이스 개념을 알고 있으면 설명의 밀도를 온전히 활용할 수 있습니다.


1. Deno 2.0이 바꾼 전제

Deno 1.x가 URL·원격 import와 “설정 최소화”를 강하게 내세웠다면, Deno 2.0은 대규모·레거시·팀 단위 채택을 염두에 두고 Node·npm과의 호환 층을 정식 제품 기능으로 끌어올렸습니다. 그 결과 동일 코드베이스에서 기존 npm 자산을 그대로 소비하면서도, 필요할 때만 Deno 고유 기능(권한 모델, 내장 도구, deno compile 등)을 점진적으로 도입하는 그림이 현실적으로 됩니다.

1.1 주요 변경사항 요약

영역내용
Node·npm 호환package.json, node_modules, npm 워크스페이스 인식. ESM 중심 Node 프로젝트 실행·도구 병행 사용이 수월해짐
패키지 관리deno install, deno add, deno remove로 의존성 설치·갱신 (npm과 유사한 UX)
레지스트리JSR(JavaScript Registry)을 공식 생태계 축으로 제시. 표준 라이브러리는 JSR @std에서 제공
비공개 npmNode와 동일하게 .npmrc로 프라이빗 레지스트리·스코프 설정
워크스페이스deno.jsonworkspace로 멀티 패키지 관리. npm 워크스페이스와 혼합 모노레포도 가능
도구deno fmt가 HTML·CSS·YAML까지, deno lint에 Node 규칙, deno testnode:test 호환, deno taskpackage.json 스크립트 실행 등
릴리스 모델LTS(장기 지원) 채널 도입(2.1부터). 기업 도입 시 안정성 논의에 활용

이 중 npm 호환JSR은 의존성 설계를 바꾸는 축이므로, 이후 절에서 개념을 분리해 설명합니다.


2. npm 패키지 호환성: 무엇이 “그대로” 되고 무엇이 조건부인가

Deno 2.0은 npm에 올라온 패키지를 Deno 런타임에서 해석할 수 있도록 모듈 해석·Node API 호환 층을 강화했습니다. 다만 모든 패키지가 수정 없이 동작한다는 뜻은 아니며, 특히 CommonJS 전용 가정, 특정 Node 내장 모듈의 엣지 케이스, 네이티브 애드온(Node-API)은 사전 검증이 필요합니다.

2.1 npm: 명세자(specifier): 매니페스트 없이 npm 쓰기

작은 스크립트나 노트북에서는 package.json 없이도 npm 패키지를 직접 가져올 수 있습니다. Deno는 이런 의존성을 전역 캐시에 두어, 저장소 루트에 node_modules를 만들지 않고도 실행할 수 있습니다.

// chalk 예시: 버전을 명세자(specifier)에 고정하면 재현성이 좋아집니다.
import chalk from "npm:[email protected]";

console.log(chalk.blue("Hello, world!"));

왜 필요한가: 빠른 실험·CI 일회성 스크립트에서 “프로젝트 뼈대 없이” 외부 라이브러리를 쓰기 위함입니다. 언제 한계가 오는가: 의존성 버전을 팀 전체가 동일하게 맞춰야 할 때는 deno.jsonimportspackage.json으로 옮기는 편이 안전합니다.

2.2 deno.json의 import map으로 bare import 정리

규모가 커지면 버전 문자열을 소스 곳곳에 두기 어렵습니다. deno.json에서 별칭을 두면 npm 패키지를 마치 일반 패키지 이름처럼 import할 수 있습니다.

{
  "imports": {
    "chalk": "npm:[email protected]"
  }
}
import chalk from "chalk";
console.log(chalk.green("bare import"));

어떻게 동작하는가: Deno가 import map을 해석할 때 chalknpm:[email protected]으로 치환합니다. 주의점: 팀 규칙상 “락파일·재현 가능 설치”가 필요하면 deno install/package.json 기반 워크플로와 함께 쓰는지 여부를 CI 정책으로 명확히 하는 것이 좋습니다.

2.3 package.jsonnode_modules를 “Node처럼”

Deno 2.0은 기존 Node 프로젝트 레이아웃을 이해합니다. 즉, 이미 package.jsonnode_modules가 있는 저장소에서 의존성 설치·스크립트 실행·테스트를 Deno 관점에서 수행할 수 있습니다. 이는 “Deno만의 별도 우주”가 아니라 실제 팀 코드베이스에 끼워 넣기 위한 호환 전략입니다.

실무에서의 의미: 프론트엔드 빌드 체인·서버·CLI 중 일부만 Deno 도구(deno fmt, deno lint, deno test)로 바꾸는 점진적 도입이 가능해집니다. 반대로, 순수 Deno 프로젝트만 유지하고 싶다면 deno.json 중심으로 두고 npm은 필요한 패키지에만 제한하는 식으로 경계를 설계할 수 있습니다.

2.4 프라이빗 npm 레지스트리 (.npmrc)

기업 내부 스코프 패키지를 쓰는 경우, Node·npm과 동일하게 .npmrc에 레지스트리 URL과 인증 정보를 두면 Deno가 이를 활용합니다. 팀 보안 정책상 토큰은 환경 변수·시크릿 저장소로 주입하고, 저장소에 평문으로 커밋하지 않는 것이 전제입니다.


3. JSR (JavaScript Registry)

JSR은 Deno 팀이 추진하는 현대적 JavaScript 패키지 레지스트리로, ESM만 허용, TypeScript 소스 배포, 다중 런타임·환경을 염두에 둔 메타데이터, 문서 자동 생성 등을 목표로 합니다. Deno 표준 라이브러리는 @std 스코프로 JSR에서 제공되며, npm만큼 거대하지 않지만 “검증된 기본 블록”을 빠르게 가져오기에 적합합니다.

3.1 npm과의 관계

  • 소비: Deno에서는 jsr: 명세자(specifier) 또는 설정으로 JSR 패키지를 가져올 수 있습니다. 팀 표준에 따라 npm 의존성과 혼합할 수 있습니다.
  • 배포: 라이브러리를 JSR에 올리면, JSR이 TypeScript를 .js·.d.ts 등으로 변환해 소비자 환경 차이를 흡수하는 데 도움을 준니다(세부는 패키지 설정에 따름).

3.2 언제 JSR을 우선할까

다음에 가깝다면 JSR을 적극 검토합니다: 라이브러리가 Deno·Node·브라우저 등 여러 런타임에서 깨지지 않아야 하고, 패키지 메타데이터·문서 품질을 레지스트리 차원에서 맞추고 싶을 때. 반면 이미 npm 중심으로 게시·버저닝·조직 프로세스가 고정된 팀은, 당장은 npm을 유지하고 Deno는 소비자 런타임으로만 쓰는 편이 비용이 적을 수 있습니다.


4. Workspaces와 모노레포

Deno 2.0의 워크스페이스는 여러 하위 패키지를 한 저장소에서 일관되게 다루기 위한 기능입니다. 루트 deno.json에 멤버 디렉터리를 나열하는 형태가 기본 패턴입니다.

{
  "workspace": ["./packages/add", "./packages/subtract"]
}

의도: 각 멤버는 자체 의존성·린트·포맷 설정을 가질 수 있어, 공용 코어와 앱·라이브러리를 한 repo에 두는 모노레포에 맞습니다.

4.1 npm 워크스페이스와의 혼합

Deno 2.0은 npm workspaces도 이해합니다. 따라서 일부 패키지는 package.json, 일부는 deno.json인 하이브리드 모노레포를 구성할 수 있습니다. 이는 “전사를 한 번에 Deno로 갈아타기”보다 팀·제품 단위로 경계를 나누는 현실적인 전략과 맞닿아 있습니다.

4.2 deno publish와 멀티 패키지

여러 멤버를 JSR 등에 게시할 때, 수동으로 순서를 맞추는 부담을 줄이기 위해 deno publish가 워크스페이스를 고려합니다(공식 예시·표준 라이브러리 구조 참고). CI에서는 버전 정책·변경 감지·게시 순서를 팀 규칙으로 문서화하는 것이 안전합니다.


5. 성능 벤치마크: 숫자를 “어떻게” 읽을 것인가

Deno 팀은 Deno 2.0 발표와 함께 패키지 매니저 성능HTTP 등 런타임 벤치마크를 제시했습니다. 여기서 중요한 것은 측정 조건(콜드/핫 캐시, OS, 버전)과 본인 워크로드와의 거리입니다.

5.1 deno install (공식 주장)

공식 자료에 따르면, deno install은 npm 대비 콜드 캐시에서 약 15%, 핫 캐시에서 약 90% 빠른 사례가 보고되었습니다. 이는 “의존성 해석·디스크 I/O·캐시 활용”이 겹친 결과이므로, 프로젝트 크기·락파일 유무·네트워크에 따라 체감은 크게 달라질 수 있습니다.

실무 해석: CI에서 캐시 전략을 세우는 팀에게는 유의미한 지표입니다. 로컬에서는 한 번 측정해 기존 npm/pnpm/yarn 파이프라인과 비교하는 것이 가장 정직합니다.

5.2 HTTP·처리량 벤치마크와 Deno 2.0 보정

공식 블로그에서는 과거 HTTP 벤치마크 그래프에 대해 Deno 2.0은 표시보다 약 20% 느릴 수 있다는 정정을 했습니다. 원인으로 V8 포인터 압축 비활성화(4GB 힙 한계를 넘는 사용자 사례 대응)가 언급되었고, 이후 포인터 압축 재활성화·대용량 힙이 필요한 빌드 분리(deno64 같은 방향)가 논의되었습니다.

시사점: 벤치마크는 특정 버전·빌드 옵션·워크로드에 묶입니다. API 게이트웨이를 Deno로 둘지, Node로 둘지는 지연 시간·메모리 프로파일·운영 팀의 친숙도를 함께 봐야 합니다.

5.3 기타 체감 포인트

  • 시작 시간: 짧은 CLI·서버리스 스타일 작업에서 중요합니다.
  • 단일 바이너리 도구체인: 별도 node_modules 없이도 포맷·린트·테스트가 가능한 점은 온보딩 비용을 줄입니다.
  • deno serve: 공식 자료에 따르면 멀티 코어 활용 등 서빙 측 개선이 포함되었습니다. 다만 이는 애플리케이션 코드·리버스 프록시 구성과 합쳐져야 의미가 있습니다.

6. Node.js vs Deno 2.0: 경쟁이 아니라 역할 분담

둘 다 V8(및 주변 스택)을 기반으로 JavaScript·TypeScript를 실행하지만, 제품 철학과 운영 모델이 다릅니다.

비교 축Node.jsDeno 2.0
생태계 중심npm·CJS 역사가 깊고, 도구·프레임워크의 기본 가정이 Node에 최적화된 경우가 많음npm·JSR을 소비할 수 있으나, 권한·내장 도구·웹 표준 API 쪽 가치 제안이 큼
보안 기본값전통적으로 전역 권한(최근에도 --permission 실험 등 진행)옵트인 권한 모델이 강함. Node 호환 실행 시에도 동일 철학이 적용된다는 점이 공식 FAQ에 명시됨
TypeScript외부 도구·빌드 단계가 일반적네이티브 지원이 기본 스토리
배포 형태서버·CLI·Electron 등 광범위deno compile단일 실행 파일 배포 스토리가 강점

선택 기준 예시: 레거시 CJS·특정 네이티브 모듈에 깊게 묶인 서비스는 당분간 Node가 안전합니다. 새로운 마이크로서비스·내부 CLI·에지 근처 워커에서 권한 모델·도구 일원화를 노린다면 Deno 2.0을 후보에 둘 만합니다.


7. 실전 마이그레이션 가이드

아래는 Deno 1.x 또는 기존 Node(ESM) 프로젝트에서 옮길 때의 권장 순서입니다. 팀 상황에 맞게 단계를 쪼개는 것이 핵심입니다.

7.1 사전 점검

  1. 모듈 형식: ESM인가, CJS 혼합인가. CJS 비중이 높으면 리팩터링 범위를 먼저 산정합니다.
  2. 네이티브 의존성: node-gyp·N-API 모듈이 있는지 확인하고, Deno에서의 지원 범위를 검증합니다.
  3. 스크립트·CI: package.jsonscriptsdeno task로 얼마나 대체할지 합의합니다.

7.2 도구부터 침투시키기

포맷·린트·테스트처럼 런타임과 분리하기 쉬운 영역부터 Deno 명령을 도입하면 리스크가 작습니다. 예: deno fmt, deno lint --fix, deno test(node:test 호환 활용).

7.3 의존성 정리

  • npm 중심이면 deno installnode_modules를 구성하고, 문제가 되는 패키지를 목록화합니다.
  • Deno 중심이면 deno add / deno removepackage.json 또는 deno.json을 갱신하는 흐름을 표준화합니다.

7.4 권한 플래그 운영

로컬에서는 -A로 빠르게 열 수 있으나, CI·프로덕션에서는 --allow-net최소 권한을 목표로 합니다. “작동은 하는데 배포만 실패”하는 경우 대부분 권한·파일 경로·환경 변수 불일치입니다.

7.5 공식 마이그레이션 문서

세부 API·플래그 변경은 릴리스마다 보강되므로, Deno 1.x → 2.x 마이그레이션 가이드를 버전에 맞춰 읽는 것을 권합니다.


8. 자주 겪는 문제와 점검 순서

  • npm: 패키지가 런타임에서만 오류: 해당 패키지가 Node 내장 모듈 가정을 강하게 쓰는지, 조건부 export가 Deno 해석과 맞지 않는지 확인합니다.
  • 워크스페이스 간 의존성 꼬임: 루트와 멤버의 deno.json/package.json 우선순위, 버전 범위를 정리하고, 락파일 전략을 하나로 맞춥니다.
  • 성능 회귀 체감: V8 빌드 옵션·메모리 한계 이슈는 버전 릴리스 노트와 함께 추적합니다. 프로덕션 전에는 부하 테스트로 확인합니다.

9. 정리

Deno 2.0은 “Deno만의 세계”와 “npm이 쌓아 온 현실” 사이를 잇는 릴리스입니다. npm:·package.json·deno install의존성 접근성을 확보하고, JSR로 차세대 모듈 게시·소비를 설계하며, 워크스페이스로 모노레포 운영을 단순화하려는 방향이 한데 모였습니다. 성능 수치는 캐시 상태·워크로드·버전에 민감하므로, 공식 벤치마크는 출발점으로만 두고 자신의 저장소에서 재측정하는 태도가 가장 안전합니다.

Node와의 선택은 기술 우열 한 방보다, 팀이 익숙한 운영·레거시 의존성·보안·배포 형태를 종합한 합의 결과에 가깝습니다. 이 글이 Deno 2.0 도입 논의의 공통 언어를 만드는 데 도움이 되기를 바랍니다.


참고