- 독립 개발자 Theo Browne의 벤치마크에서 Cloudflare Workers가 Vercel Node.js보다 최대 3.5배 느린 성능을 보임
- 벤치마크 결과의 원인은 여러 인프라·라이브러리 설정 및 벤치마크 방법론상의 문제 때문임
-
스케줄링 알고리듬 개선, V8 가비지 컬렉터 튜닝, OpenNext 최적화 등 다수의 플랫폼 및 프레임워크 개선이 이루어짐
- 주요 패치로 인해 현재 대부분의 벤치마크에서 Cloudflare와 Vercel 간 성능 차이가 크게 감소하였음
- 앞으로도 Cloudflare는 공개 인프라와 프레임워크 개선에 기여하며, 지속적인 최적화와 벤치마크 검증을 이어갈 계획임
개요 및 벤치마크 논란
- 2023년 10월, 개발자 Theo Browne가 Cloudflare Workers와 Vercel(AWS Lambda 기반)의 서버측 JavaScript 실행 속도를 비교하는 벤치마크를 공개함
- Cloudflare Workers는 V8 자바스크립트 엔진을 기반으로 Vercel과 같지만, 최대 3.5배의 성능 저하가 관찰됨
- 인프라 미세 튜닝, 자바스크립트 라이브러리 차이, 테스트 방식 문제 등 다양한 원인으로 불합리한 성능 격차가 발생함
- 이 문제점들을 개선하는 과정에서 Cloudflare Workers 전체 성능이 향상됨
- 주요 수정 사항 중에는 삼각함수 연산 속도 개선 등 타 플랫폼에 영향을 줄 수 있는 개선도 포함됨
벤치마크 방법론
- Theo의 최초 테스트 클라이언트는 샌프란시스코에서 Webpass로 접근, Vercel은 sfo1 지역에서 실행됨
- Cloudflare에서는 AWS us-east-1 데이터센터 내에서 Vercel의 iad1 인스턴스와 직접 통신함으로써 네트워크 지연의 영향을 최소화함
- 벤치마크는 모두 단일 스레드(vCPU 1개) 환경에서 이루어졌으며, 가격 비교도 쉽게 맞춤
- 테스트 중에 발견된 버그는 Pull Request로 업스트림에 제출되어 수정됨
Cloudflare 플랫폼의 성능 개선
Workers Runtime의 스케줄링 및 격리 처리 개선
- 기존에는 트래픽을 "웜" 격리(빠르게 처리가능한 인스턴스)로 라우팅하는 알고리듬을 사용해 대규모 앱의 레이턴시 및 처리량을 최적화했으나, CPU 집약적인 워크로드에 비효율적이었음
- CPU 점유가 큰 요청이 몰릴 경우, 대기열이 길어지고 지연이 커진 현상이 벤치마크에서 드러남
- Cloudflare Workers는 빌링 기준이 CPU 사용 시간이므로, 대기 시간(격리 준비 대기)은 비용이 부과되지 않음
-
알고리듬 개편을 통해 CPU 사용량이 큰 워크로드를 더 빨리 감지, 신규 격리를 빠르게 생성하도록 개선함
- I/O 바운드와 CPU 바운드 워크로드 모두에 효율적으로 대응, 전 세계적으로 배포되어 즉시 반영됨
V8 가비지 컬렉터 설정 개선
- 테스트 과정에서 JavaScript 가비지 컬렉션과 메모리 관리 이슈가 성능 저하에 큰 영향을 미침을 확인
- V8 엔진의 "young generation" 메모리 영역 크기 설정이 너무 제한적으로 고정되어 있었음 (과거 권장치인 128MB에 맞춤)
- 최신 V8에서는 해당 설정 방식이 오히려 불필요한 빈번한 GC 발생을 유발
- 수동 튜닝을 해제하고, V8 자체의 휴리스틱 기반 동적 메모리 할당 허용
- 약 25% 벤치마크 성능 향상을 확인, 모든 Workers에 적용
OpenNext 기반 Next.js 성능 최적화
불필요한 메모리 할당 및 복제 제거
- 분석 결과, 요청 처리 시간 중 10–25%가 메모리 해제(GC) 에 소모
- OpenNext, Next.js, React는 내부 데이터 버퍼를 과도하게 복제하는 코드 패턴이 다수 있었음
- 스트림 출력 데이터 전체를 불필요하게 복사하는 작업, Buffer.concat으로 단순 길이 측정 목적으로 대량 데이터 복사가 이루어짐
- 관련 이슈들을 OpenNext 저장소에 Pull Request로 개선 중
- 전체 플랫폼에서 공통적으로 성능 개선될 수 있도록 계속해서 고도화 계획
비효율적인 스트림 어댑터 최적화
- Workers는 Web Streams API, Next.js는 Node.js의 스트림 API 위주로 설계되어 변환 어댑터가 필요함
- 불필요하게 중첩된 어댑터 사용, 메모리 복제 및 버퍼링 오버헤드 다수 발생
- 단순히 ReadableStream.from(chunks)로 코드를 축소해 중간 복제를 제거
- 기본적으로 단일 값 스트림(highWaterMark=1) 구조를 바이트 스트림(highWaterMark=4096 등)으로 개선해 대량 데이터 처리를 최적화
- 향후 Next.js 및 React의 스트림 처리 개선 패치도 상위 플랫폼으로 upstream 예정
JSON.parse() 성능 문제와 V8 패치
- Next.js 및 React 전반에서 reviver 옵션이 포함된 JSON.parse() 사용 시 과도한 호출이 발생(100,000회 이상)
- 최신 ECMAScript 표준에서 세 번째 인자(소스 컨텍스트)를 reviver에서 받을 수 있게 되어, 성능이 추가 악화됨(파이어폭스, Chrome 등 공통)
- Cloudflare Workers 팀이 V8 엔진에 패치 제공(33% 성능 개선) , Node.js와 크롬 브라우저, Deno 등 전 생태계에 이득이 돌아갈 예정
Node.js의 삼각함수 성능 문제
- Theo의 벤치마크와 별개로, 수학 삼각함수(sin, cos 등) 반복 호출 벤치마크에서 Cloudflare Workers가 3배 빠른 결과 보고됨
- 원인은 Node.js가 V8에서 제공하는 최신/고속 삼각함수 경로(compile-time flag)에 미처 대응하지 못했던 것임
- Cloudflare Workers는 우연히 해당 플래그를 기본 활성화, Node.js에는 Pull Request로 패치 제출
- 이 문제 역시 오픈소스 생태계 공통성이므로, AWS Lambda와 Vercel까지 반영 시 전반적인 속도 안정화 기대
벤치마크 설계/측정상의 한계와 교훈
- 벤치마크는 대부분 클라이언트에서 요청 시간(latency) 측정 방식으로, 실제 서버측 CPU 사용 시간을 직접 측정하지 않음
- 네트워크 경로, 데이터센터 위치, 하드웨어 세대, 멀티테넌시 등 다양한 비교 불가능한 변수가 결과에 영향을 줄 수 있음
- 응답의 첫 바이트 도달 시간(TTFB)만 측정한 경우, 전체 렌더링/전송 시간 반영 어려움. TTFL로 바꾸면 네트워크 속도 차이에 더 민감해질 수 있음
- 서버 하드웨어/소프트웨어 다양성, 인스턴스 할당 운 등에 따라 일시적/연관성 있는 노이즈도 존재함
- 벤치마크용 환경 및 업무 흐름 정확화, 변수를 맞추는 과정에서 실무적 개선점을 도출, 자사·타사 플랫폼 모두에 유익을 줌
실험 중 발견된 벤치마크 및 환경 설정 문제
- Next.js의 force-dynamic 설정 미적용, 캐시 처리 로직, 응답 스트리밍 방식 차이 등으로 결과 오해 위험이 있었음
- React SSR 벤치마크에서 NODE_ENV 환경 변수 미설정으로 dev mode 동작, 실제보다 느린 결과 반환
- 이러한 오류는 환경 변수를 명시적으로 설정하여 수정
앞으로의 계획 및 결론
- Cloudflare Workers Runtime의 다양한 성능 개선 사항이 이미 전면 적용, 사용자는 별도 조치 없이 이득 효과
- Theo에게 테스트 코드, OpenNext 최적화 등이 반영된 Pull Request를 제공
- OpenNext와 Vercel 기반 Next.js 간 격차 해소를 위한 추가 개선 예정
- 스케줄링 알고리듬 및 오픈소스 엔진(V8, Node.js) 지속적 업그레이드 및 커뮤니티 기여 방침
- 더 나은 벤치마크와 프로파일링으로 잠재 이슈 조기 발견, 최적화 및 공유 문화 유지 예정
참고 자료 및 추가 링크