Cheondi
개발 · 웹

WebGPU 시대의 Unity WebGL

브라우저의 새 그래픽 API인 WebGPU를 Unity WebGL과 비교하며 기능 감지, 폴백, 실제 지원 경계를 정리했습니다.

  • #webgpu
  • #webgl
  • #unity
  • #browser
  • #graphics

Unity 프로젝트를 WebGL로 빌드하면서 브라우저도 꽤 많은 일을 한다는 걸 알게 됐다. 빌드 결과가 JavaScript와 WebAssembly로 바뀌고, 화면은 브라우저의 WebGL 위에서 그려진다. 네이티브 앱처럼 보이지만 메모리, 입력, 네트워크, 그래픽 기능 모두 브라우저 규칙을 따라야 했다.

2023년에 Chrome에서 WebGPU가 기본 제공됐다는 글을 보고 처음 든 생각은 단순했다. “그럼 Unity WebGL 빌드도 더 빨라지는 건가?” 결론부터 말하면 그렇게 자동으로 이어지는 관계는 아니었다.

WebGL과 WebGPU의 차이

WebGL은 OpenGL ES에 가까운 상태 기반 API다. 반면 WebGPU는 Vulkan, Metal, Direct3D 12 같은 현대 그래픽 API의 개념을 웹에 맞게 가져왔다. 명령을 미리 구성하고 파이프라인과 리소스 사용을 더 명시적으로 표현한다.

항목 WebGL WebGPU
설계 배경 OpenGL ES 계열 현대 네이티브 GPU API
명령 모델 상태 변경 중심 command encoder와 queue
셰이더 GLSL 계열 WGSL
범용 계산 제한적 우회 compute pipeline 제공
지원 확인 넓은 브라우저 지원 브라우저·OS·장치 확인 필요

새 API가 더 낮은 수준의 제어를 제공해도 기존 엔진의 렌더링 백엔드가 이를 지원해야 사용할 수 있다. Unity에서 빌드 대상을 WebGL로 골랐다는 사실만으로 브라우저가 내부 렌더링을 WebGPU로 바꿔 주지는 않는다.

지원 여부는 실행할 때 확인

WebGPU 자체를 사용하는 웹 기능이라면 사용자 에이전트 문자열보다 기능 감지가 먼저다.

async function createGraphicsBackend() {
  if (!('gpu' in navigator)) {
    return { kind: 'webgl', reason: 'WebGPU API unavailable' };
  }

  const adapter = await navigator.gpu.requestAdapter();
  if (!adapter) {
    return { kind: 'webgl', reason: 'No compatible adapter' };
  }

  const device = await adapter.requestDevice();
  return { kind: 'webgpu', device };
}

navigator.gpu가 있다고 끝도 아니다. 보안 컨텍스트인지, 호환 어댑터가 있는지, 필요한 limit과 feature를 제공하는지 확인해야 한다. 회사 내부 페이지든 개인 프로젝트든 HTTPS가 아닌 환경에서 테스트 결과가 달라질 수 있다.

폴백은 단순히 오류 메시지를 띄우는 것보다 기능 수준을 정해 두는 편이 낫다.

const backend = await createGraphicsBackend();

if (backend.kind === 'webgpu') {
  startParticlePreview({ backend: backend.device, count: 100000 });
} else {
  console.info(`WebGL fallback: ${backend.reason}`);
  startParticlePreview({ backend: createWebGL2Context(), count: 10000 });
}

같은 장면을 무조건 같은 품질로 실행하려다 실패하기보다, WebGPU에서는 많은 파티클과 compute 작업을 켜고 WebGL에서는 규모를 줄이는 식이다. 중요한 기능이라면 아예 지원 브라우저를 안내하는 선택도 가능하다.

Unity WebGL에서 따로 볼 경계

Unity WebGL을 다룰 때는 다음 층을 나눠 보는 게 좋았다.

Unity C# 코드와 렌더 파이프라인
        ↓ IL2CPP / 빌드 도구
WebAssembly + JavaScript glue
        ↓ Unity가 선택한 웹 그래픽 백엔드
브라우저 그래픽 API
        ↓
운영체제와 GPU 드라이버

브라우저가 WebGPU를 지원하는 것과 현재 Unity 버전·렌더 파이프라인·플랫폼 빌드가 WebGPU를 출력하는 것은 별도 조건이다. 기술 소개 글만 보고 설정 하나로 바뀐다고 생각하면 문제의 층을 잘못 찾게 된다.

직접 만든 JavaScript 플러그인에서 WebGPU를 쓰는 방법도 떠올릴 수 있지만, Unity가 소유한 캔버스·렌더링 수명·리소스와 별도 GPU 컨텍스트를 섞는 비용을 확인해야 한다. 작은 계산 결과를 전달하는 실험과 전체 렌더러를 바꾸는 일은 규모가 완전히 다르다.

먼저 해 볼 만한 작은 실험

  • 브라우저별 navigator.gpu와 adapter 결과 기록
  • 필요한 feature와 limit을 실행 전에 확인
  • WebGPU 실패 시 WebGL2 경로가 실제로 동작하는지 확인
  • 초기화 시간, 프레임 시간, 메모리를 같은 장면에서 비교
  • Unity 빌드 자체의 그래픽 백엔드와 외부 JavaScript 실험을 구분

WebGPU는 웹 그래픽의 큰 변화지만 이름만으로 성능을 보장하지 않는다. 내가 이해한 핵심은 “더 빠른 WebGL”이 아니라, GPU 작업을 더 명시적으로 구성할 수 있는 새 API라는 점이다. Unity WebGL과 연결하려면 브라우저 지원보다 한 단계 더 나아가 엔진의 실제 출력 경로를 확인해야 한다.

또 하나 배운 건 지원 표를 제품 요구사항으로 그대로 옮기면 안 된다는 점이었다. “브라우저가 지원한다”와 “우리 장면이 필요한 feature와 limit을 만족한다” 사이에는 차이가 있다. 장치별 초기화 결과와 폴백 사용 비율을 기록하고, WebGL 경로도 계속 테스트해야 새 API를 켠 뒤 기존 사용자를 놓치지 않는다. 기술 선택은 발표 시점보다 실제 사용 환경의 측정 결과에 맞춰야 했다.

참고: Chrome의 WebGPU 출시 안내