Stripe는 결제 서비스를 넘어 다양한 금융 상품을 제공하며, 이 모든 서비스의 대부분은 Ruby로 구축되어 있습니다. 회사는 규모가 커지더라도 Ruby를 포기하지 않고 확장하기 위해 Ruby 인프라 팀을 운영하며 코드베이스의 확장성, 청결성, 버전 업그레이드 및 Gem 관리를 전담하고 있습니다.
대규모 코드베이스 디버깅 및 타입 체커 활용
개발자의 하루 시나리오를 통해 Stripe의 개발 프로세스가 설명됩니다. 루마니아 통화 추가 후 발생한 결제 금액 표시 오류를 디버깅하는 과정에서 다음 도구와 전략이 활용됩니다.
* 내부 코드 검색 도구: 2,500만 라인 이상의 Ruby 코드에서 특정 문자열을 0.5초 만에 검색합니다.
* Sorbet (타입 체커): VS Code의 LSP 모드에서 실행되어 ‘정의로 이동’과 같은 기능을 제공하며, 코드의 정확성을 검증합니다. 특히 enum
기능을 활용한 완전성(exhaustiveness) 검사를 통해 새로운 통화 추가 시 누락된 처리 로직을 자동으로 감지하여 프로덕션 배포 전 문제를 방지합니다.
* 타입 체커의 이점: 생산성 향상, 개발자의 정신적 부담 감소, 프로덕션 버그 방지(5~10초 만에 오류 발견), 코드베이스를 더 작게 느끼게 함, 신규 입사자 온보딩 지원.
* Sorbet 권장 사항: 소규모 프로젝트는 typed: true
모드로 시작하여 점진적으로 타입을 추가하는 것을 권장합니다.
CI/CD 및 모노레포 전략
Stripe의 CI/CD 파이프라인은 다음과 같은 특징을 가집니다.
* 일관성 검사: Rust로 작성된 고속 Ruby 포맷터와 RuboCop을 사용하여 코드 일관성을 유지합니다.
* 모노레포의 이점: 모든 코드를 단일 저장소에 두어 생산성을 극대화합니다. 이는 규모에 따른 문제를 전담 팀이 해결하고, 서비스 간의 원자적 변경을 용이하게 합니다. Ruby 코드의 99.9%가 단일 코드베이스에 있습니다.
* 스마트 테스트 선택: 150만 개의 테스트를 매번 실행하는 비효율성을 해결하기 위해 변경된 파일에 영향을 받는 테스트만 선별적으로 실행합니다. Linux의 open
syscall을 가로채 테스트 실행 중 접근한 파일을 추적하고, 이를 역추적하여 변경된 코드와 관련된 테스트만 실행합니다. 이를 통해 기능 브랜치에서 테스트 실행 시간을 99.5% 단축합니다 (150만 개 → 1,000~2,000개).
* 탄력적인 CI 워커: Amazon Spot 인스턴스를 활용한 탄력적인 워커 풀을 통해 개발자 부하에 따라 CI 자원을 동적으로 조절합니다.
배포 자동화 및 안정성
Stripe는 높은 배포 빈도와 안정성을 위해 다음과 같은 시스템을 구축했습니다. * 통합 브랜치: 병합 전 최신 메인 브랜치 위에 변경 사항을 쌓아 CI를 재실행하여 병합 충돌 및 잠재적 오류를 방지합니다. 이로써 경쟁 상태(race window)를 2주에서 5분으로 단축합니다. * 자동 병합: CI 통과 및 동료 승인 시 PR이 자동으로 병합 및 배포되는 기능을 제공하여 개발자의 편의성을 높입니다. * 컨테이너 최적화: Kubernetes 기반으로 전환하며 서비스별 컨테이너를 구축하고, 도달 불가능한 코드를 제거하여 압축 이미지 크기를 수백 MB 절감하여 빌드 및 배포 속도를 향상시킵니다. * QA 환경: 고위험 변경 사항이나 로컬 테스트가 어려운 경우를 위해 QA 환경을 제공합니다. 과거 공유 환경에서 개별 개발자 전용 QA 환경으로 전환하여 병목 현상을 해소합니다. * 프로덕션 배포: 결제 서비스는 하루 20~25회 배포되며, 대부분의 시간은 트래픽 전환에 사용됩니다. 자동화된 헬스 체크를 통해 이상 감지 시 즉시 트래픽을 이전 버전으로 되돌리는 블루/그린 배포 및 점진적 트래픽 전환 전략을 사용합니다. * 다층 방어 체계: 타입 검사, CI, 사전 프로덕션 테스트, 트래픽 전환 등 여러 단계의 방어 체계를 통해 개발자의 두려움을 줄이고 5-9 수준의 가용성을 목표로 합니다.
프로덕션 환경 최적화
- 상수 사전 로딩: 서비스 시작 시 모든 참조 가능한 Ruby 상수를 미리 로드하여 첫 요청의 지연 시간을 없앱니다.
- Copy-on-Write (CoW): 워커 포크 시 Linux의 CoW 페이지 공유 기능을 활용하여 메모리 사용량을 최적화합니다.
- Ruby 3.3 및 YJIT: 최근 Ruby 3.3으로 업그레이드했으며, Shopify의 YJIT 덕분에 CPU 사용량이 약 25% 감소하는 효과를 보았습니다.
- 커뮤니티 참여: Ruby 버그를 조기에 발견하고 수정하기 위해 커뮤니티에 적극적으로 참여하고 있습니다.