WebAssembly(WASM)는 이진 명령어 형식으로, 이식성을 보장하며 샌드박스 환경에서 코드를 실행하도록 설계되었습니다. 이는 LLVM 툴킷의 또 다른 타겟으로 작동하여, C Ruby 인터프리터와 같은 코드를 WASM 모듈로 컴파일하여 다양한 VM 런타임 및 모든 브라우저에서 실행 가능하게 합니다. WASM은 명시적으로 내보내거나 가져오지 않는 한 모듈 외부의 어떤 작업도 허용하지 않는 샌드박스 특성을 가집니다. 이를 보완하기 위해 WebAssembly System Interface(WASI)가 표준 시스템 호출 목록을 정의하여 WASM 모듈이 다양한 플랫폼에서 실행될 수 있도록 지원합니다. 그러나 WASI Preview 1은 스레드, 네트워킹, 동적 연결 등 여러 기능에 제한이 있으며, 이는 Ruby WASM에도 동일하게 적용됩니다.
Ruby WASM은 CRuby 인터프리터에 WASI 호환성을 위한 패치가 적용된 형태로, WASI의 제약을 공유합니다. 특히 동적 연결의 부재는 사용할 수 있는 젬의 수를 제한하지만, 여전히 많은 젬을 활용할 수 있습니다. 젬 설치는 빌드 타임 패키징 시스템을 통한 방식과 런타임 설치 방식이 있습니다. 런타임 설치는 네트워킹을 필요로 하는데, WASI Preview 1의 네트워킹 제한을 극복하기 위해 Ruby WASM의 핵심 기능인 JavaScript Interop이 활용됩니다. 이를 통해 Ruby 코드에서 JavaScript를 실행하고 값을 주고받을 수 있어, JavaScript의 Fetch
API를 사용하여 네트워크 요청을 처리할 수 있습니다. 발표자는 Socket
과 같은 누락된 코어 클래스나 C 함수를 원숭이 패치(Monkey Patching)하여 에러를 회피하는 방법을 시연하며, 이는 비록 ‘추악한’ 방식이지만 현재로서는 효과적인 해결책임을 강조합니다. 이와 더불어 bundler의 초기 메타데이터 캐싱 문제를 클라우드에서 최적화된 단일 파일 다운로드 방식으로 해결하는 등 다양한 실용적인 해결책을 제시합니다.
나아가, 브라우저 내에서 Ruby 기반 웹 서버를 구동하는 가능성도 제시됩니다. Rack 미들웨어를 활용하여 Ruby의 Rack
애플리케이션을 JavaScript 코드로 대체하고, Service Worker를 통해 브라우저의 네트워크 요청을 가로채 Ruby 애플리케이션이 생성한 응답을 반환하는 방식으로 구현됩니다. 이는 Rails 애플리케이션을 브라우저에서 실행할 수 있는 잠재력을 보여주지만, C 확장, 데이터베이스 어댑터(소켓 사용) 등 더 많은 복잡한 문제를 해결해야 함을 인정합니다. 그러나 전반적인 패치 및 우회 기법은 동일하게 적용될 수 있음을 시사합니다.