Ruby rdkafka 설치 문제 해결: 사전 컴파일된 네이티브 확장으로 60초의 기다림을 끝내다

The 60-Second Wait: How I Spent Months Solving the Ruby’s Most Annoying Gem Installation Problem

작성자
발행일
2025년 08월 14일

핵심 요약

  • 1 Ruby의 `rdkafka` 젬은 Apache Kafka 통합에 필수적이지만, 설치 시 60~90초에 달하는 긴 컴파일 시간으로 개발자들에게 큰 불편을 초래했습니다.
  • 2 이 문제를 해결하기 위해 저자는 `librdkafka` 및 관련 C 라이브러리들을 정적으로 링크하여 모든 의존성을 포함하는 사전 컴파일된 네이티브 확장을 개발했습니다.
  • 3 그 결과, 설치 시간이 5초 미만으로 단축되었고, Docker 빌드 및 CI 파이프라인 속도 향상, 개발 환경 설정 용이성 등 Ruby 개발 생태계 전반에 긍정적인 영향을 미쳤습니다.

도입

Ruby 개발자들에게 `bundle install` 명령은 익숙하지만, `rdkafka` 젬의 설치는 악명 높은 인내심 테스트였습니다. Apache Kafka 통합에 필수적인 이 젬은 컴파일에 60초에서 90초가 소요되어 개발자들을 좌절시켰고, Docker 빌드 시간과 CI/CD 파이프라인을 지연시켰습니다. Karafka 생태계의 관리자로서 저자는 이러한 고통을 수년간 지켜보았으며, 매월 백만 건 이상의 `rdkafka` 다운로드에서 발생하는 불필요한 컴파일 시간(매월 6천만 초, 약 2년치의 CPU 시간)이 엄청난 자원 낭비임을 깨달았습니다. 이 비효율성을 근본적으로 해결해야 할 필요성을 절감하며, 저자는 이 '60초 문제'를 해결하기 위한 여정을 시작했습니다.

이 문제의 핵심은 rdkafka 젬이 librdkafka라는 복잡한 C 라이브러리를 래핑하고, 이 라이브러리가 OpenSSL, Cyrus SASL, MIT Kerberos, 다양한 압축 라이브러리(zlib, zstd, lz4, snappy) 등 수많은 시스템 라이브러리에 의존한다는 점이었습니다. 각 Linux 배포판(Ubuntu, CentOS, Alpine)과 macOS 등 플랫폼마다 라이브러리 버전과 구현 방식이 상이하여 ‘호환성 지옥’이 발생했고, 동적 링크 방식으로는 범용적인 바이너리를 만드는 것이 불가능했습니다.

저자는 nokogiri 젬의 성공 사례와 Python의 wheels, Go의 정적 바이너리처럼 다른 생태계의 접근 방식을 연구했습니다. 그리고 모든 의존성을 소스 코드로부터 컴파일하여 최종 라이브러리에 정적으로 링크하는 방식을 채택했습니다. 이는 단순해 보였지만, 각 플랫폼(Linux x86_64 GNU, Alpine Linux의 musl libc, macOS ARM64)의 고유한 특성(다른 시스템 호출, 라이브러리 규칙, 컴파일러 동작) 때문에 수많은 난관에 부딪혔습니다.

이를 극복하기 위해 모든 의존성을 올바른 순서와 플래그로 컴파일하는 2,000줄 이상의 정교한 셸 스크립트를 개발했습니다. 또한, 사전 컴파일된 바이너리의 보안 문제를 해결하기 위해 모든 다운로드된 의존성에 대한 SHA256 검증, RubyGems Trusted Publishing을 통한 암호화 증명, 고정된 버전의 재현 가능한 빌드, 공급망 보호 등 포괄적인 보안 모델을 구현했습니다.

CI/CD 파이프라인 또한 복잡해졌습니다. Linux는 Docker 컨테이너, macOS는 실제 macOS 러너에서 빌드 및 테스트를 수행했으며, Ruby 3.1부터 3.5까지의 모든 버전을 지원하기 위해 각 플랫폼별로 10개의 CI 액션이 필요했습니다. 릴리스 과정 역시 단순한 gem push를 넘어 여러 플랫폼에서 동시에 빌드, 테스트하고 플랫폼별 젬을 조율하며, 보안 강화를 위해 RubyGems Trusted Publishing을 적용하는 등 전면적인 재구축이 이루어졌습니다.

결론

수개월간의 노력 끝에 모든 주요 플랫폼에서 작동하는 `rdkafka` 네이티브 확장이 성공적으로 완성되었습니다. 이제 `gem install rdkafka` 명령은 60초 이상 걸리던 과거와 달리 3~5초 만에 완료됩니다. 이러한 변화는 단순히 설치 시간을 단축하는 것을 넘어, Docker 빌드 및 CI 파이프라인 속도를 획기적으로 향상시켰고, 신규 개발자들이 컴파일 오류 없이 개발 환경을 쉽게 설정할 수 있게 했습니다. 또한, 매월 수백만 건의 다운로드를 고려할 때, 60초의 컴파일 시간 단축은 매월 16,667시간의 CPU 사용량 절감으로 이어져 에너지 소비와 탄소 배출량 감소에도 기여했습니다. 비록 사용자들은 이러한 개선 사항을 알아채지 못할 수 있지만, 저자는 가장 가치 있는 개선은 종종 눈에 띄지 않는 곳에서 이루어진다고 강조합니다. 개발자들이 컴파일을 기다리는 대신 창의적인 작업에 집중할 수 있게 하고, CI 파이프라인이 빨라져 더 많은 반복과 혁신을 가능하게 함으로써, 이 프로젝트는 Ruby 개발 생태계에 중요한 기여를 했습니다. `rdkafka`와 `karafka-rdkafka` 젬은 이제 네이티브 확장과 함께 제공되며, 다음 `bundle install`은 더 빨라질 것입니다.

댓글 0

댓글 작성

0/1000
정중하고 건설적인 댓글을 작성해 주세요.

아직 댓글이 없습니다

첫 번째 댓글을 작성해보세요!