패키지 매니저 (Package Manager)와 Bun

·2026년 1월 26일

interviewQnA

목록 보기
3/3

처음 컴퓨터에 세팅할때면 흔히 npm -v 라는 명령어로 뭐가 제대로 설치됐는지 확인하고는 했는데, 정확히 npm이 무엇인지, 뭔데 Node.js를 설치하면 따라오는지 자세히는 모르는 상태로 사용하고는 했다..!

이번 사이드프로젝트를 진행하면서 bun을 사용했고, bun 또한 무엇이길래 npm install 대신에 쓰는지 이번 기회에 알아보고자 한다.


패키지 매니저(Package Manager)란?

개발을 하다 보면 React부터 사소한 라이브러리들까지 남이 만들어 둔 코드(라이브러리)를 가져다 쓸 일이 매우 많다. 만약 이런 패키지 매니저들이 없다면 node_modules 에 있는 수많은 파일들을 USB에 담거나 메일로 주고받는다면 관리가 불가능해진다.

이럴때 패키지 매니저(자바스크립트 매니저)를 사용할 수 있다.

요리를 할 때(개발), 쌀이나 야채 같은 재료(남이 만들어둔 코드/라이브러리)를 직접 농사지어서 구하는 것이 아니라, 마트에서 손쉽게 사오고 관리해주는 '구매 대행 비서'와 같은 역할을 패키지 매니저가 수행하게 된다.



패키지 매니저를 왜 쓰지?

  • 손쉬운 설치: npm install react 명령어 한 줄이면 리액트 라이브러리를 인터넷(저장소)에서 내 컴퓨터로 다운로드 할 수 있다.
  • 버전 관리 :
    • package.json이라는 파일에 "우리 프로젝트는 A 라이브러리 1.2 버전이 필요해"라고 명시해둔뒤
    • 이 파일만 있으면 팀원 누구든 똑같은 환경을 즉시 구축할 수 있다.
  • 의존성 해결:
    • A라는 도구를 설치하려는데, A가 작동하려면 B가 필요하고, B는 C가 필요하다면?
    • 패키지 매니저가 알아서 A, B, C를 모두 찾아서 순서대로 설치해 준다.
  • 스크립트 실행:
    • 복잡한 실행 명령어 대신 npm start, npm build 같이 약속된 단축 명령어를 실행할 수 있다.

프로젝트를 진행하면서 package.jsonnode_modules 는 누구나 한번씩 만나봤을 친구들인데, 그 친구들에 간단하게 정의하면 아래와 같다.

package.json : (라이브러리) 버전 관리를 위한 리스트

node_modules : package.json 에 따른 라이브러리들의 코드들이 실제로 담기는 바구니 (폴더)

패키지 매니저가 node_modules를 만드는 과정

개발자가 터미널에 npm install이라고 치면, 패키지 매니저는 다음과 같은 일을 수행하여 node_modules 폴더를 생성(혹은 갱신)한다.

  1. 확인: package.json을 읽고 필요한 라이브러리 목록을 확인한다. (예: React, TypeScript 등)
  2. 다운로드: 인터넷(npm 레지스트리)에서 해당 라이브러리 파일들을 다운로드한다.
  3. 배치: 다운로드한 파일들을 프로젝트 폴더 내의 node_modules라는 이름의 폴더 안에 차곡차곡 정리해서 넣는다.
  4. 연쇄 작용 :
    • React를 설치하려고 보니, React가 작동하려면 다른 A, B 라이브러리가 또 필요하네?
    • 그럼 A와 B도 같이 다운로드해서 node_modules에 넣는다.
    • 이 과정이 반복되면서 node_modules 폴더는 엄청나게 커지게 된다.

node_modules가 필요한가?

코드에서 import 문을 쓸 때, 컴퓨터는 그 파일을 어디서 찾을까?

import React from 'react'; // "react를 가져와!"

이 코드를 실행하면 자바스크립트(Node.js)는 무조건 node_modules 폴더 안을 뒤지기 시작한다.
"react라는 폴더가 있나? 아, 여기 있네!" 하고 찾아서 코드를 가져오게 된다.

즉, 패키지 매니저는 코드가 실행될 수 있도록 node_modules라는 약속된 장소에 파일들을 배달해 주는 역할을 한다!


