지속적인 벤치마킹이란 무엇입니까?
지속적인 벤치마킹(Continuous Benchmarking)은 팀 구성원이 자신의 작업을 자주 벤치마킹하는 소프트웨어 개발 방식으로, 보통 각 개인이 최소한 매일 한 번 이상 벤치마킹을 수행하여 하루에 여러 번의 벤치마크가 이루어집니다. 각 벤치마크는 자동화된 빌드에 의해 검증되어 성능 회귀를 가능한 한 빨리 감지합니다. 많은 팀들이 이러한 접근 방식을 통해 성능 회귀를 크게 줄이고 팀이 더 빠르게 성능이 우수한 소프트웨어를 개발할 수 있음을 확인했습니다.
이제 소프트웨어 업계의 모든 사람들은 지속적인 통합(Continuous Integration, CI)에 대해 알고 있습니다. 기본적으로 CI는 소프트웨어 기능 회귀가 프로덕션에 도달하기 전에 이를 감지하고 방지하는 것입니다. 마찬가지로, 지속적인 벤치마킹(Continuous Benchmarking, CB)은 소프트웨어의 성능 회귀가 프로덕션에 도달하기 전에 이를 감지하고 방지하는 것입니다. 코드 변경마다 CI에서 단위 테스트를 실행하는 것과 같은 이유로, 코드 변경마다 CB에서 성능 테스트를 실행해야 합니다. 실제로 이 비유는 매우 적절해서, 이 섹션의 첫 번째 문단은 Martin Fowler가 2006년에 쓴 지속적인 통합 소개글의 Mad Libs 버전에 불과합니다.
🐰 성능 버그도 버그입니다!
CI에서의 벤치마킹
속설: CI에서는 벤치마크를 실행할 수 없다
대부분의 벤치마크 하네스는 지연 시간이나 처리량을 측정하기 위해 시스템 벽시계 시간을 사용합니다. 이것은 개발자인 우리가 가장 중요하게 여기는 지표이기 때문에 매우 유용합니다. 그러나 범용 CI 환경은 벽시계 시간을 측정할 때 종종 시끄럽고 일관성이 없습니다. 지속적인 벤치마킹을 수행할 때 이러한 변동성은 결과에 원치 않는 노이즈를 추가합니다.
이 문제를 처리하는 몇 가지 방법이 있습니다:
- 베어메탈 러너
- 상대적 지속적 벤치마킹
- 벽시계 시간 대신 명령어 수를 카운트하는 벤치마크 하네스로 전환
단연코 거의 모든 경우에 베어메탈 러너가 최선의 선택입니다. Bencher는 2% 미만의 변동성을 가진 베어메탈 러너를 제공합니다. 이를 GitHub Action 러너와 비교해 보면, 실행 간 30% 이상의 변동성이 발생할 수 있습니다. 지속적인 벤치마킹 환경에서 변동성, 즉 노이즈를 줄이면 훨씬 더 미세한 성능 회귀를 감지할 수 있게 됩니다.
성능의 중요성
속설: 100ms의 지연 시간은 느낄 수 없다
사람들이 100ms의 지연 시간을 인지할 수 없다고 주장하는 것은 흔한 일입니다. 이러한 주장의 근거로 Nielsen Group의 응답 시간에 관한 기사가 자주 인용됩니다.
0.1초는 사용자가 시스템이 즉각적으로 반응하고 있다고 느끼게 하는 한계이며, 이는 결과를 표시하는 것 외에는 특별한 피드백이 필요하지 않음을 의미합니다.
- Jakob Nielsen, 1 Jan 1993
그러나 이것은 사실이 아닙니다.
어떤 작업에서는 사람들이 단 2ms의 지연 시간도 인지할 수 있습니다.
이를 쉽게 증명하는 방법은 Dan Luu의 실험입니다. 터미널을 열고 sleep 0; echo "ping"을 실행한 다음 sleep 0.1; echo "pong"을 실행해 보세요. 차이점을 알아차리셨죠‽
또 다른 흔한 혼동은 지연 시간의 인지와 인간의 반응 시간 사이의 구분입니다. 시각 자극에 반응하는 데 약 200ms가 걸리지만, 이것은 사건 자체의 인지와는 별개입니다. 비유하자면, 기차 여행이 두 시간 걸리더라도(반응 시간) 기차가 2분 늦었다는 것(인지된 지연 시간)을 알아차릴 수 있는 것과 같습니다.
성능이 중요합니다! 성능은 기능입니다!
- 100ms 더 빠를 때마다 → 전환율 1% 증가 (Mobify, 연간 +$380,000 수익)
- 50% 더 빠름 → 매출 12% 증가 (AutoAnything)
- 20% 더 빠름 → 전환율 10% 증가 (Furniture Village)
- 40% 더 빠름 → 가입자 15% 증가 (Pinterest)
- 850ms 더 빠름 → 전환율 7% 증가 (COOK)
- 1초 더 느릴 때마다 → 사용자 10% 감소 (BBC)
무어의 법칙이 종말을 맞으면서, 병렬로 실행 가능한 워크로드는 병렬화되어야 할 것입니다. 그러나 대부분의 워크로드는 직렬로 실행되어야 하며, 문제에 단순히 더 많은 연산 자원을 투입하는 것은 빠르게 해결하기 어렵고 비용이 많이 드는 해결책이 되고 있습니다.
지속적인 벤치마킹은 이러한 변화 속에서 성능이 뛰어난 현대 소프트웨어를 개발하고 유지하는 데 핵심적인 구성 요소입니다.

