Chrome 157의 HTML-in-Canvas: 2D, WebGL, WebGPU 내의 대화형 DOM

게시일: 2026년 10월 26일

성공적인 오리진 트라이얼에 이어 Chrome 157에서는 HTML-in-Canvas API의 공식 안정화 버전이 출시됩니다. HTML-in-Canvas API는 DOM의 상호작용적이고 접근성이 뛰어난 환경과 <canvas>의 고성능 픽셀 수준 제어 간의 격차를 해소합니다. 이 API는 풍부한 브라우저 기능과 GPU 가속 캔버스 그래픽이라는 두 가지 장점을 모두 제공합니다.

HTML-in-Canvas API의 동영상 개요

캔버스와 DOM의 딜레마

이전에는 시각적으로 까다로운 웹 앱을 만들 때 표준 HTML 요소와 원시 캔버스 컨텍스트 중에서 선택해야 했습니다.

기술 강점 제한사항
<canvas> 2D 및 3D 그래픽 파이프라인, 맞춤 셰이더, 오프스크린 작업자를 구동하는 GPU 액세스를 통한 하위 수준 픽셀 제어 데이터가 많은 무거운 UI를 위한 고성능 렌더링 텍스트 선택, 복사 및 붙여넣기, 마우스 오른쪽 버튼 클릭 작업, 텍스트 줄바꿈과 같은 기본 제공 웹 플랫폼 기능이 없습니다. 불투명 픽셀 그리드는 기본적으로 스크린 리더, 페이지에서 찾기, 자동 번역, 자동 완성을 지원하지 않으며 대체 구현이 필요합니다.
HTML 기본 제공 양식 컨트롤, 반응형 서체, CSS 스타일이 포함된 시맨틱 UI를 즉시 사용할 수 있습니다. 스크린 리더, 페이지에서 찾기, DevTools를 위한 심층 브라우저 통합 복잡한 UI의 성능을 제어하는 기능이 제한적입니다. 시각 효과는 직접적인 픽셀 조작이나 셰이더 없이 표준 CSS 및 SVG로 제한됩니다.

HTML-in-Canvas 이전

이 API가 도입되기 전에는 캔버스가 많은 UI를 빌드하는 경우 두 가지 접근 방식 중 하나를 선택해야 했으며, 각 방식에는 다음과 같은 단점이 있었습니다.

  1. 텍스트를 캔버스 픽셀로 직접 렌더링 (fillText()): 앱이 텍스트와 UI 컨트롤을 원시 픽셀로 명령형으로 그렸습니다. 이 접근 방식에는 다음과 같은 단점이 있습니다.
    • 접근성 분석: 보이지 않는 대체 DOM을 수동으로 구성하고 동기화하지 않으면 스크린 리더와 보조 도구에서 캔버스 픽셀을 읽을 수 없습니다.
    • 브라우저 기능 손실: 사용자가 페이지 내 찾기 (Ctrl/Cmd+F)로 검색하거나, 텍스트를 자연스럽게 복사하여 붙여넣거나, 컨텍스트 메뉴를 트리거하거나, 브라우저 번역 및 맞춤법 검사를 사용할 수 없습니다.
    • 복잡한 서체 엔진: 국제화를 지원하려면 대규모 JavaScript 레이아웃 엔진을 번들로 묶어야 합니다.
  2. 캔버스 상단의 플로팅 HTML 오버레이: 예를 들어 JavaScript에서 경계 상자와 행렬 변환을 계산하여 캔버스 위에 표준 HTML 요소를 배치하는 라이브러리를 사용합니다. 이 접근 방식의 단점은 다음과 같습니다.
    • 동기화 지연 및 시각적 테어링: 3D에서 스크롤, 확대/축소 또는 카메라 움직임으로 인해 프레임 시간 차이로 인해 오버레이 DOM 요소가 캔버스 픽셀을 기준으로 이동하거나 지터링될 수 있습니다.
    • 클리핑 및 Z 순서 제한: HTML 오버레이는 항상 전체 캔버스 버퍼의 맨 위에 위치합니다. 3D 장면 내부에 HTML을 삽입하는 것 (예: 3D 객체 뒤, 유리 소재 내부 또는 거울에 반사되는 경우)은 복잡한 iframe-to-image 해결 방법 없이는 불가능했습니다.
    • 성능 오버헤드: 오버레이를 캔버스와 정렬된 상태로 유지하려면 JavaScript에서 각 오버레이의 변환을 다시 계산하고 프레임마다 style.transform에 작성해야 합니다. 그러면 브라우저가 각 문자열을 파싱하고 프레임을 렌더링하기 전에 요소의 스타일을 다시 계산하므로 오버레이를 추가할 때마다 기본 스레드 작업이 늘어납니다. 2D 컨텍스트에서 drawElementImage()는 요소의 위치를 업데이트합니다. WebGL 및 WebGPU에서는 계산한 변환을 updateElementGeometry()에 행렬로 전달합니다. 어느 쪽이든 브라우저는 CSS를 파싱하거나 스타일을 다시 계산하지 않습니다.

