이전 Compo의 한계점 및 문제 해결
이전 Compo는 require
메서드를 오버라이딩하여 Ruby 스크립트와 확장 라이브러리를 단일 실행 파일에 결합하는 방식을 사용했으나, 다음과 같은 주요 문제에 직면했습니다.
* autoload
충돌: require
오버라이딩 시 autoload
가 내부적으로 require
를 호출할 때 상수가 초기화되지 않아 대규모 프로젝트에서 예외를 발생시켰습니다.
* 파일 접근 제한: 내장된 파일 데이터 접근이 require
로만 제한되어 File.read
등 일반적인 파일 I/O 함수로는 리소스(설정 파일, 이미지 등)를 읽을 수 없었습니다.
* 디렉터리 구조 미지원: 파일 단위 관리만 가능하여 디렉터리 순회 등 일반적인 파일 시스템 활용 패턴을 지원할 수 없었습니다.
새로운 Compo의 구현 전략
이러한 문제를 해결하기 위해 Compo는 두 가지 핵심 전략을 도입했습니다.
- 가상 파일 시스템 (Virtual File System, VFS) 구축:
- 단일 바이너리 내부에 계층적 파일 및 디렉터리 구조를 표현하는 읽기 전용 VFS를 자체 구현했습니다.
- 이를 통해 Ruby 스크립트 외 모든 종류의 리소스를 바이너리 내부에 포함하고 관리할 수 있게 되었습니다.
libc
함수 랩핑을 통한 I/O 경로 스위칭:- Ruby가
read
와 같은libc
의 파일 I/O 함수를 호출할 때, 실제 파일 시스템과 가상 파일 시스템 중 어느 곳에서 데이터를 읽을지 동적으로 선택하는 랩핑 계층을 도입했습니다. dlsym(RTLD_NEXT, "read")
를 활용하여libc
의 원본 함수 주소를 획득하고, Compo의 랩핑 함수 내에서 파일 경로(절대/상대) 및Dir.chdir
에 따른 현재 디렉터리 변경을 고려하여 적절한 I/O 소스로 요청을 전환합니다.
- Ruby가
Rails 프로젝트 원 바이너리화 시연
발표에서는 Ruby가 설치되지 않은 Docker 환경에서 단일 Compo 실행 파일이 완전한 Rails 애플리케이션을 성공적으로 구동하고, 데이터베이스 연동까지 수행하는 모습을 시연하여 새로운 구현 방식의 성공을 입증했습니다.