WebAssembly는 이진 명령어 형식이며 샌드박스 환경으로 설계되어 뛰어난 이식성을 제공합니다. LLVM 툴킷의 또 다른 타겟으로 작동하여 C 언어 기반의 Ruby 인터프리터를 Wasm 모듈로 컴파일할 수 있게 합니다. 그러나 Wasm 모듈은 명시적으로 내보내고 가져오지 않는 한 모듈 외부의 어떤 작업도 수행할 수 없는 샌드박스 특성을 가집니다. 이를 보완하기 위해 WASI가 등장했는데, 이는 POSIX와 같은 표준 시스템 호출 목록을 정의하여 Wasm 모듈이 다양한 플랫폼에서 실행될 수 있도록 합니다. 하지만 WASI Preview 1은 스레드, 네트워킹, 동적 연결과 같은 중요한 기능에 제약이 있어 Ruby Wasm 또한 이와 동일한 문제를 겪습니다.
이러한 한계를 극복하기 위해 발표자는 몇 가지 창의적인 해결책을 제시합니다. 첫째, Ruby Wasm의 가장 흥미로운 기능 중 하나인 JavaScript Interop을 활용합니다. 이는 Ruby 코드에서 JavaScript 함수를 호출하고 값을 주고받을 수 있게 하여, WASI가 직접 지원하지 않는 네트워킹(예: fetch
API)을 JavaScript를 통해 우회적으로 사용할 수 있게 합니다. 이를 통해 bundler
를 이용한 젬 설치와 같은 네트워크 의존적인 작업을 가능하게 합니다. 둘째, Ruby Wasm에서 누락된 코어 클래스나 C 함수로 인해 발생하는 오류는 ‘몽키 패칭(monkey patching)’ 기법을 통해 해결합니다. 이는 필요한 클래스나 메서드를 최소한으로 재구현하여 오류를 회피하는 방식입니다. 셋째, 가상 파일 시스템을 JavaScript와 Ruby Wasm 간에 공유하여 브라우저 내에서 파일을 수정하고 실행할 수 있도록 합니다.
또한, 강연에서는 Ruby Wasm을 통해 웹 서버를 구동하는 놀라운 시연을 보여줍니다. 이는 Ruby의 Rack 인터페이스를 활용하여 HTTP 요청을 JavaScript의 fetch
API로 가로채고, Service Worker를 통해 Ruby 애플리케이션으로 전달하여 응답을 생성하는 방식으로 구현됩니다. 비록 현재 상태의 Ruby Wasm이 Rails와 같은 복잡한 프레임워크를 완벽하게 지원하기에는 C 확장 젬, 데이터베이스 어댑터(소켓 사용) 등 해결해야 할 과제가 많지만, 이러한 해킹과 우회적인 방법들이 브라우저 내에서 완전한 Ruby 개발 환경을 구현하는 가능성을 열어줍니다. 젬 다운로드 프록시 구현이나 번들러 메타데이터 캐싱 최적화와 같은 세부적인 문제 해결 노력도 언급됩니다.