본문으로 건너뛰기

RSpec 대형 테스트 파일 병목 현상 해결을 위한 rspec-big-split 활용 가이드

Parallel Tests Without Waiting - Blog - Visuality

작성자
발행일
2025년 12월 15일
https://visuality.pl/posts/parallel_tests_without_waiting

핵심 요약

  • 1 RSpec의 대형 테스트 파일이 병렬 실행 시 특정 워커에 집중되어 전체 CI 빌드 시간을 지연시키는 병목 현상을 해결하기 위해 rspec-big-split 보석을 활용할 수 있습니다.
  • 2 이 도구는 대규모 테스트 파일을 여러 워커로 분산 실행할 수 있게 하며, 유료 서비스나 외부 의존성 없이도 효율적인 테스트 병렬화를 구현하는 비용 효율적인 대안을 제공합니다.
  • 3 메타데이터 설정과 드라이 런을 통한 테스트 맵 생성을 통해 CI 환경에서 각 노드별로 최적화된 테스트 범위를 동적으로 할당하여 전체 빌드 속도를 획기적으로 개선합니다.

도입

루비 온 레일즈 프로젝트의 규모가 커짐에 따라 CI(지속적 통합) 빌드 시간의 증가는 개발 생산성을 저해하는 주요 요인이 됩니다. 특히 여러 워커를 사용하는 병렬 테스트 환경에서도 특정 대형 RSpec 파일이 하나의 워커를 독점하면서 발생하는 '꼬리 지연(Tail Latency)' 문제는 흔한 병목 현상입니다. 본 글에서는 이러한 문제를 해결하기 위해 오픈 소스 도구인 rspec-big-split을 활용하여 대형 테스트 파일을 효율적으로 쪼개고 전체 빌드 시간을 단축하는 구체적인 방법론을 제시합니다.

1. 병렬 테스트 환경에서의 고질적인 병목 현상

루비 온 레일즈 환경에서 RSpec을 사용하여 테스트를 수행할 때, 프로젝트 규모가 커지면 테스트 실행 시간도 비례해서 늘어납니다. 이를 해결하기 위해 CI 환경에서 여러 개의 워커(Worker)를 띄워 병렬로 테스트를 실행하는 것이 일반적입니다. 하지만 일반적인 병렬 실행 방식에는 치명적인 약점이 있습니다. 바로 테스트 파일을 최소 단위로 인식하여 워커에 배분한다는 점입니다. 만약 30개의 워커 중 29개가 5분 만에 작업을 끝내더라도, 단 하나의 워커가 35분이 걸리는 거대한 테스트 파일을 할당받는다면 전체 CI 빌드 시간은 결국 40분 이상이 소요됩니다. 이러한 ‘꼬리 지연’ 문제는 개발 팀의 생산성을 크게 저해하며 빠른 배포를 방해하는 주범이 됩니다. 개발자들은 테스트 결과를 기다리느라 컨텍스트 스위칭 비용을 지불하게 되며, 이는 전체적인 개발 속도 저하로 이어집니다.

2. rspec-big-split의 등장 배경과 주요 특징

이러한 문제를 해결하기 위해 고안된 rspec-big-split은 거대한 RSpec 파일을 더 작은 단위로 쪼개어 여러 워커에 분산할 수 있게 해주는 오픈 소스 루비 젬입니다. Knapsack PRO와 같은 파워풀한 유료 도구가 훌륭한 대안이 될 수 있지만, 매달 발생하는 비용 문제나 외부 서비스에 코드를 의존해야 하는 부담, 그리고 데이터 보안 등을 고려해야 하는 기업 환경에서는 rspec-big-split이 매우 강력하고 유연한 커스텀 솔루션이 됩니다. 이 도구는 MIT 라이선스 하에 제공되어 자유롭게 수정 및 배포가 가능하며, 개발자가 어떤 파일을 ‘거대 파일’로 간주하고 쪼갤지 직접 결정할 수 있는 세밀한 제어권을 제공합니다. 또한 별도의 서드파티 서비스 연동 없이 로컬 환경과 CI 환경만으로 동작하므로 신뢰성이 매우 높습니다.

3. 단계별 도입 및 적용 가이드

#### 젬 설치 및 대상 지정 먼저 bundle add rspec-big-split 명령어를 통해 프로젝트에 젬을 추가합니다. 설치 후에는 병목의 원인이 되는 대형 테스트 파일의 RSpec.describe 블록에 ci_split_example_group: true라는 메타데이터를 추가합니다. 이 설정은 해당 그룹이 병렬 실행 시 쪼개질 수 있는 대상임을 명시하며, 작은 파일들은 그대로 유지하여 효율성을 보존합니다.

테스트 맵 생성 및 분석

실제 테스트를 돌리기 전, 프로젝트의 전체 테스트 구조를 파악하는 단계가 필요합니다. RSpec의 dry-run 모드와 제공되는 포매터를 사용하여 테스트 구성 정보를 JSON 파일로 추출합니다. bundle exec rspec –dry-run –format Rspec::Big::Split::Formatter –out tmp/rspec_splitter.json 명령어를 사용하면 됩니다. 이 과정은 실제 테스트를 실행하지 않으므로 매우 빠르게 완료됩니다.

CI 파이프라인 구성

CI 설정 파일에서 전체 노드 수(TEST_NODE_TOTAL)와 현재 노드의 인덱스(TEST_NODE_INDEX)를 환경 변수로 정의해야 합니다. rspec-big-split 명령어는 앞서 생성한 JSON 맵을 읽어 현재 노드가 실행해야 할 최적의 테스트 목록을 계산하여 반환합니다. 이를 RSpec 실행 명령어의 인자로 전달하면 각 워커는 자신에게 할당된 적절한 양의 테스트만 수행하게 됩니다.

4. 극대화된 최적화: 예제 단위 분할 및 기대 효과

기본적인 파일 단위 분할로도 충분하지 않은 경우, –split-by-example 옵션을 활용할 수 있습니다. 이 옵션을 사용하면 파일 내부의 개별 it 블록 단위로 테스트를 쪼개어 워커에 배분하므로, 워커 간의 부하 불균형을 거의 완벽하게 해소할 수 있습니다. 실제 적용 사례에 따르면, 최적화되지 않은 환경에서 450초가 소요되던 테스트가 단 15초로 단축되는 드라마틱한 성능 향상을 기록하기도 했습니다. 이는 개발자에게 즉각적인 피드백을 제공하여 전체적인 소프트웨어 품질 향상에 기여하며, 대규모 모놀리식 테스트 파일로 고통받는 팀에게 가장 현실적이고 비용 효율적인 해결책을 제시합니다.

결론

rspec-big-split을 도입하면 특정 대형 파일로 인해 정체되었던 CI 파이프라인의 흐름을 원활하게 바꿀 수 있습니다. 테스트 부하가 모든 워커에 균등하게 분산됨에 따라 전체 실행 시간은 평균치에 가까워지며, 이는 곧 빠른 피드백 루프로 이어집니다. 유료 솔루션 도입이 부담스럽거나 커스텀한 제어가 필요한 루비 개발 팀에게 이 오픈 소스 솔루션은 빌드 최적화를 위한 강력하고 실용적인 선택지가 될 것입니다. 효율적인 병렬화를 통해 개발 주기를 단축해 보시기 바랍니다.

댓글0

댓글 작성

댓글 삭제 시 비밀번호가 필요합니다.

이미 계정이 있으신가요? 로그인 후 댓글을 작성하세요.

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