
다니엘 르미르가 자바스크립트 웹소켓 서버 성능을 다시 비교하며 과거의 ‘Bun이 Node.js보다 두 배 빠르다’는 결과를 바로잡았다. 르미르가 10월 10일 공개한 원문 분석과 공식 벤치마크 저장소에 따르면, 2023년 시험에는 Bun 서버가 메시지를 잘못 전달하는 오류가 있었다.
웹소켓은 실시간 채팅과 알림, 협업 편집 등에 쓰이는 통신 방식이다. 이번 시험은 두 클라이언트가 서버를 거쳐 메시지를 주고받는 구조다. 한 차례 왕복에는 ‘클라이언트 1→서버→클라이언트 2→서버→클라이언트 1’의 네 번 전송이 필요하다. 그러나 당시 Bun 코드는 메시지를 상대 클라이언트가 아니라 보낸 쪽으로 되돌려 두 번만 전송했다. 작업량이 달라 성능이 부풀려진 셈이다. 수정된 클라이언트는 이런 오류를 검사한다.
르미르는 자바스크립트 클라이언트가 느려 서버 간 차이를 가리는 문제도 지적했다. 이를 줄이기 위해 C로 작성한 클라이언트를 추가했다. 공개 저장소에는 기존 자바스크립트 클라이언트와 새 C 클라이언트의 결과가 함께 실려 있다.
새 시험은 인텔 Xeon Gold 6548N을 탑재한 리눅스 서버에서 진행됐다. 서버와 클라이언트를 서로 다른 CPU 코어에 고정하고, 외부 네트워크가 아닌 같은 기기의 루프백 인터페이스로 연결했다. 비교 대상은 Node.js 26.11.1과 uWebSockets.js 20.71.0 조합, Bun 1.4.2의 Bun.serve, Deno 2.9.7의 내장 서버다.
16바이트 메시지를 단일 연결쌍이 순차적으로 주고받는 시험에서 Node.js와 uWebSockets.js 조합은 초당 약 4만9000회 왕복을 기록했다. Deno는 약 4만회, Bun은 약 3만7000회였다. 기준점으로 둔 간단한 C 중계 서버는 약 5만4000회다. 왕복 지연시간의 중앙값은 Node.js 조합이 20.4마이크로초, Deno가 25.0마이크로초, Bun이 26.8마이크로초로 측정됐다. 99백분위 지연시간은 각각 24.8, 32.0, 46.4마이크로초였다.
다만 이는 런타임 자체만 비교한 결과가 아니다. Node.js에는 C++ 네이티브 애드온인 uWebSockets.js를 붙였고, Bun과 Deno는 내장 서버를 사용했다. 단일 연결쌍의 왕복 속도 역시 서버가 처리할 수 있는 동시 접속 수나 실제 서비스의 최대 처리량을 뜻하지 않는다.
부하를 늘리면 순서도 달라졌다. 저장소의 별도 시험은 클라이언트 네 개 스레드로 64개 연결쌍을 구동해 서버 코어를 포화시켰다. 같은 16바이트 메시지 조건에서 Bun 내장 서버는 초당 약 9만9000회 왕복, Node.js와 uWebSockets.js 조합은 약 9만3000회, Deno 내장 서버는 약 7만6000회를 기록했다. 한 연결쌍의 응답 지연과 여러 연결쌍의 부하 처리에서는 같은 순위를 기대할 수 없다는 점을 보여준다.
르미르는 코드와 원시 측정 결과, 집계 스크립트를 공개했다. 이번 비교는 특정 런타임의 전면적인 우열을 가리기보다, 메시지 전달 경로와 클라이언트 병목, 서버 구현, 부하 조건을 함께 확인해야 성능 수치를 해석할 수 있음을 드러낸다. 모두 한 기기 안에서 얻은 결과인 만큼 실제 서비스의 네트워크 지연과 접속 규모는 별도로 측정해야 한다.
출처: 다니엘 르미르 웹소켓 벤치마크 원문 https://lemire.me/blog/2026/10/10/websocket-servers-in-javascript-node-js-bun-and-deno-in-2026/
다니엘 르미르 공식 벤치마크 저장소 https://github.com/lemire/jswebsocket_bench
벤치마크 README(검증 시점 버전) https://github.com/lemire/jswebsocket_bench/blob/1b17e03facdb26f29879ae3b2a6e08f7b978843f/README.md