본문으로 건너뛰기

레일즈 테스트 실행 시간을 40분에서 4분으로 단축하기: 병렬화의 힘

작성자
Rails Upgrade News
발행일
2026년 03월 05일
https://www.fastruby.io/blog/speed-up-tests-from-40-to-4-minutes.html

핵심 요약

  • 1 레일즈 6 이상에서 제공하는 내장 병렬화(Parallelization) 기능을 활용하여 1만 개 이상의 테스트 실행 시간을 40분에서 4분으로 90% 단축했습니다.
  • 2 테스트 병렬화 도입 전 무작위 실행 순서 보장과 레이스 컨디션 해결을 위해 임시 파일 관리 및 하드코딩된 디렉토리 구조를 개선하는 과정이 필수적입니다.
  • 3 테스트 환경 개선은 개발자의 피드백 루프를 가속화할 뿐만 아니라 CI 인프라의 CPU 자원 활용도를 극대화하여 운영 비용을 절감하는 효과를 가져옵니다.

도입

본 아티클은 레일즈 2.3 및 루비 2.5 환경의 레거시 애플리케이션을 최신 버전으로 업그레이드하고, 40분에 달하던 테스트 실행 시간을 4분으로 단축시킨 실제 사례를 다룹니다. 긴 테스트 시간은 개발자의 코드 병합을 방해하고 전체적인 피드백 루프를 지연시키는 핵심적인 병목 현상이었습니다. 기술 부채 해결을 위해 루비 3.4.7과 레일즈 8.1.1로의 전환을 마친 후, 테스트 병렬화를 통해 성능을 극대화한 전략과 그 과정에서 마주한 기술적 도전 과제들을 상세히 소개합니다.

1. 테스트 실행 도구의 변화와 부팅 속도 개선

애플리케이션은 기존에 Test::Unit을 사용하고 있었으나, 레일즈의 기본 프레임워크이자 가장 빠른 속도를 자랑하는 Minitest로 전환했습니다. 루비와 레일즈의 최신 버전 업그레이드와 맞물려, 테스트 부팅 시간이 기존 30초에서 단 몇 초 수준으로 줄어들었습니다. 이는 개별 테스트 파일을 실행하거나 특정 메서드만 테스트할 때의 피드백 루프를 획기적으로 개선하여 로컬 개발 환경의 생산성을 높였습니다.

2. 데이터 생성 전략: Fixtures와 Factories의 조화

테스트 데이터 생성 방식은 성능에 큰 영향을 미칩니다. factory_bot과 같은 팩토리는 동적 데이터 생성에는 유리하지만, 매번 데이터베이스 쓰기 작업을 수행하여 테스트를 느리게 만듭니다. 반면 Fixtures는 테스트 시작 시 한 번만 로드되어 재사용되므로 DB 쓰기 횟수를 줄여줍니다. 본 사례에서는 두 방식을 혼합하여, 자주 사용되는 공통 데이터는 Fixtures로 관리하고 특수한 상황의 동적 데이터는 Factories로 관리하여 효율성을 극대화했습니다.

3. 프로파일링을 통한 슬로우 테스트 제거

전체 테스트 세트의 속도를 높이기 위해서는 실제 병목 지점을 찾는 작업이 선행되어야 합니다. Minitest와 RSpec에서 제공하는 --profile 플래그를 사용하여 가장 느린 상위 10개 테스트를 식별했습니다. 이를 통해 과거 스레드 관련 레이스 컨디션을 피하기 위해 임시로 삽입되었던 불필요한 sleep(1) 호출 등을 찾아내어 제거함으로써 실질적인 실행 시간을 단축했습니다.

4. 레일즈 병렬화(Parallelization)의 실제 적용과 도전 과제

레일즈 6부터 도입된 병렬화 기능은 test_helper.rbparallelize(workers: :number_of_processors)를 추가하는 것만으로 활성화할 수 있습니다. 하지만 안정적인 적용을 위해 다음의 문제를 해결해야 했습니다.

  • 무작위 실행 순서(Randomized Order): 테스트 간의 의존성을 제거하기 위해 어떤 순서로 실행되어도 성공하도록 보장해야 합니다. I18n.locale 변경 후 복구하지 않는 등의 상태 누수 문제를 --seed 플래그로 추적하여 수정했습니다.
  • 레이스 컨디션(Race Conditions): 여러 프로세스가 동시에 실행되면서 발생하는 충돌을 해결해야 합니다. 특히 이 앱은 임시 파일(tmp/export)을 생성하고 삭제하는 작업이 많아 충돌이 잦았습니다. 하드코딩된 디렉토리 대신 프로세스별 고유 경로를 사용하고, 전체 폴더 삭제 대신 명확한 파일 단위 정리를 수행하도록 개선했습니다.

5. 병렬화의 이점과 대안 도구

병렬화 도입 결과, 1만 개 이상의 테스트가 4분 만에 완료되었습니다. 이는 CI 서버의 14~16개 프로세서 코어를 모두 활용하게 됨으로써 유휴 자원을 줄이고 CI 인프라 비용을 절감하는 성과를 거두었습니다. 만약 Minitest를 사용하지 않는 환경이라면 flatware, turbo_tests, parallel_tests, 혹은 CI 인프라와 통합되는 knapsack_pro와 같은 도구를 통해 유사한 병렬화 효과를 얻을 수 있습니다.

결론

테스트 병렬화는 단순한 시간 단축을 넘어 개발자 경험과 비즈니스 비용 측면에서 막대한 이점을 제공합니다. 40분 걸리던 병합 대기 시간이 5분 이내로 줄어들면서 팀의 생산성이 비약적으로 향상되었으며, 유휴 자원이 많았던 CI 서버의 CPU를 풀가동함으로써 인프라 유지 비용도 절감할 수 있었습니다. Minitest뿐만 아니라 RSpec이나 Cucumber 사용자들도 다양한 외부 라이브러리를 통해 유사한 효과를 얻을 수 있으므로, 테스트 속도 개선은 모든 레일즈 프로젝트에서 우선적으로 고려해야 할 과제입니다.

댓글0

댓글 작성

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

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

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