HTML-in-Canvas의 주요 이점

HTML-in-Canvas는 이러한 단점을 보완합니다. <canvas> 요소 내에 HTML을 배치하면 콘텐츠가 상호작용 가능한 상태로 유지되고 모든 브라우저 통합이 자동으로 작동합니다.

<canvas> 내부에 렌더링된 HTML 콘텐츠는 <canvas> 외부의 HTML과 동일한 기능을 갖습니다.

  • 텍스트 레이아웃 및 서식: CSS 스타일이 적용된 여러 줄 또는 양방향 텍스트를 포함한 텍스트 레이아웃 및 서식을 지원합니다.
  • 양식 컨트롤: 광범위한 CSS 및 셰이더 맞춤설정 옵션이 있는 표현력이 풍부한 양식 컨트롤입니다.
  • 텍스트 선택, 복사 및 붙여넣기, 마우스 오른쪽 버튼 클릭: 사용자는 3D 장면 내에서 텍스트를 강조 표시하거나 컨텍스트 메뉴를 트리거할 수 있습니다.
  • 접근성: 캔버스 내에서 렌더링된 HTML 콘텐츠는 스크린 리더의 접근성 트리에 노출됩니다.
  • 브라우저 기능 통합: 번역, 자동 완성, 페이지에서 찾기와 같은 브라우저 기능이 즉시 작동합니다. 사용자는 WebGL 및 WebGPU 텍스처 내에서 텍스트를 번역하거나 검색할 수 있습니다.
  • 확장 프로그램 통합: 브라우저 확장 프로그램이 콘텐츠에서 작동합니다. 예를 들어 텍스트 대체 확장 프로그램은 3D 메시에 렌더링된 텍스트를 자동으로 업데이트합니다.
  • DevTools 통합: Chrome DevTools에서 직접 캔버스 UI 요소의 CSS 스타일을 검사하고 조정합니다.
  • 색인 생성 가능성 및 AI 에이전트: 웹 크롤러와 AI 에이전트는 2D 및 3D 장면으로 렌더링된 DOM 콘텐츠의 색인을 생성할 수 있습니다.
  • 미디어 편집 및 내보내기: 실시간 DOM 요소가 포함된 전체 캔버스 합성물을 이미지 (toDataURL(), toBlob()) 또는 동영상 스트림 (captureStream())으로 직접 내보냅니다.
캔버스에 직접 렌더링된 텍스트와 HTML-in-Canvas의 기능 통합을 비교하는 데모입니다. HTML-in-Canvas 창에서는 콘텐츠를 선택하고 번역할 수 있으며 자동 완성 등의 브라우저 기능이 기본적으로 작동합니다. 표준 캔버스 창에서 콘텐츠는 fillText 메서드를 사용하여 캔버스에 직접 렌더링되며 상호작용이 불가능합니다.

주요 사용 사례

HTML-in-Canvas는 여러 영역에서 기능을 지원합니다.

  • 대규모 캔버스 기반 앱: 무거운 웹 앱은 UI 구성요소를 캔버스 작업공간에 직접 렌더링하여 접근성을 개선하고 번들 크기를 줄일 수 있습니다.
  • 3D 장면 및 게임: 몰입형 WebXR 환경 및 게임은 게임 내 터미널이나 읽을 수 있는 3D 책과 같은 상호작용 DOM 요소를 장면 내에 직접 배치할 수 있습니다.
  • 미디어 편집 및 내보내기: 풍부한 HTML 서체와 셰이더 효과를 결합한 광고 소재 도구를 사용하면 합성 장면을 이미지 또는 동영상 스트림으로 직접 내보낼 수 있습니다.
  • 표현력이 뛰어난 UI: HTML 콘텐츠를 원시 픽셀로 조작하여 셰이더 기반 시각 효과를 빌드할 수 있습니다.