패키지 매니저의 종류

패키지 매니저가 왜 필요하고, 뭔지는 이제 알았으니 그 다음으로는 이 패키지매니저의 종류에 대해 알아볼 수 있다. 패키지 매니저에는 우리가 널리 아는 npm 외에도 yarn, pnpm, bun 등 다양한 종류들이 있다.

  • npm (Node Package Manager):
    • 특징: Node.js를 설치하면 자동으로 같이 설치된다. 가장 기본적이고 사용자가 제일 많다.
    • 단점: 예전에는 속도가 느리고 비효율적이라는 평이 있었으나, 최근에는 많이 개선되었다.
  • Yarn (Yet Another Resource Negotiator):
    • 특징: 페이스북(Meta)에서 만들으며, 초기에 npm의 느린 속도와 보안 문제를 해결하기 위해 등장하여 큰 인기를 끌었다.
    • 버전: Classic(v1)Berry(v2 이상)로 나뉘며, 최근에는 Berry 버전을 많이 사용한다.
  • pnpm (Performant npm):
    • 특징: 컴퓨터 내에 같은 라이브러리가 있다면 중복해서 저장하지 않고 링크(Symlink)로 연결하여 디스크 용량을 획기적으로 아낄 수 있다.
  • Bun:
    • 특징: 단순한 패키지 매니저가 아니라 자바스크립트 실행 도구(런타임)이다. 그 안에 패키지 매니저 기능이 포함되어 있는데, 속도가 압도적으로 빠르다는 것이 가장 큰 장점이다.

1. npm (Node Package Manager)

  • 역사 (2010년): 아이작 슐루터가 Node.js를 위해 만들었다. 이전에는 라이브러리를 직접 다운받아 폴더에 넣어야 했는데, npm이 등장하면서 명령어 한 줄로 설치가 가능해졌다.
  • 설명: Node.js를 설치하면 자동으로 깔리며, 가장 방대한 커뮤니티와 자료를 가지고 있다.
  • 특징:
    • 초기의 문제: 초창기에는 설치 속도가 느리고, 의존성(라이브러리 간의 관계) 관리가 꼬이는 지옥(Dependency Hell)이 종종 발생했다.
    • 현재: Yarn의 등장 이후 자극을 받아 속도와 보안이 대폭 개선되었다. 여전히 가장 무난하고 안전한 선택이라고 할 수 있다.

2. Yarn (Yet Another Resource Negotiator)

  • 역사 (2016년): 페이스북(현 Meta)이 거대한 프로젝트를 운영하다 보니 npm의 느린 속도와 불안정함을 견딜 수 없어 자체적으로 개발해 공개했다.
  • 특징:
    • Lock 파일 도입: yarn.lock 파일을 처음으로 도입하여, 모든 팀원이 완벽하게 동일한 버전의 패키지를 설치하도록 보장했다. (나중에 npm도 이를 따라 package-lock.json을 만듦)
    • 버전의 분리: 현재는 Yarn Classic (v1)과 완전히 새로 설계된 Yarn Berry (v2 이상)로 나뉜다. Berry는 굉장히 혁신적이지만 설정이 까다로워 호불호가 갈린다고 한다.

3. pnpm (Performant npm)

  • 역사 (2017년): 졸탄 코찬(Zoltan Kochan)이 개발했는데, "왜 똑같은 라이브러리를 프로젝트마다 중복해서 저장해서 내 하드 디스크를 낭비하는가?"라는 불만에서 시작되었다.
  • 특징:
    • 중복 제거: 컴퓨터 내부의 글로벌 저장소에 라이브러리를 딱 한 번만 저장하고, 프로젝트에서는 심볼릭 링크(바로가기)로 연결만 한다.
    • 엄격함: npm이나 Yarn은 설치하지 않은 하위 의존성 패키지에 접근할 수 있는 '유령 의존성' 문제가 있는데, pnpm은 이를 원천 차단하여 매우 깔끔한 관리가 가능하다.