지속적인 벤치마킹 도구
Bencher를 만들기 전에, 우리는 다음을 충족하는 도구를 찾기 위해 나섰습니다:
- 로컬과 CI 모두에서 완전히 동일한 베어메탈 하드웨어에서 벤치마크 실행
- 여러 언어에 걸쳐 벤치마크 추적
- 언어 표준 벤치마크 하네스 출력의 원활한 수집
- 사용자 정의 벤치마크 하네스 출력에 대한 확장성
- 오픈 소스이며 자체 호스팅 가능
- 여러 CI 호스트와 호환
- 사용자 인증 및 권한 부여
안타깝게도 이 모든 기준을 만족하는 도구는 존재하지 않았습니다. 우리가 영감을 받은 기존 벤치마킹 도구의 종합적인 목록은 선행 기술에서 확인할 수 있습니다.
CI 외부에서의 지속적인 벤치마킹
CI는 최종 점검 단계로 의도된 것이며, 테스트가 수행되는 유일한 장소가 아닙니다. Bencher는 로컬과 CI 모두에서 완전히 동일한 베어메탈 하드웨어에서 벤치마크를 실행할 수 있게 해주는 최초의 지속적인 벤치마킹 도구입니다. 이를 통해 개발자와 에이전트는 진행 중인 로컬 작업을 프로젝트의 성능 이력 중 어느 시점과도 비교할 수 있습니다.
로컬 하드웨어에서 실행할 때, Bencher 베어메탈을 사용하면 멀티태스킹을 계속 유지할 수 있습니다. 시스템의 다른 모든 작업을 중단하고, 이전 브랜치를 가져와서 비교를 실행할 필요가 없습니다.
클라우드 환경에서 실행할 때, Bencher 베어메탈을 사용하면 결과를 신뢰할 수 있습니다. 시끄러운 이웃, 스로틀링, 또는 중간에 호스트가 교체되는 것에 대해 걱정할 필요가 없습니다.
빅테크에서의 지속적인 벤치마킹
Bencher와 같은 도구들은 Microsoft, Facebook(현재의 Meta), Apple, Amazon, Netflix, Google을 비롯한 수많은 기업들에서 내부적으로 개발되어 왔습니다. 업계의 거물들로서 그들은 개발 중에 성능을 모니터링하는 것의 중요성과 지속적인 벤치마킹을 통해 이러한 통찰을 개발 프로세스에 통합하는 것의 중요성을 이해하고 있습니다. 우리는 지속적인 벤치마킹을 빅테크의 벽 너머에서 오픈 소스 커뮤니티로 가져오기 위해 Bencher를 만들었습니다. 빅테크의 지속적인 벤치마킹 관련 게시물 링크는 선행 기술에서 확인하세요.
Bencher: 지속적인 벤치마킹
Bencher는 지속적인 벤치마킹 도구 모음입니다. 성능 회귀가 사용자에게 영향을 미친 경험이 있나요? Bencher가 그런 일이 일어나는 것을 막을 수 있었습니다. Bencher를 이용하면 성능 회귀를 병합되기 전에 탐지하고 예방할 수 있습니다.
- 실행: 완전히 동일한 베어 메탈 러너와 즐겨 사용하는 벤치마킹 도구를 사용하여 로컬 또는 CI에서 벤치마크를 실행합니다.
bencherCLI는 베어 메탈에서 벤치마크 실행을 조율하고 결과를 저장합니다. - 추적: 벤치마크 결과를 시간이 지남에 따라 추적합니다. 소스 브랜치, 테스트 베드, 측정 기반의 Bencher 웹 콘솔을 사용하여 결과를 모니터링, 쿼리, 그래프로 만듭니다.
- 캐치: 완전히 동일한 베어 메탈 하드웨어를 사용하여 로컬 또는 CI에서 성능 회귀를 잡아냅니다. Bencher는 최첨단, 사용자 정의 가능한 분석을 사용하여 병합되기 전에 성능 회귀를 탐지합니다.
단위 테스트가 기능 회귀를 방지하기 위해 실행되는 것처럼, 벤치마크는 Bencher와 함께 실행되어 성능 회귀를 방지해야 합니다. 성능 버그도 버그입니다!
성능 회귀를 잡아내기 시작하세요 - Bencher Cloud를 무료로 시도해보세요.
지속적인 벤치마킹 vs 로컬 벤치마크 비교
로컬에서 결과를 비교할 수 있는 여러 벤치마크 하네스가 있습니다. 로컬 비교는 성능을 튜닝할 때 빠르게 반복하기에 훌륭합니다. 그러나 지속적으로 성능 회귀를 감지하기 위해 이것에만 의존해서는 안 됩니다. 로컬에서 단위 테스트를 실행할 수 있다고 해서 CI의 필요성이 사라지지 않는 것처럼, 로컬에서 벤치마크를 실행하고 비교할 수 있다고 해서 지속적인 벤치마킹의 필요성이 사라지는 것은 아닙니다.
Bencher가 제공하지만 로컬 벤치마크 비교 도구는 제공하지 못하는 여러 기능이 있습니다:
- 서로 다른 테스트베드 간에 동일한 벤치마크 비교
- 언어와 하네스에 걸친 벤치마크 비교
- 벤치마크 결과의 협업과 공유
- 노이즈를 최소화하기 위한 전용 테스트베드에서 벤치마크 실행
- 더 이상 복사-붙여넣기가 필요 없음
지속적인 벤치마킹 vs 애플리케이션 성능 관리 (APM)
애플리케이션 성능 관리(APM)는 현대 소프트웨어 서비스에 필수적인 도구입니다. 그러나 APM은 프로덕션 환경에서 사용되도록 설계되었습니다. 성능 회귀가 감지될 시점에는 이미 고객에게 영향을 미치고 있습니다.
대부분의 결함은 결국 그것을 예방하는 데 드는 비용보다 더 많은 비용을 치르게 합니다. 결함이 발생하면 비용이 많이 드는데, 결함을 수정하는 직접 비용뿐 아니라 손상된 관계, 잃어버린 비즈니스, 그리고 낭비된 개발 시간으로 인한 간접 비용 때문입니다.
— Kent Beck, Extreme Programming Explained
Bencher가 제공하지만 APM 도구는 제공하지 못하는 여러 기능이 있습니다:
- 성능 회귀를 병합되기 전에 포착
- 코드 리뷰에 성능 변화와 영향 포함
- 프로덕션 환경에서의 오버헤드 없음
- 온-프레미스 배포에 효과적
- 프로덕션 소스 코드의 변경 불필요
지속적인 벤치마킹 vs 관측 가능성
다른 이름으로 불려도 장미의 향기는 여전히 달콤할 것입니다. 위의 지속적인 벤치마킹 vs 애플리케이션 성능 관리를 참조하세요.
지속적인 벤치마킹 vs 지속적인 통합 (CI)
지속적인 벤치마킹(CB)은 지속적인 통합(CI)과 상호 보완적입니다. 코드 변경마다 CI에서 단위 테스트를 실행하는 것과 같은 이유로, 코드 변경마다 CB에서 성능 테스트를 실행해야 합니다.
단위 테스트와 인수 테스트는 표준 개발 관행으로 널리 받아들여지고 있지만, 이러한 추세는 성능 테스팅 영역으로는 이어지지 않았습니다. 현재 일반적인 도구들은 테스터로 하여금 일회성 코드와 클릭 앤 스크립트 사고방식으로 유도하고 있습니다. 성능 테스팅을 일급 시민으로 대우하면 더 많은 기능을 포괄하는 더 나은 테스트를 작성할 수 있게 되고, 이는 성능 테스트를 만들고 실행하는 더 나은 도구로 이어지며, 결과적으로 유지보수가 가능하고 그 자체로도 테스트할 수 있는 테스트 스위트로 이어집니다.
지속적인 벤치마킹 vs 지속적인 부하 테스팅
지속적인 벤치마킹과 지속적인 부하 테스팅의 차이를 이해하려면, 벤치마킹과 부하 테스팅의 차이를 이해해야 합니다.
| 테스트 종류 | 테스트 범위 | 테스트 사용자 |
|---|---|---|
| 벤치마킹 | 함수 - 서비스 | 한 명 - 여러 명 |
| 부하 테스팅 | 서비스 | 여러 명 |
벤치마킹은 함수 수준(마이크로 벤치마크)부터 서비스 수준(매크로 벤치마크)까지 소프트웨어의 성능을 테스트할 수 있습니다. 벤치마크는 코드의 특정 부분의 성능을 격리된 방식으로 테스트하는 데 적합합니다. 부하 테스팅은 서비스 수준에서만 소프트웨어의 성능을 테스트하며 여러 동시 사용자를 모의합니다. 부하 테스트는 특정 부하 하에서 전체 서비스의 성능을 테스트하는 데 적합합니다.
🍦 아이스크림 트럭의 성능을 추적하고 싶다고 상상해 보세요. 벤치마킹은 아이스크림 콘을 한 스쿱 떠내는 데 걸리는 시간을 측정하는 데 사용할 수 있고(마이크로 벤치마크), 또한 한 명의 고객이 주문하고, 아이스크림을 받고, 결제하는 데 걸리는 시간을 측정하는 데도 사용할 수 있습니다(매크로 벤치마크). 부하 테스팅은 더운 여름날 아이스크림 트럭이 100명의 고객에게 얼마나 잘 서비스하는지 확인하는 데 사용할 수 있습니다.