한 개발자가 Playwright 또는 Puppeteer를 통해 Chrome DevTools 디버거를 연결하면 fetch 기반 업로드 속도가 20배 이상 저하되어, 일상적인 성능 벤치마크가 잘못된 데이터로 변질된다는 사실을 발견했습니다.
조사를 촉발한 수수께끼
서버로 데이터를 전송하기 전에 암호화하는 브라우저 기반 파일 저장소인 Coffer는 로컬 네트워크를 통해 정기적으로 기가비트급 업로드를 수행합니다. 팀이 업로드 속도를 측정했을 때 격차가 발견되었습니다. 다운로드는 대역폭을 가득 채웠지만, 업로드는 가용 대역폭의 약 8분의 1 수준으로 매우 느렸습니다. 이러한 불일치로 인해 세 차례의 코드 수정이 이루어졌으나 아무런 변화가 없었습니다. 그러다 네 번째 "수정"이 엄청난 속도 향상을 가져오는 듯 보였으나, 디버거를 제거하자마자 그 효과는 사라졌습니다.
팀이 처음 시도한 것들
엔지니어들은 흔히 의심되는 원인들을 조사했습니다:
- Chunk size – 블록 크기를 16 MiB에서 32 MiB로 두 배 늘렸으나 처리량은 변하지 않았습니다.
- Pipelining – 현재 업로드와 다음 블록의 암호화 작업을 중첩시켰으나, 측정 오차와 구별할 수 없는 13%의 미미한 이득만 얻었습니다.
- Concurrency – 여러 업로드를 병렬로 실행했으나 총 속도는 동일한 수준에서 제한되었으며, 이는 전역적인 한계가 있음을 시사했습니다.
이러한 변수 중 그 어떤 것도 8배의 속도 저하를 설명하지 못했습니다.
놀라운 일대일 비교
문제를 격리하기 위해 팀은 클라이언트 구현 방식을 교체했습니다. 동일한 네트워크에서 .NET HttpClient를 사용했을 때는 700 Mbps를 기록했지만, Chromium의 fetch() API를 통해 동일한 요청을 보냈을 때는 140 Mbps에서 멈췄습니다. 이러한 극명한 차이는 브라우저의 네트워크 스택을 원인으로 지목했으나, 다음 실험 결과는 달랐습니다.
디버거의 숨겨진 비용
Playwright와 Puppeteer는 Chrome DevTools Protocol(CDP)을 통해 Chrome을 제어합니다. 이 프로토콜은 브라우저 프로세스에 디버거를 연결하여 네트워크 이벤트, DOM 스냅샷, 콘솔 로그를 노출합니다. 팀은 Uint8Array 페이로드를 전송하는 fetch() 호출에 대해 CDP 디버거를 연결했을 때와 연결하지 않았을 때를 비교하는 집중 테스트를 수행했습니다.
- 디버거 연결됨: 113 Mbps
디버거가 존재할 경우 업로드 속도가 20배 이상 감소했습니다. 디버거를 연결하지 않은 일반 Edge 창에서의 수동 테스트에서는 600 Mbps 이상이 나와, 방해 요소가 없을 때 브라우저 자체가 트래픽을 충분히 처리할 수 있음을 확인했습니다.
작지만 실제적인 개선
디버거가 속도 저하의 대부분을 차지했지만, 팀은 여전히 실제적인 최적화 방법을 찾아냈습니다. 요청 본문(request body)을 Uint8Array에서 Blob으로 전환하자 Chromium의 속도가 약 30% 향상되었습니다. 이는 유용한 조정 방법이지만, 처음에 기대했던 "기적적인" 향상에는 훨씬 못 미치는 수준이었습니다.
엔지니어에게 이것이 중요한 이유
- 측정 도구는 거짓말을 할 수 있습니다. 브라우저를 자동화하는 성능 측정 도구 자체가 측정 체인의 일부이기 때문입니다.
- 불가능해 보이는 벤치마크 결과는 검증이 필요합니다. 수치가 네트워크 용량과 크게 차이 난다면, 측정 환경을 가장 먼저 의심해야 합니다.
- 결과가 없는 것도 가치 있는 결과입니다. 특정 변경 사항이 아무런 영향을 미치지 않는다는 것을 확인하면, 유령 버그를 쫓느라 시간을 낭비하는 것을 방지할 수 있습니다.
- 수동 제어는 저렴한 보험입니다. 일반 브라우저 창에서 동일한 작업을 실행해 보면 숨겨진 측정 오버헤드를 찾아낼 수 있습니다.
반론: 디버거가 필수적인 경우
디버거는 페이지 동작, 에러 추적, 네트워크 타임라인 등 다른 방법으로는 접근할 수 없는 가시성을 제공합니다. 회귀 테스트, 보안 감사 또는 복잡한 UI 상호작용의 경우 CDP 디버거를 연결하는 것이 필수적인 경우가 많습니다. 핵심은 기능 테스트와 순수 성능 측정을 분리하고, 성능 측정이 목적일 때는 디버거를 비활성화하는 것입니다.
시사점: 자동화 테스트를 가능하게 하는 도구가 성능 왜곡의 가장 큰 원인이 될 수도 있습니다. 브라우저, 네트워크 또는 코드를 탓하기 전에, 디버거가 데이터 스트림을 조용히 제한하고 있지는 않은지 확인하십시오.
