NodeJS vs Bun vs Go

발행: (2026년 5월 25일 AM 04:22 GMT+9)
10 분 소요
원문: Dev.to

출처: Dev.to

Mon 25 May 2026,
전제:
저는 주로 Node 서비스를 만드는 4년 차 소프트웨어 개발자입니다. Node의 아키텍처, 한계, 그리고 고처리량 네트워크 I/O를 다룰 때의 프로덕션 역량을 꽤 잘 이해하고 있다고 자신 있게 말할 수 있습니다.
하지만 아직 Bun은 매우 새로워서, 간단한 벤치마크를 만들기로 했습니다. 같은 간단한 HTTP 서버를 Node, Bun, 그리고 Go에서 실행해 보는 것이죠.
Go는 여기서 컨트롤(기준) 역할을 합니다. Go는 베어메탈에 가깝기 때문에 좋은 기준이 될 것이라 생각했고, V8/JSC와 libuv/zig 안에서 Node와 Bun이 얼마나 부풀어 있는지 파악하고 싶었습니다.

로컬호스트에서 클라우드 현실까지—병목 현상을 단계별로 추적하기

로컬호스트 성능을 호스팅 환경과 혼동하기 쉽습니다. 로컬에서 간단한 hello‑world 벤치마크를 돌리고, Bun이나 Node가 랩탑 RAM 안에서 거대한 수치를 내뱉는 것을 보며 “내가 가장 좋아하는 런타임이 속도 면에서 절대적인 왕이다”라고 선언하곤 합니다.
하지만 로컬호스트는 거짓말입니다. RAM 안에서는 소프트웨어 아키텍처를 테스트하는 것이 아니라, CPU가 로컬 메모리 버스를 통해 문자열을 얼마나 빨리 복사할 수 있는지를 테스트하는 겁니다.

프로덕션의 진실을 파헤치기 위해, 저는 세 가지 인기 백엔드 스택을 Docker 안에서 엄격히 샌드박스하고, 다음과 같은 제어된 설정으로 실험했습니다:

  • 로컬 메모리 버스에서
  • Node, Bun, Go 모두 기본 제공 HTTP 서버를 실행하고, /json 엔드포인트에 들어오는 트래픽을 받아 간단한 JSON 응답을 반환하도록 함

우리의 여정은 로컬 Windows 개발 머신에서 시작되었습니다. 컨테이너를 단일 코어에 고정하고, 표준 단일 스레드 설정으로 4코어까지 확장했으며, 마지막으로 클러스터링을 도입했습니다.

벤치마크 단계

Node.jsBunGo (최적화된 Raw Bytes)
1 CPU Core Baseline~14,000 RPS~28,000 RPS~29,000 RPS
4 CPU Cores (No Cluster)~16,000 RPS (Stuck)~30,000 RPS (Stuck)~115,000 RPS 🚀
4 CPU Cores (Clustered)~110,000 RPS~170,000 RPS 🏆N/A (Go는 기본적으로 처리)

단일 스레드 한계: 4코어 환경에서 클러스터링을 사용하지 않았을 때, Node와 Bun은 완전히 멈춰 버렸습니다. JavaScript는 단일 스레드이기 때문에 오직 하나의 코어만 100% 활용했고, 나머지 3코어는 완전히 유휴 상태였습니다. 반면 Go의 네이티브 스케줄러는 하드웨어를 손쉽게 활용해 바로 115,000 RPS를 달성했습니다.

클러스터링된 괴물: Node의 cluster 모듈을 켜고 Bun 인스턴스를 4개 병렬로 띄우자, JavaScript 엔진이 깨어났습니다. Bun은 로컬 메모리 상에서 무려 170,000 RPS라는 충격적인 수치를 기록했으며, 이론상으로는 손대기 어려운 존재처럼 보였습니다.

그때 첫 번째 거대한 아키텍처 변화를 적용했습니다. 패킷을 로컬 랩탑 RAM의 안락함에서 벗어나 실제 물리적인 네트워크 레이어를 통과하도록 강제한 겁니다. 저는 MacBook을 Tailscale 가상 사설 메쉬 네트워크에 연결하고, 로컬 Wi‑Fi 어댑터를 통해 무선으로 요청을 전송했습니다.

트래픽이 공중으로 날아오르자, 170,000 RPS의 파워하우스는 바로 콘크리트 벽에 부딪혔습니다.

Node.js (4 Workers)Bun (4 Instances)Go (Optimized Raw Bytes)
Throughput (RPS)7,954 RPS12,519 RPS12,873 RPS 🏆
Average Latency26.79 ms16.49 ms15.69 ms 🏆
Max Outlier Latency864.53 ms ⚠️163.24 ms152.21 ms 🏆
Data Transfer Rate1.62 MB/s1.76 MB/s1.67 MB/s

