잃어버린 컨텍스트

932025년 09월 18일5

외부 텍스처 API가 도입되면서, 개발자들은 마침내 이미지와 비디오 데이터를 효율적으로 WebGPU 파이프라인에 통합할 수 있게 되었다. 웹은 한 단계 더 동적이고 상호작용적인 플랫폼으로 진화했다. 하지만 이 강력한 기능은, 개발자들이 미처 예상하지 못했던 새로운 종류의 함정을 파놓고 있었다.

함정의 존재는 한 인기 있는 웹 기반의 소셜 네트워킹 사이트에서 처음으로 드러났다.
그 사이트는 사용자가 페이지를 스크롤하면, 화면 밖으로 사라지는 동영상들은 재생을 멈추고, 다시 화면 안으로 들어오면 재생을 재개하는 최적화 로직을 가지고 있었다.

그런데 WebGPU 기반의 비디오 필터 기능을 도입한 이후, 이상한 현상이 발생하기 시작했다.
화면 밖으로 나갔다가 다시 돌아온 비디오에, 더 이상 필터 효과가 적용되지 않고 원본 영상만 보이는 버그가 간헐적으로 발생했다.

사이트의 개발팀은 원인을 찾지 못하고, 결국 Dawn 팀에 도움을 요청했다.
“저희는 아무것도 바꾸지 않았습니다. 단지 비디오의 재생을 잠시 멈췄다가 다시 시작했을 뿐인데, WebGPU 렌더링 컨텍스트가 완전히 망가져 버립니다.”

드미트리는 이 현상이 단순한 버그가 아니라, 웹의 복잡한 생명 주기(Lifecycle)와 관련된 근본적인 문제일 수 있다고 생각했다.
그는 팀의 시니어 엔지니어인 카이에게 이 문제의 심층 분석을 맡겼다.

카이는 며칠 동안 브라우저의 내부 동작을 추적했다.
그리고 그는 마침내, 문제의 원인이 WebGPU가 아닌, 브라우저의 ‘자원 관리 정책’에 있음을 밝혀냈다.

카이가 팀 회의에서 설명했다.
“여러분, 브라우저는 똑똑합니다. 그리고 매우 효율적이죠. 만약 사용자가 현재 보고 있지 않은 비디오가 있다면, 브라우저는 시스템 자원을 아끼기 위해 그 비디오와 연결된 모든 하드웨어 리소스, 예를 들어 비디오 디코더나 GPU 메모리 버퍼를 운영체제에 반납해버립니다.”

그는 화이트보드에 그림을 그렸다.
“문제는, 이 과정이 WebGPU에게는 전혀 알려지지 않는다는 겁니다. WebGPU의 GPUDevice는 여전히 자신이 유효한 비디오 텍스처를 참조하고 있다고 믿고 있죠. 하지만 그 텍스처의 실제 하드웨어 자원은 이미 허공으로 사라져버린 뒤입니다.”

“그리고 사용자가 다시 스크롤해서 비디오가 화면에 나타나면, 브라우저는 새로운 하드웨어 자원을 할당해서 비디오를 다시 재생합니다. 하지만 WebGPU는 이 사실을 모르고, 여전히 예전의 ‘죽은’ 자원을 참조하려고 하니, 렌더링이 실패하거나 아무것도 그려지지 않는 겁니다.”

이것은 ‘컨텍스트 상실(Context Loss)’이라고 불리는, 그래픽스 프로그래밍의 고전적인 문제였다.
사용자가 컴퓨터를 잠자기 모드로 전환하거나, 다른 고사양 프로그램을 실행하여 GPU 자원이 부족해지는 등의 상황에서, 운영체제는 언제든지 애플리케이션의 GPU 컨텍스트를 빼앗아 갈 수 있었다.
네이티브 개발자들은 항상 이 ‘컨텍스트 상실’에 대비하는 코드를 작성해야만 했다.

하지만 웹 개발자들은 그동안 브라우저라는 안전한 보호막 뒤에 있었다. WebGL은 컨텍스트 상실이 발생하면, 간단한 이벤트를 통해 개발자에게 알려주고, 복구할 수 있는 방법을 제공했다.

그런데 WebGPU는 달랐다.
초기 설계 당시, WebGPU는 ‘더 예측 가능하고 명시적인’ API를 지향했다. 그들은 컨텍스트 상실과 같은 암시적인 상태 변화를 최대한 배제하려 했다. 그 결과, 개발자들이 이 중요한 예외 상황에 대비할 수 있는 명확한 방법이 부족했던 것이다.

드미트리는 이것이 설계상의 심각한 허점이었음을 인정해야 했다.
그들은 성능과 명시성에 집중한 나머지, 실제 세상의 웹 브라우저가 얼마나 역동적이고 예측 불가능한 환경인지를 간과했다.

W3C 회의.
드미트리는 이 문제를 공식적으로 제기하고, 해결책을 제안했다.

“우리는 개발자들에게, 자신들이 사용하는 GPUDevice가 언제든지 ‘상실(lost)’될 수 있다는 사실을 명확하게 알려줘야 합니다. 그리고 그 상실의 원인이 무엇인지에 대한 정보도 함께 제공해야 합니다.”

그는 device.lost 라는, Promise를 반환하는 새로운 속성을 제안했다.
개발자는 이 Promise를 await 함으로써, 디바이스가 상실될 때까지 기다리고, 상실이 발생하면 그 이유(reason)를 확인하여 적절한 복구 로직을 수행할 수 있다.

try {
  await device.lost;
  console.log('Device was lost!', device.lost.reason);
  // 새로운 디바이스를 요청하는 등의 복구 로직 실행
} catch (e) {
  // 디바이스가 아직 상실되지 않음
}

또한, 그는 GPUDevice가 상실되었을 때, 모든 후속 API 호출이 즉시 명확한 에러를 발생시키도록 사양을 강화해야 한다고 주장했다. 더 이상 소리 없는 실패는 없어야 했다.

이 제안은 커뮤니티의 폭넓은 지지를 얻었다.
이것은 WebGPU가 초기의 이상적인 설계를 넘어, 실제 웹이라는 혼돈의 세계에 적응하며 더 견고하고 성숙한 플랫폼으로 진화하는 중요한 과정이었다.

드미트리는 이 사건을 통해, 가장 잘 설계된 시스템조차도, 그것이 놓인 현실 세계의 복잡성을 모두 예측할 수는 없다는 겸허한 진실을 배웠다.
플랫폼을 만든다는 것은, 단 한 번의 완벽한 설계를 하는 것이 아니었다.
그것은 세상의 변화에 귀 기울이고, 자신들의 실수를 인정하며, 끊임없이 배우고 적응해나가는, 끝없는 여정이었다.