HTML-in-Canvas 빠른 시작

캔버스에서 HTML을 렌더링하려면 다음 단계를 따르세요.

  1. 캔버스를 준비합니다. 브라우저가 HTML을 캔버스에 렌더링해야 한다는 것을 알 수 있도록 올바른 속성을 선언적으로 설정합니다. 이 설정은 2D, WebGL, WebGPU 컨텍스트에서 동일합니다. 캔버스를 설정하는 방법과 독립적으로 그려질 HTML 요소를 선언하는 방법을 알아보세요.

    <!-- Prepare your canvas by setting the `content` attribute -->
    <canvas id="canvas" width="600" height="400" content="drawable">
      <!-- Mark child as `drawable` to render to canvas -->
      <div id="myElement" drawable>
        <!-- Your HTML here -->
      </div>
    </canvas>
    
  2. 캔버스에 요소 이미지를 그립니다. 정확한 구현은 2D, WebGL 또는 WebGPU 컨텍스트에서 HTML을 렌더링하는지에 따라 달라집니다.

    const ctx = canvas.getContext("2d");
    // Draw HTML element into canvas in 2D
    ctx.drawElementImage(myElement, myElementX, myElementY);
    
  3. 선택사항: DOM과 픽셀을 동기화합니다. 기하학 동기화는 사용하는 컨텍스트에 따라 달라집니다. 2D에서는 브라우저가 기본적으로 이를 자동으로 처리하는 반면, 3D 컨텍스트에서는 변환을 구성하여 updateElementGeometry 메서드에 전달해야 합니다.

    // In 3D, construct a transform as needed, for example:
    const transform = new DOMMatrix().translate(x, y);
    // Synchronize the element's DOM and pixels
    canvas.updateElementGeometry(myElement, { canvasTransform: transform });
    

프레임워크 및 생태계 지원

주요 WebGL 및 3D 그래픽 라이브러리는 HTML-in-Canvas를 지원합니다.

  • Three.js: THREE.HTMLTexture를 사용하여 실험용 지원을 제공합니다.

    const material = new THREE.MeshBasicMaterial();
    material.map = new THREE.HTMLTexture(uiElement);
    const mesh = new THREE.Mesh(new THREE.BoxGeometry(1, 1, 1), material);
    scene.add(mesh);
    
  • PlayCanvas: setSource()를 사용하여 HTML 텍스처 스트리밍을 지원합니다.

    canvas.addEventListener('paint', () => {
      htmlTexture.setSource(htmlElement);
    }, { once: true });
    
  • Babylon.js: BABYLON.HtmlTexture를 통해 기본 제공 바인딩을 제공합니다.

    const htmlTexture = new BABYLON.HtmlTexture("htmlTexture", uiElement, scene);
    material.diffuseTexture = htmlTexture;
    
  • v8.19.0 버전에서 HTMLSource를 사용하여 기본 지원을 제공하는 PixiJS

    import { HTMLSource } from 'pixi.js/html-source';
    const sprite = Sprite.from(new HTMLSource({ resource: form, autoUpdate: true }));
    app.stage.addChild(sprite);
    
  • CanvasUI: HTML-in-Canvas를 위해 특별히 설계된 오픈소스 구성요소 라이브러리입니다.

구현에 관한 자세한 내용은 각 프레임워크의 문서를 참고하세요.

기능 감지 및 대체 전략

교차 브라우저 호환성을 보장하려면 코드를 실행하기 전에 API 지원을 확인하세요.

export function supportsHtmlInCanvas() {
  if (typeof document === "undefined") return false;
  const canvas = document.createElement("canvas");
  canvas.setAttribute("content", "drawable");
  return canvas.content === "drawable";
}

API를 사용할 수 없는 경우 대체 UI, 플로팅 HTML 오버레이 또는 사용 가능한 라이브러리 (예: three-html-render, html2canvas, dom-to-image) 중 하나로 대체할 수 있습니다.

다음 단계