엔진들은 이제 서로 경쟁하지 않았습니다. 모두 물리적인 Wi‑Fi 카드가 라디오 파를 변조하고 WireGuard UDP 래퍼를 처리하기를 기다리는 상황이었습니다.

Go가 왕관을 되찾다: Go의 네이티브 네트워크 폴러가 OS 커널 스택과 직접 통합돼 있어 네트워크 지터를 절대적인 안정성으로 처리했으며, 평균 및 최악 지연 시간을 가장 낮게 유지했습니다.

Node.js는 지터에 무너졌다: Node의 마스터 프로세스는 도착 시간이 고르지 않은 패킷을 워커들에게 고르게 분배하지 못해, 최악 지연 시간이 치명적인 864 ms까지 치솟았습니다.

참고: 제 PC는 매우 기본적인 Tenda U10 USB Wi‑Fi 어댑터를 사용하고 있습니다. Wi‑Fi 3만 지원하므로 아마도 병목이었을 가능성이 높습니다.

이 경험을 통해 시스템이 네트워크 병목에 걸리기 쉽고, 현재 하드웨어와 환경으로 테스트를 계속하는 것이 불공정하다는 것을 깨달았습니다. 그래서 테스트를 하드웨어 제한에서 격리하기 위해 DigitalOcean Droplet에 배포했습니다.

네트워크 잡음이나 로컬 가상화 레이어 없이 코드의 절대적인 한계를 알아보기 위해, 엔터프라이즈급 Linux 클라우드 하드웨어(10 Gbps 데이터센터 백플레인 위에 있는 DigitalOcean Shared Droplets)로 실험을 옮겼습니다.

  • 동일 데이터센터 스위치 안에 타깃 서버 VM과 별도 공격자 VM을 배치하고, Docker 런타임 플래그를 통해 리소스 환경을 네이티브하게 격리한 뒤, 다시 테스트를 진행했습니다.

1코어 격리 테스트 실행 방법

# Target VM - Launching Single Core Baselines
docker run --rm --cpus="1" -m="512m" -p 3000:3000 --name cloud-bench node-bench
docker run --rm --cpus="1" -m="512m" -p 3000:3000 --name cloud-bench bun-bench
docker run --rm --cpus="1" -m="512m" -p 3000:3000 --name cloud-bench go-bench
Node.js (1 Core)Go (1 Core - Optimized)Bun (1 Core)
Throughput (RPS)11,705 RPS13,935 RPS25,444 RPS 🏆
Average Latency29.13 ms22.83 ms7.89 ms 🏆
Max Outlier Latency2,000.00 ms ⚠️135.97 ms93.27 ms
Failed Requests60 Timeouts ⚠️00

단일 클라우드 코어에서 Node의 V8 엔진은 11 k 패킷/초를 처리하려다 내부 이벤트 루프 관리에 허덕이며 60개의 소켓 타임아웃을 발생시켰습니다. Bun의 초경량 Zig 이벤트 루프는 단일 코어 제약을 거뜬히 소화해 Go보다 두 배 빠른 속도를 기록했습니다.

멀티코어 클러스터링으로 완전 개방

마지막으로 모든 제한을 해제했습니다. 타깃 설정을 4 CPU 코어 할당으로 확장하고, JavaScript 런타임은 멀티스레드 스케줄링을 위해 클러스터링 변형을 사용했습니다.

# Target VM - Launching Multi-Core Clusters
docker run --rm --cpus="4" -m="512m" -p 3000:3000 --name cloud-bench node-bench-c
docker run --rm --cpus="4" -m="512m" -p 3000:3000 --name cloud-bench bun-bench-c
docker run --rm --cpus="4" -m="512m" -p 3000:3000 --name cloud-bench go-bench

로드 제너레이터는 Alpine 컨테이너 안에서 최적화된 실행 스레드 제한을 두고 실행했습니다.

# Attacker VM - The Native wrk Attack Command
docker run --rm alpine sh -c "apk add --no-cache wrk && wrk -t2 -c200 -d30s http://159.65.6.89:3000/json"
Node.js Cluster (4 Cores)Go Optimized (4 Cores)Bun Cluster (4 Cores)
**Throughput (
0 조회
Back to Blog

관련 글

더 보기 »

내 스킬

프로젝트를 위한 AI 지시문을 만들고, 설치하고, 관리하세요 — 코딩이 필요 없습니다. CREATE 이름을 정하고, 카테고리를 선택하고, 원하는 것을 설명하세요 — 마법사가 자동으로 구성합니다.