작업 디렉토리나 상위 디렉토리에서 node_modules 디렉토리를 찾을 수 없으면 Bun 은 Node.js 스타일의 모듈 해결 방식을 포기하고 Bun 모듈 해결 알고리즘을 사용합니다.
Bun 스타일의 모듈 해결 방식에서는 실행 중에 모든 임포트된 패키지를 전역 모듈 캐시에 자동으로 설치합니다 (bun install 에서 사용하는 것과 동일한 캐시).
import { foo } from "foo"; // `latest` 버전 설치
foo();이 스크립트를 처음 실행하면 Bun 이 "foo" 를 자동으로 설치하고 캐시합니다. 다음에 스크립트를 실행할 때는 캐시된 버전을 사용합니다.
버전 해결
설치할 버전을 결정하기 위해 Bun 은 다음 알고리즘을 따릅니다.
- 프로젝트 루트에서
bun.lock파일이 있는지 확인합니다. 존재하면 lockfile 에 지정된 버전을 사용합니다. - 그렇지 않으면 트리를 따라 올라가면서
"foo"를 의존성으로 포함하는package.json을 찾습니다. 찾으면 지정된 semver 버전 또는 버전 범위를 사용합니다. - 그렇지 않으면
latest를 사용합니다.
캐시 동작
버전 또는 버전 범위가 결정되면 Bun 은 다음 작업을 수행합니다.
- 모듈 캐시에서 호환 가능한 버전이 있는지 확인합니다. 있으면 사용합니다.
latest를 해결할 때 Bun 은package@latest가 지난 24 시간 이내에 다운로드되어 캐시되었는지 확인합니다. 그렇다면 사용합니다.- 그렇지 않으면
npm레지스트리에서 적절한 버전을 다운로드하고 설치합니다.
설치
패키지는 <cache>/<pkg>@<version> 에 설치되고 캐시되므로 동일한 패키지의 여러 버전을 동시에 캐시할 수 있습니다. 또한 캐시에 있는 패키지의 모든 버전을 더 빠르게 찾을 수 있도록 <cache>/<pkg>/<version> 아래에 심볼릭 링크가 생성됩니다.
버전 지정자
임포트 문에 버전 또는 버전 범위를 직접 지정하여 이 전체 해결 알고리즘을 우회할 수 있습니다.
import { z } from "zod@3.0.0"; // 특정 버전
import { z } from "zod@next"; // npm 태그
import { z } from "zod@^3.20.0"; // semver 범위장점
이 자동 설치 방식은 몇 가지 이유로 유용합니다.
- 공간 효율성 — 각 의존성 버전은 디스크의 한 곳에만 존재합니다. 이는 프로젝트별 중복 설치에 비해 공간과 시간 측면에서 큰 절약입니다.
- 이식성 — 간단한 스크립트와 gist 를 공유하려면 소스 파일이 자체 포함 되어야 합니다. 코드와 설정 파일을 함께
zip으로 묶을 필요가 없습니다.import문에 버전 지정자를 사용하면package.json조차 필요하지 않습니다. - 편의성 — 파일이나 스크립트를 실행하기 전에
npm install또는bun install을 실행할 필요가 없습니다. 그냥bun run하면 됩니다. - 하위 호환성 — Bun 은 여전히
package.json이 존재하면 지정된 버전을 존중하므로 단일 명령으로 Bun 스타일 해결 방식으로 전환할 수 있습니다.rm -rf node_modules.
제한 사항
- Intellisense 가 없습니다. IDE 의 TypeScript 자동완성은
node_modules내부의 타입 선언 파일 존재에 의존합니다. 이에 대한 다양한 해결 방법을 조사 중입니다. - patch-package 지원이 없습니다.
FAQ
pnpm 의 방식과 어떻게 다른가요?">
pnpm 을 사용하면 pnpm install 을 실행해야 하며, 이는 런타임이 해결할 심볼릭 링크의 node_modules 폴더를 생성합니다. 반면 Bun 은 파일을 실행할 때 의존성을 즉시 해결하므로 미리 install 명령을 실행할 필요가 없습니다. Bun 은 node_modules 폴더도 생성하지 않습니다.
Yarn Plug'N'Play 의 방식과 어떻게 다른가요?">
Yarn 을 사용하면 스크립트를 실행하기 전에 yarn install 을 실행해야 합니다. 반면 Bun 은 파일을 실행할 때 의존성을 즉시 해결하므로 미리 install 명령을 실행할 필요가 없습니다.
Yarn Plug'N'Play 은 또한 의존성을 저장하기 위해 zip 파일을 사용합니다. 이는 zip 파일에 대한 무작위 접근 읽기가 동등한 디스크 조회보다 느린 경향이 있어 런타임에 의존성 로딩이 더 느려집니다.
Deno 의 방식과 어떻게 다른가요?">
Deno 는 각 npm import 앞에 npm: 지정자가 필요하며, tsconfig.json 의 compilerOptions.paths 를 통한 임포트 맵 지원이 없고, package.json 설정에 대한 지원이 불완전합니다. Deno 와 달리 Bun 은 현재 URL 임포트를 지원하지 않습니다.