심연의 괴물, 드라이버 버그

152025년 08월 10일4

Dawn 프로젝트는 순항하는 듯 보였다. 붉은 삼각형이 화면에 떠올랐고, 컴퓨트 셰이더는 압도적인 성능을 증명했다. 팀은 자신들의 설계가 옳았다는 확신에 차 있었다. 하지만 그들의 발밑에는 예측할 수 없는 심연이 도사리고 있었다. 그 심연의 이름은 ‘그래픽 드라이버(Graphics Driver)’였다.

드라이버는 운영체제와 GPU 하드웨어 사이를 잇는 통역사와 같다. WebGPU API가 아무리 완벽하게 설계되어도, 이 통역사가 실수를 하거나 제멋대로 행동하면 모든 것이 엉망이 된다.

첫 번째 괴물이 모습을 드러낸 것은 테스트 자동화 시스템에서였다.
“드미트리, 이쪽으로 와서 이것 좀 보시죠.”

QA 팀의 리더, 사라가 심각한 표정으로 드미트리를 불렀다. 그녀의 모니터에는 수백 개의 테스트 결과가 나열되어 있었다. 대부분은 녹색 ‘PASS’였지만, 유독 특정 테스트 케이스 하나가 붉은색 ‘FAIL’을 띄고 있었다.

“어제까지 멀쩡히 통과되던 텍스처 밉맵(Mipmap) 생성 테스트입니다. 그런데 오늘 아침부터 특정 제조사의 특정 GPU 모델에서만 계속 실패하고 있어요.”

드미트리는 눈살을 찌푸렸다. 코드는 어제와 똑같았다. 바뀐 것은 아무것도 없었다.
“해당 제조사에서 어젯밤에 새 드라이버 업데이트를 배포했습니다.”
사라의 말에 드미트리의 머릿속이 복잡해졌다.

그는 즉시 해당 GPU가 장착된 머신으로 달려가 디버거를 붙였다. Dawn의 코드는 한 줄 한 줄 완벽하게 실행되고 있었다. Vulkan API 호출도 사양에 명시된 그대로였다. 하지만 GPU가 반환한 결과물은 완전히 깨진 이미지였다. 드라이버가 Dawn의 정당한 명령을 오해석하고 있었다.

“젠장, 또 드라이버 버그야.”

이것은 시작에 불과했다.
어떤 GPU에서는 컴퓨트 셰이더가 이유 없이 멈춰 섰고, 다른 GPU에서는 특정 블렌딩 모드를 사용했을 때 화면이 뒤집혔다. 심지어 macOS의 Metal 환경에서는 특정 순서로 API를 호출하면 시스템 전체가 얼어붙는 치명적인 문제도 발견되었다.

팀은 끝없는 두더지 잡기 게임에 내던져졌다. 버그를 발견하면, 그것이 Dawn의 버그인지, 아니면 드라이버의 버그인지부터 밝혀내야 했다. Dawn의 버그라면 코드를 수정하면 그만이었다. 하지만 드라이버 버그라면 문제는 훨씬 복잡해졌다.

그들은 하드웨어 제조사에 버그 리포트를 보내야 했다. 하지만 거대 제조사가 이 작은 프로젝트 팀의 리포트에 즉각적으로 반응해 줄 리 만무했다. 드라이버 업데이트에는 수개월이 걸릴 수도 있었다. 그동안 손을 놓고 기다릴 수만은 없는 노릇이었다.

결국, 그들은 ‘우회(Workaround)’라는 길을 택해야 했다.

드미트리는 팀원들을 모아놓고 말했다.
“이 드라이버는 우리가 A라고 말하면 B라고 알아듣습니다. 그렇다면 우리가 원하는 A라는 결과를 얻기 위해, 우리는 C라고 말하는 법을 찾아내야 합니다.”

그때부터 기묘한 코딩이 시작되었다.
Dawn의 코드베이스에는 if (gpu_vendor == 'VENDOR_X' && driver_version < '1.2.3') { ... } 와 같은 조건문들이 하나둘 늘어나기 시작했다.

  • X사 드라이버의 버그를 피하기 위해, 직접 밉맵을 생성하는 대신 여러 개의 텍스처를 만들어 수동으로 복사하는 코드를 추가한다.
  • Y사 드라이버에서 크래시를 유발하는 API 호출 순서를 피하기 위해, 일부러 비효율적인 중간 단계를 삽입한다.
  • Z사 GPU에서 메모리 누수를 막기 위해, 명시적으로 자원을 해제하는 코드를 불필요해 보이는 곳에 추가한다.

이런 우회 코드들은 논리적으로는 설명되지 않는, 오직 특정 환경의 버그를 피하기 위한 ‘주술’과도 같았다. 아름답고 일관성 있어야 할 코드베이스는 점점 누더기처럼 변해갔다. 팀원들은 자신들이 공들여 설계한 아키텍처를 스스로 망가뜨리는 듯한 자괴감에 시달렸다.

“우리가 지금 뭘 하고 있는 건지 모르겠습니다. 이건 공학이 아니라 민간요법 같아요.”
벤이 좌절 섞인 목소리로 말했다.

드미트리가 그의 어깨를 두드렸다.
“알고 있네, 벤. 하지만 이게 바로 현실이야. 우리는 이상적인 세상이 아니라, 수십 개의 제조사와 수백 개의 드라이버 버전이 뒤섞인 현실 세계 위에서 동작하는 소프트웨어를 만들고 있는 걸세. 우리의 임무는 이 혼돈 속에서도 사용자에게 일관되고 안정적인 경험을 제공하는 거야. 비록 그 과정이 우아하지 않더라도.”

그의 말은 쓰라린 위로가 되었다.
WebGPU의 길은 단순히 멋진 API를 설계하는 것에서 끝나지 않았다. 그것은 전 세계의 수많은 하드웨어와 소프트웨어가 만들어내는 혼돈의 심연을 탐험하고, 그 안에서 어떻게든 살아남는 방법을 찾아내는 끈질긴 생존 투쟁이었다. 그리고 이 과정에서 얻어진 경험들은, 훗날 WebGPU 사양을 더욱 견고하게 만드는 귀중한 밑거름이 되고 있었다. ‘이런 API 호출은 드라이버 버그를 유발할 가능성이 높으니, 사양 단계에서부터 금지하자’는 식의 현실적인 제안들이 커뮤니티에 올라가기 시작한 것이다.