이전 Compo 버전은 Ruby의 require
메서드를 오버라이드하여 필요한 스크립트와 확장 라이브러리를 단일 실행 파일에 통합하는 방식을 사용했습니다. 이 방식은 Sinatra와 SQLite를 결합한 정도의 소규모 애플리케이션에는 적용 가능했으나, Rails와 같이 규모가 크고 복잡한 Ruby 프로젝트에는 여러 한계점을 드러냈습니다. 주요 문제점으로는 autoload
기능과의 충돌로 인한 초기화 문제, require
외의 다른 I/O 메서드(File.read
, IO.open
등)로는 임베드된 파일을 읽을 수 없는 점, 그리고 디렉토리 개념의 부재 등이 있었습니다. 이는 Ruby 프로젝트가 설정 파일, 이미지, CSV 등 다양한 비-Ruby 파일을 포함하며 디렉토리 구조에 의존하는 경우가 많기 때문에 큰 걸림돌이었습니다.
새로운 Compo는 이러한 문제들을 해결하기 위해 두 가지 핵심 전략을 도입했습니다. 첫째, 바이너리 내부에 가상 파일 시스템(Virtual File System, VFS)을 구축하여 임베드된 파일과 디렉토리를 계층 구조로 관리합니다. 이 VFS는 읽기 전용으로 구현되어 단순한 파일 로딩에 중점을 둡니다. 둘째, Ruby의 C 레벨 I/O 함수(read
, open
, chdir
등) 호출을 가로채는 방식(인터셉션)을 사용합니다. 이를 위해 dlsym
함수와 RTLD_NEXT
핸들을 이용하여 원본 C 함수의 주소를 동적으로 획득하고, Compo의 래핑 함수를 통해 실제 파일 시스템과 가상 파일 시스템 중 어디에서 파일을 읽어올지 동적으로 전환합니다. 이 방식은 require
뿐만 아니라 모든 파일 I/O 작업에서 임베드된 데이터를 투명하게 처리할 수 있게 합니다. 시연에서는 Ruby가 설치되지 않은 Docker 환경에서 Rails 애플리케이션이 성공적으로 단일 실행 파일로 구동되는 것을 보여주며, 이는 Compo의 발전된 기능을 명확하게 입증했습니다.