릴리스 트레인은 멈추지 않았다.
크롬 113은 개발자 채널을 무사히 통과하고, 드디어 베타(Beta) 채널이라는 세 번째 역에 진입했다. 이것은 이전과는 차원이 다른 무대였다. 사용자의 규모가 수십만에서 수백만, 수천만 단위로 기하급수적으로 늘어났다. 이제 WebGPU는 전문가의 영역을 넘어, 전 세계의 평범한 사용자들 앞에서 그 성능과 안정성을 증명해야 했다.
Dawn 팀의 모든 눈은 원격 측정(Telemetry) 대시보드에 고정되었다. 크래시 비율, 평균 프레임 속도, GPU 메모리 사용량. 모든 주요 지표가 녹색의 안정권에 머물러 있었다. 며칠이 지나도 심각한 문제는 보고되지 않았다. 연구실에는 조심스러운 낙관론이 퍼지기 시작했다.
“이대로만 가면… 정말 문제없이 출시할 수 있겠어.”
벤이 안도의 한숨을 내쉬었다.
그의 말이 끝나기 무섭게, 대시보드의 사용자 피드백 패널에 새로운 이슈가 등록되었다. 제목은 평범했다. [Beta] Minor visual glitches on some sites.
사소한 시각적 결함.
팀은 처음에는 대수롭지 않게 여겼다. 베타 채널에서는 흔히 있는 일이었다. 특정 드라이버와의 사소한 호환성 문제일 가능성이 높았다.
하지만 다음 날, 비슷한 내용의 피드백이 몇 개 더 올라왔다.
“WebGPU 기반의 포토 에디터를 사용하는데, 가끔씩 화면이 미세하게 깜빡입니다.”
“3D 차트 라이브러리에서 애니메이션이 부드럽지 않고 순간적으로 멈칫거리는 느낌이 있습니다.”
공통점은 두 가지였다. 첫째, 문제는 항상 간헐적으로, 예측 불가능하게 발생했다. 둘째, 문제를 보고한 사용자들은 대부분 구형 노트북에 탑재된 인텔 내장 그래픽 카드를 사용하고 있었다.
“특정 하드웨어에서만 발생하는 마이너 버그군. 일단 우선순위를 P2로 두고 추적합시다.”
카이가 결론 내렸다.
하지만 드미트리의 마음속에는 불길한 예감이 싹트고 있었다. 이런 종류의 ‘유령 같은’ 버그가 가장 잡기 어렵다는 것을 그의 경험이 말해주고 있었다.
그는 즉시 버그를 보고한 사용자와 동일한 사양의 구형 노트북을 구해왔다. 그리고 문제의 웹사이트들을 열어 몇 시간을 테스트했다. 하지만 그의 노트북에서는 어떤 결함도 재현되지 않았다. 화면은 완벽하게 부드러웠다.
“미치겠군. 내 컴퓨터에선 왜 아무렇지도 않은 거지?”
벤이 머리를 쥐어뜯었다.
팀은 온갖 가설을 세웠다. 특정 버전의 윈도우 업데이트 문제일까? 백그라운드에서 실행되는 다른 프로그램과의 충돌일까? 그들은 사용자에게 더 상세한 정보를 요청했지만, 돌아오는 대답은 한결같았다. “그냥 가끔씩 그래요.”
며칠이 더 흘렀다. 베타 채널의 사용자 수가 정점을 찍으면서, 피드백의 양은 수십 건으로 늘어났다. 더 이상 무시할 수 없는 수준이었다. 안정 버전 출시를 앞두고, 이런 미해결 이슈를 남겨둘 수는 없었다.
그날 밤, 드미트리는 홀로 연구실에 남아 원격 측정 데이터를 파고 있었다. 그는 버그가 발생한 시점의 시스템 로그를 샅샅이 뒤졌다. 그러다 아주 미세한 패턴 하나를 발견했다.
버그가 발생하는 순간에는, 공통적으로 시스템의 CPU 사용량이 순간적으로 급증하는 경향이 있었다. 백그라운드에서 바이러스 검사가 실행되거나, 다른 탭에서 무거운 자바스크립트가 동작하는 등의 상황이었다.
“혹시…?”
드미트리의 머릿속에 섬광이 스쳤다.
다음 날 아침, 그는 팀원들을 모아놓고 새로운 실험을 제안했다.
“버그를 재현하려 하지 말고, 버그가 발생할 ‘환경’을 만들어봅시다.”
그는 구형 노트북에서 문제의 WebGPU 페이지를 띄워놓고, 동시에 백그라운드에서 4K 동영상을 인코딩하는 CPU 부하 테스트 프로그램을 실행시켰다. 시스템 전체가 느려지고 팬이 미친 듯이 돌기 시작했다.
그리고 바로 그 순간, 유령이 모습을 드러냈다.
화면의 3D 차트가 분명하게 멈칫거리며 깜빡였다.
“잡았다!”
연구실에서 환호성이 터져 나왔다.
원인은 ‘경합 상태(Race Condition)’였다.
시스템에 부하가 걸리면, 운영체제의 스케줄러는 CPU 자원을 다른 중요한 작업에 할당한다. 그 때문에 Dawn이 GPU에 명령(Command Buffer)을 보내는 작업이 아주 미세하게 지연될 수 있었다. 그런데 Dawn의 현재 로직은 이 지연 시간을 제대로 고려하지 않고, 다음 프레임의 렌더링 명령을 너무 빨리 준비하기 시작했다. 그 결과, 이전 프레임의 명령과 다음 프레임의 명령이 GPU 파이프라인 안에서 충돌하며 순간적인 결함을 만들어낸 것이었다.
“우리는 GPU와의 통신이 항상 즉각적일 거라고 너무 낙관했던 거야.”
드미트리가 말했다.
이제 원인을 알았으니 해결책은 명확했다.
GPU가 이전 프레임의 작업을 완전히 마쳤다는 신호(Fence)를 명시적으로 기다린 후에, 다음 프레임 작업을 시작하도록 동기화 로직을 강화하는 것.
그들은 즉시 패치 작업에 착수했다. 최종 안정 버전 출시까지 남은 시간은 얼마 없었다. 베타 채널의 수천만 사용자들이라는 거대한 그물은, 실험실에서는 결코 잡을 수 없었던 교활한 유령을 마침내 수면 위로 끌어올려 준 것이다.