QuickJS RB는 Fabrice Bellard가 개발한 경량 JavaScript 엔진 QuickJS를 Ruby 바인딩으로 래핑한 Gem입니다. 발표자는 QuickJS가 ECMAScript 2023을 지원하고 C 언어로 작성되어 바이너리 크기가 작다는 점에 주목했습니다. 이 프로젝트의 핵심은 QuickJS를 Ruby 환경에 ‘제품화’하고 ‘인터페이싱’하는 것이었습니다.주요 구현 내용은 다음과 같습니다.* 샌드박싱: QuickJS의 OS 리소스 접근 기능을 기본 제한하고, CRuby로 구현된 대체 기능을 제공하여 보안을 강화했습니다.* 주변 기능: QuickJS에 부족한 국제화(Intl) API를 지원하기 위해 기존 오픈소스 프로젝트의 주변 기능을 통합했습니다. 대규모 JS 번들을 QuickJS 컴파일 기능을 활용, C 코드로 변환하여 메인 빌드에 포함시키는 독창적인 방식을 적용했습니다.* Ruby 인터페이스:
* Import 기능: ES 모듈을 Ruby에서 JS 구문과 유사하게 import
메서드를 통해 유연하게 가져올 수 있도록 설계했습니다. Ruby의 패턴 매칭으로 다양한 import 방식을 지원합니다.
* console.log
지원: JS 코드 내 console.log
호출 시, 로그가 Ruby 런타임 인스턴스에 기록되어 Ruby에서 접근 및 관리할 수 있습니다.
* define_function
기능: Ruby로 구현된 함수를 JS 런타임에 정의하여 JS 코드에서 직접 호출할 수 있게 했습니다. 이는 커스텀 HTTP 클라이언트 제공 등 강력한 Ruby-JS 상호작용을 가능하게 하며, JS 내에서 Ruby 예외를 투명하게 처리할 수 있습니다.QuickJS RB는 Persona의 커스텀 코드 시스템에서 하루 4백만 건 이상의 JS 호출을 처리하며, FaaS 비용 절감 및 HTTP 요청 감소를 통한 성능 향상을 달성했습니다. 또한, 동료 개발자가 DSL 파서를 백엔드와 프론트엔드에서 단일 JS 코드로 재사용하는 데 활용하며, QuickJS RB의 새로운 활용 가능성을 입증했습니다.
QuickJS RB: Ruby에서 JavaScript를 실행하는 여정 및 실제 활용 사례
[EN] Running JavaScript within Ruby / Kengo Hamasaki @hmsk
작성자
RubyKaigi
발행일
2025년 05월 27일
핵심 요약
- 1 QuickJS RB는 Ruby에서 JavaScript 코드를 실행하는 Gem으로, FaaS 기반 시스템을 대체하여 비용 절감 및 성능 향상을 성공적으로 달성했습니다.
- 2 C 언어 기반 QuickJS 엔진을 Ruby 바인딩으로 래핑하여 샌드박싱, 국제화 지원, Ruby 함수 호출 등 실제 서비스에 필요한 기능을 구현했습니다.
- 3 Ruby의 네이티브 확장 및 패턴 매칭을 활용한 점진적 C 코드 개발과, 백엔드-프론트엔드 단일 JavaScript 코드 재사용의 이점을 발견했습니다.
도입
발표자는 RubyKaigi에서 Ruby 내에서 JavaScript를 실행하는 자신의 프로젝트인 `quickjs_rb` Gem에 대해 소개합니다. Persona라는 신원 확인 SaaS 플랫폼에서 프로덕트 엔지니어로 근무하며, 기존에 AWS Lambda와 같은 FaaS(Function as a Service)를 통해 JavaScript 커스텀 코드를 실행하는 시스템이 네트워크 지연, 관리 복잡성, 유지보수 비용 등의 문제점을 안고 있음을 언급합니다. 이러한 문제 해결을 위해 Ruby 애플리케이션 내에서 직접 JavaScript를 실행할 수 있는 솔루션의 필요성을 느끼게 되었고, QuickJS 엔진을 Ruby 바인딩으로 구현하게 된 배경을 설명합니다.
결론
QuickJS RB 프로젝트는 Ruby 개발자가 C 언어 기반의 네이티브 확장을 구축하는 것이 얼마나 즐겁고 실용적인 경험이 될 수 있는지를 보여줍니다. FaaS의 한계를 극복하고 Ruby 애플리케이션 내에서 JavaScript를 효율적이고 안전하게 실행하는 솔루션을 제공함으로써, 비용 절감과 성능 향상이라는 직접적인 비즈니스 가치를 창출했습니다. Ruby의 친화적인 개발 환경과 점진적인 C 언어 마이그레이션 전략은 복잡한 네이티브 확장을 성공적으로 구축하는 데 기여했습니다. 이 프로젝트는 Ruby와 JavaScript의 시너지를 통해 새로운 개발 가능성을 열었으며, 발표자는 Ruby 커뮤니티에 네이티브 확장 개발을 적극 권장합니다.