Shopify의 MySQL2에서 Trilogy로의 마이그레이션 및 Rails 7.1에 Trilogy 어댑터 통합 사례 발표

Adrianna Chang - Migrating Shopify’s Core Rails Monolith to Trilogy - Rails World 2023 - YouTube

3줄 요약

  • Shopify는 MySQL2의 설치 및 버전 불일치 문제 해결을 위해 Trilogy로 데이터베이스 클라이언트를 전환했습니다.
  • Trilogy 마이그레이션을 통해 개발자 경험 개선, 쿼리 성능 향상(최대 22% 단축) 및 유지보수성 강화 효과를 얻었습니다.
  • Shopify의 성공적인 프로덕션 도입 후, Trilogy는 Rails 7.1에 공식 어댑터로 통합되어 Ruby on Rails 커뮤니티의 표준으로 자리 잡았습니다.

본 강연은 Shopify가 대규모 Ruby on Rails 코드베이스에서 MySQL2 데이터베이스 클라이언트를 Trilogy로 마이그레이션한 여정과, 이 과정에서 Trilogy 지원을 Rails 7.1 릴리스에 통합하기 위해 기여한 내용을 상세히 설명합니다. 발표자는 Trilogy의 핵심 특징과 전환 동기를 설명하고, 실제 마이그레이션 과정에서 직면했던 기술적 도전과 해결책, 그리고 프로덕션 배포를 통한 성능 개선 결과를 공유합니다. 궁극적으로 Trilogy를 Rails 커뮤니티의 표준으로 만드는 데 기여한 배경을 제시하며, 다른 개발자들에게도 Trilogy 도입을 권장합니다.

Trilogy는 GitHub가 2022년 오픈 소스화한 C 기반의 MySQL 데이터베이스 클라이언트로, Ruby 바인딩을 제공합니다. 기존 MySQL2가 libmysqlclient에 의존하는 것과 달리, Trilogy는 자체적인 MySQL 네트워크 프로토콜 구현을 통해 최소한의 의존성, 간편한 설치, 클라이언트-서버 버전 불일치 문제 해소, 메모리 사용량 개선, 그리고 Ruby VM 환경에서의 효율적인 성능을 제공합니다. Shopify는 MySQL2의 컴파일 문제로 인한 개발자 경험 저하, 쿼리 성능 개선의 필요성, 그리고 Trilogy의 강력한 유지보수성에 주목하여 전환을 결정했습니다. 특히, Trilogy를 Rails의 공식 어댑터로 통합하여 커뮤니티 표준으로 만들겠다는 장기적인 목표를 설정했습니다.

마이그레이션 과정에서는 trilogy 젬 설치 및 database.yml 설정 변경 외에, 클라이언트 API 직접 호출 부분에서의 변경 사항(예: each_as_hash 대신 each_hash 사용, query_options 대신 connection_options 사용)과 에러 클래스 차이(예: Mysql2::Error 대신 Trilogy::Error, ActiveRecord::ConnectionNotEstablished 대신 ActiveRecord::ConnectionFailed 처리)를 해결해야 했습니다. 기능적 동등성을 확보하기 위해 Active Record의 벌크 픽스처 삽입을 위한 멀티 스테이트먼트 지원을 Trilogy에 구축하고, SQL 경고 보고 기능을 Rails 코어에 업스트림하여 기존 커스텀 어댑터의 의존성을 제거했습니다. Semian, OpenTelemetry와 같은 외부 툴링과의 호환성도 확보했습니다.

프로덕션 배포는 점진적인 방식으로 진행되었습니다. 초기에는 1%의 트래픽에만 Trilogy를 적용하여 MySQL2와 Trilogy를 동시에 지원하는 코드를 운영했습니다. CI/CD는 MySQL2 기반을 유지하되, Trilogy 브랜치에 대한 수동 테스트를 병행하며 안정성을 확인했습니다. 이후 단일 클러스터에 100% Trilogy를 적용하여 성능을 비교한 결과, 평균 요청 시간이 약 22% 단축되고 MySQL 쿼리 시간이 약 17% 단축되는 등 인상적인 성능 향상을 확인했습니다. 이러한 성공적인 검증 후, Shopify는 전체 프로덕션 환경에 Trilogy를 배포하고 테스트 스위트도 Trilogy 기반으로 전환했습니다.

Trilogy 어댑터의 Rails 7.1 통합은 Shopify와 GitHub의 협력으로 이루어졌습니다. 이는 어댑터 코드의 공유된 소유권, Rails 자체 테스트 스위트를 활용한 향상된 테스트 커버리지, 그리고 Rails 추상 MySQL 어댑터 클래스 변경으로 인한 호환성 위험 감소를 목표로 했습니다. 기존 독립형 젬의 코드를 Rails로 이식하며, 추상 MySQL 어댑터 테스트를 Trilogy에 맞춰 일반화하고, explain 메소드와 같은 누락된 기능을 추가했습니다. 또한, Rails 데이터베이스 제너레이터에 Trilogy 옵션을 추가하고, CI/CD에 Trilogy 테스트 빌드를 통합했습니다. 마지막으로 중복 테스트 제거, 공유 데이터베이스 문 코드 추출, 커스텀 Trilogy 에러 클래스를 일반 Active Record 에러로 통일하는 등의 클린업 작업을 수행했습니다.

Shopify의 MySQL2에서 Trilogy로의 성공적인 마이그레이션은 개발 효율성 증대와 애플리케이션 성능 향상이라는 실질적인 이점을 가져왔습니다. 이 경험과 기술적 기여는 Trilogy 어댑터가 Rails 7.1에 공식적으로 포함되는 결정적인 역할을 했으며, Trilogy가 Ruby on Rails 생태계의 신뢰할 수 있는 데이터베이스 클라이언트로 자리매김하는 기반을 마련했습니다. 이는 대규모 Rails 애플리케이션에서 새로운 기술을 도입하고 오픈 소스 커뮤니티에 기여하는 훌륭한 사례입니다.