4. Bun

  • 역사 (2022~2023년): 재러드 섬너가 공개했습니다. 단순히 패키지 매니저만 만든 게 아니라, Node.js 자체를 대체하는 새로운 런타임을 만들었다.
  • 특징:
    • 통합: 패키지 매니저(bun install)뿐만 아니라 실행(node 대체), 번들러(webpack 대체), 테스트 도구(jest 대체)가 하나로 합쳐져 있다.
    • 압도적 속도: 설치 속도가 npm보다 최대 30배 빠르다는 벤치마크 결과가 있을 정도로 속도 면에서는 굉장히 빠르다.
구분npmYarnpnpmBun
핵심 키워드표준, 안정성안정적 개선, 기능디스크 절약, 효율초고속, 올인원
속도보통빠름매우 빠름압도적으로 빠름
디스크 효율낮음낮음최상 (공유 사용)낮음 (캐시 방식)
추천 대상입문자기존 Yarn 사용자용량 부족한 분속도 중시

이렇게 4가지 종류의 패키지 매니저를 보고 나서 의문이 들었던게, 그럼 npm (패키지매니저) 만 npm https://www.npmjs.com/과 연결되어 있는건가? 라는 의문이 들었다. 그럼 나머지 매니저들은 너무 부실하지 않나? 라는 생각…

하지만 세상은 그렇게 쉽게 굴러가지 않았다!

npm이라는 단어는 두 가지 뜻이 있다

  • 거대한 창고 (npm Registry): 전 세계 개발자들이 만든 코드가 저장된 데이터베이스 (우리가 보는 npm 웹사이트)
  • 배송 기사 (npm CLI): 그 창고에서 물건을 가져오는 도구 (우리가 컴퓨터에 설치하는 프로그램)

다른 도구들(yarn, pnpm, bun)은 그저 배송기사의 역할만 바꾼것 뿐이였다!

창고는 그대로이고 (npm 웹사이트) 그걸 우리에게 가져다주는 배송기사(패키지 매니저)의 역할만 바꿨기때문에 어떤 패키지매니저를 써도 npm에 있는 엄청나게 다양한 오픈소스들을 우리가 손쉽게 가져다쓸 수 있는 구조이다.

그럼 이제 내가 사용하고자 하는 Bun에 대해서 조금만 더 자세히 알아보려고 한다!



Bun

bun 뭐냐고 gemini한테 물어보니

Node.js를 대체하기 위해 태어난, 스테로이드를 맞은 런타임

라고 하는데, 설명을 들으니 왜 스테로이드를 맞았다는지 알겠다!

우리가 Node.js를 사용해서 개발할 때, 실제로는 수많은 도구를 덕지덕지 붙여서 사용한다.

  • 실행은 Node.js
  • 패키지 관리는 npm
  • 테스트는 Jest
  • 번들링(파일 합치기)은 Webpack이나 Vite
  • 타입스크립트 변환은 ts-node

Bun은 이 모든 것을 하나의 실행 파일(bun)에 다 넣어버렸다!


왜 이렇게 빠를까?

bun의 아주 큰 장점 중 하나는 빠르다는 것인데, 그럼 도대체 왜 이렇게 빠른지 알아보려고 한다.

① 엔진의 교체: V8 → JavaScriptCore

  • Node.js는 구글 크롬 브라우저에 들어가는 V8 엔진을 사용한다. Node.js는 성능이 좋지만 메모리를 많이 먹고 무겁다.
  • Bun은 애플 사파리 브라우저에 들어가는 JavaScriptCore (JSC) 엔진을 사용한다. JSC는 V8보다 시작 속도(Startup time)가 훨씬 빠르고 메모리 사용량이 적도록 최적화되어 있다. 모바일 기기에서의 성능을 위해 설계되었기 때문이라고 한다.

② 프로그래밍 언어: C++ → Zig

  • Node.js는 C++로 작성되었다.
  • Bun은 Zig(지그)라는 최신 시스템 프로그래밍 언어로 작성되었다. Zig는 C언어처럼 로우 레벨 메모리 제어가 가능하면서도, 훨씬 더 현대적인 최적화가 가능하다고 한다.

Bun의 기능

① 런타임 (Runtime)

  • 기능: 자바스크립트/타입스크립트 파일을 실행한다. (node index.js 대신 bun index.js)
  • 강점: 타입스크립트(.ts)를 별도 설정 없이 바로 실행 (Node.js는 설정을 따로 해줘야 함)
  • 호환성: Node.js의 내장 모듈(fs, path, http 등)을 90% 이상 구현해 두어서, 기존 Node.js 코드가 대부분 그대로 돌아간다.

② 패키지 매니저 (Package Manager)

  • 기능: npm install 대신 bun install
  • 강점: 세계에서 가장 빠른 패키지 매니저를 표방한다. npm보다 최대 30배 빠르다고 한다. 글로벌 캐시를 사용하여 다운로드 속도를 줄이고, 심지어 오프라인 상태에서도 캐시가 있다면 설치가 된다.

③ 번들러 (Bundler)

  • 기능: 여러 개의 JS 파일을 하나로 합치고 최적화 (Webpack, Vite, Parcel 대체)
  • 강점: bun build 명령어 하나로 수십만 줄의 코드를 눈 깜짝할 새(0.x초 단위)에 번들링한다. esbuild보다 더 빠르다고 주장한다고 한다.

④ 테스트 러너 (Test Runner)

  • 기능: 코드가 잘 돌아가는지 테스트합니다. (Jest, Vitest 대체)
  • 강점: bun test 명령어를 사용합니다. Jest와 문법이 거의 호환되면서 속도는 훨씬 빠르다.

특별한 기능: bun.lock (텍스트 기반 락파일)

Bun은 초기에는 속도를 위해 바이너리 파일(bun.lockb)을 사용했지만, 최신 버전부터는 텍스트 기반의 bun.lock을 기본으로 사용한다.

  • 진화 (Binary → Text): 초기에는 읽을 수 없는 바이너리 파일을 사용하여 "Git에서 변경 내역을 볼 수 없다"는 단점이 있었으나, 최근 업데이트를 통해 사람이 읽을 수 있는 텍스트 형식으로 변경되었다.
  • 장점:
    • 가독성: 이제 git diff를 통해 패키지 버전 변경 사항을 눈으로 직접 확인할 수 있다.
    • 여전한 속도: 텍스트로 바뀌었음에도 Bun의 파서(Parser)가 워낙 빨라 성능 저하는 거의 없다.

Bun의 장/단점

구분내용
✅ 장점압도적인 속도 (설치, 실행, 빌드, 테스트 전 분야)
TypeScript 네이티브 (설정 없이 바로 실행)
설정 지옥 탈출 (All-in-One 툴킷)
Node.js 호환성 (기존 npm 패키지 사용 가능)
❌ 단점초기 단계 (Node.js에 비해 검증 기간이 짧음, 버그 가능성)
생태계 호환성 (특수 기능을 쓰는 일부 라이브러리 미지원)
정보 부족 (에러 발생 시 레퍼런스가 적음)

여기서 말하는 단점 : 생태계 호환성은 아래와 같은 이유로 발생한다.

  • 엔진의 차이 (V8 vs JavaScriptCore)

    • 어떤 라이브러리들은 성능을 극한으로 올리기 위해 V8 엔진 전용 명령어(v8 모듈 등)를 직접 사용하게 된다.
    • Bun은 V8 엔진이 아니므로, 이런 코드를 만나면 멈춰버린다.
  • C++ 네이티브 모듈

    • node_modules 안에는 자바스크립트 파일만 있는 게 아니라, 성능이 중요한 라이브러리(이미지 처리, 암호화 등)는 C++로 짜인 파일을 포함하게 된다.
    • 이 C++ 파일들은 Node.js의 내부 구조에 딱 맞춰서 컴파일되는데, Bun이 이걸 실행하려면 Node.js의 내부 구조인 척 속여주는(N-API 지원) 과정이 필요한데, 이 과정에서 복잡한 설정이 꼬이면 실행이 안 되서 호환성이 떨어지게 된다.



Bun이 좋다, 빠르다는 말은 여러 번 들었고 사이드 프로젝트에서 써보기도 했지만, 정작 왜 빠른지, 왜 쓰는 건지 깊게 생각해보진 않았던 것 같다.

이번 기회에 정리하면서 도전적이고 새로운 기술을 써보는 재미를 다시 한번 느꼈다! 😘😘

profile
하고싶은거 짱많은 주니어 프론트엔드 개발자

0개의 댓글