요약
Chrome이 DOM 요소를 캔버스와 3D 텍스처에 그려 주는 HTML-in-Canvas API를 시범 공개했습니다.
구글 Chrome 팀의 토마스 나테스타드와 나탈리아 마르코보로도바가 Chrome 개발자 블로그에 쓴 글입니다. 개발자들은 그동안 텍스트와 접근성 기능이 풍부한 DOM과 픽셀 성능이 좋은 캔버스 가운데 하나를 골라야 했습니다. 이 API는 둘을 함께 쓰게 하려는 시도입니다.
왜 중요한가
- 캔버스로 만든 앱과 게임에서도 화면 낭독기, 페이지 내 검색, 번역, 확장 프로그램이 동작하게 됩니다.
- 3D 장면이나 WebXR 안에 실제로 조작되는 웹 UI를 넣을 수 있어, 캔버스용 UI를 따로 만들 부담이 줄어듭니다.
- Three.js와 PlayCanvas가 이미 실험적으로 지원해 기존 3D 라이브러리에서 바로 써 볼 수 있습니다.
핵심 내용
- canvas 요소에 layoutsubtree 속성을 붙이면 안쪽 요소가 캔버스에 그려지고 접근성 트리에도 노출됩니다.
- 2D는 drawElementImage로, WebGL과 WebGPU는 전용 함수로 DOM 요소를 그리거나 텍스처로 올립니다.
- 그릴 때 돌려받는 변환값을 요소에 적용하면 클릭과 입력이 화면에 보이는 위치와 맞습니다.
- 오리진 트라이얼(정식 출시 전 신청한 사이트에서 기능을 미리 켜는 시범 운영)은 Chrome 148~150에서 진행합니다.
- 보안과 개인정보 문제로 다른 출처의 iframe은 그릴 수 없고, 스크롤도 자바스크립트 실행에 묶입니다.
HN 반응
- DOM이 앱 개발의 걸림돌이니 새 UI 기반을 달라는 쪽과, DOM을 버리면 더 나쁜 DOM을 다시 만들 뿐이라는 쪽이 맞섰습니다.
- 캔버스 위에 요소를 띄우는 방식과 무엇이 다르냐는 의문과, 장식 이상의 용도에는 한계가 뚜렷하다는 비판도 나왔습니다.
웹에서 앱을 만들 때 문제는 바로 DOM입니다. 30년 넘은 레거시를 물려받지 않는 새로운 UI 렌더링 방식이나 기반을 추가하면 될 일인데, 브라우저는 왜 굳이 복잡한 걸 계속 얹는 건지 어이가 없네요. (그 30년 중 15년 가까이는 웹 앱이라는 것 자체가 없었다는 걸 떠올려 보세요.)
진짜 애플리케이션을 만들려고 하면 DOM은 느리고 짜증 나는 쓰레기 더미예요.
DOM을 배우지 않는 자는 DOM을 다시 발명하게 될 운명이죠. 그것도 더 못나게요.
90년대부터 이어진 GUI 툴킷들을 보세요. DOM과 웹 개발은 역사의 우연이었어요.
DOM의 G는 Graphics의 G예요.
인터넷을 통해 쓰는 GUI 툴킷 중에 어떤 걸 말씀하시는 건가요?
제 요점은 브라우저에는 GUI 툴킷이 없고, 있어야 한다는 거예요. 문서 객체 모델을 애플리케이션 전달 플랫폼으로 억지로 바꾸려 들지 말고, DOM은 문서만 다루게 두고 다른 새로운 걸 내놓아야 합니다. 그래야 새로운 것에 접근성 지원도 제대로 붙일 수 있고요. 지금은 다들 UI를 그리려고 GPU를 맨손으로 만지고 있으니 스크린 리더 지원은 없죠.
여기서 하는 건 어설프기 짝이 없는 시도예요. 그리기는 직접 하게 하면서 접근성은 DOM으로 해결하겠다는 거잖아요. 양쪽의 단점만 모아 놓은 셈이죠?
우리에게 남은 유일한 희망은 AI가 스크린 리더를 대체하는 거고, 그러면 그냥 WebGPU 앱을 내놓으면 되겠네요.
저는 캔버스 네이티브 워크스페이스를 통째로 만들고 싶었습니다. 처음에는 HTML만 쓰는 "가짜 캔버스" 방식으로 구현했는데, 패널이 50개쯤만 되어도 반응 속도가 꽤 많이 떨어졌습니다. 그래서 "진짜 캔버스"로 새로 구현하고 패널과 상호작용을 하나씩 만들어 냈습니다.
성능 면에서는 이 방식이 훨씬 나았습니다(패널과 중첩 패널 1000개 이상을 60fps 이상으로 거뜬히 처리합니다). 하지만 패널마다 구현 복잡도가 크게 올라갑니다. 예를 들어 마크다운 렌더링 JS 라이브러리나 서드파티 UI 컴포넌트는 그냥 가져다 쓸 수 없습니다. 게다가 뭔가 하나 바꿀 때마다 성능이 크게 떨어지는 일이 잦았습니다.
https://canaster.in/
지금은 텍스트, 마크다운, 이미지, 오디오, 비디오, PDF 패널이 있습니다(파일을 드래그 앤 드롭할 수 있습니다).
html-in-canvas API로 다시 한번 구현해 봐야 할지 고민 중입니다. 다만 이 API가 효용이나 사용량이 안 보인다고 유지보수되지 않을까 걱정입니다.
최신 브라우저의 DOM은 사람들이 캔버스나 WebGPU로 직접 만드는 것과 똑같이 텍스처 합성(compositing) 기반이라서 아주 빠를 수 있습니다.
캔버스 렌더링으로 버틸 수 있는 정도라면, 오히려 HTML을 쓰되 CSS containment와 절대 위치 지정으로 CSS와 레이아웃 비용을 크게 줄일 수 있습니다.
팁 감사합니다. contain: strict는 몰랐네요. position absolute야 물론 다들 아는 거고요. contain은 한번 살펴보겠습니다. 그래도 contain 하나 때문에 HTML 기반 캔버스를 다시 시도해 볼 만한 가치는 없어 보여요. 네이티브 캔버스 방식으로 이미 꽤 멀리 왔다는 느낌이 있거든요.
1년 전에 html-in-canvas를 두고 나온 토론입니다: https://news.ycombinator.com/item?id=44772177
(댓글 116개)
죄송해요, 제가 웹은 초보라서요. 혹시 이거 재귀적으로도 되나요? 예를 들면 html-in-canvas 안에 또 html-in-canvas를 넣을 수 있나요? :D
저는 웹 초보는 아니지만 똑같은 게 궁금하네요!
됩니다.
크롬에서 활성화하면 지금도 중첩은 동작하는데, 어째서인지 이벤트가 깨집니다.
https://johnhenry.github.io/html-in-canvas-lab/
도멤션(Domception)이네요.
(2026년 5월.)
그 무렵에 나온 관련 댓글 모음입니다: https://news.ycombinator.com/item?id=48201222
거기에 "yo dawg" 짤(Xzibit 밈)이 하나쯤은 있을 줄 알았는데요.
음, 이게 잠재적인 프라이버시 유출을 어떻게 막는지 얼른 이해가 안 되네요. 예를 들어 DOM 하이퍼링크를 캔버스에 그린 다음 픽셀 데이터에서 방문 여부에 따른 링크 색을 긁어내는 식으로요.
아니면 제가 시대에 뒤처진 걸 수도 있겠네요. 진지한 웹 개발은 안 한 지 오래라서요.
이 블로그 글은 제안서가 아니고, 제안서에는 당연히 그 내용이 들어 있어요.
https://github.com/WICG/html-in-canvas/#read-back-allowed-rendering
아, 스키아(Skia)처럼 접근성과 텍스트 레이아웃 API를 따로 두고 DOM을 완전히 버릴 수 있으면 얼마나 좋을까요.
맞아요, 바로 그거예요.
저는 얼마 전 이 글에서 HTML-in-Canvas에 대한 우려를 이야기한 적이 있습니다: https://acko.net/blog/html-is-dead-long-live-html/
그 뒤로 이 API를 만든 두 사람을 실제로 만나 보았는데, 결론은 이렇습니다.
겉보기 효과를 넘어서는 용도는 염두에 두고 있지 않았습니다.
광고 회사 소속이라는 사실이 웹 기술을 만들고 구상하는 방식을 어떻게 좌우하는지 잘 이해하지 못합니다.
응원이 아닌 반응에는 꽤 좋지 않게 반응합니다.
곡면 요소는 어떻게 하느냐는 물음에 "평면 투영 변환으로 근사하면 된다"며 얼버무렸습니다. 성숙한 UI 내부 구조를 제대로 노출하려는 진지한 시도가 아니라, 삐걱거리는 괴물 같은 HTML5 웹 API 위에 또 하나 얹은 번지르르한 주전원(epicycle)일 뿐이라는 뜻입니다.
"자동으로 동작한다"는 기능 목록은 사소한 시각 조정에서만 성립하는 가정에 기대고 있습니다. HTML-in-Canvas를 좀 더 기본적인 구성 요소로 쓰려는 순간 그중 상당수가 무너집니다.
예를 들어 글자 한 줄을 렌더링한 다음 그걸 시각 효과의 마스크로 쓴다고 해 보죠. 이때 브라우저가 그 마스크에 텍스트 선택 하이라이트까지 그려 넣으면 글자를 읽을 수 없게 됩니다.
블로그를 여러 번 읽어서 보자마자 알아봤는데, 블로그 헤더가 움직이고 상호작용되는 3D 데모라는 건 이번에 처음 알았네요. 멋져요!
새 API가 저는 헷갈립니다. 캔버스 위에 떠 있는 position:absolute 요소 몇 개를 얹는 것만으로는 안 되는 일이 뭔지 모르겠거든요. 텍스처로 렌더링되니 임의의 시각적 변환을 적용할 수는 있겠죠. 그런데 입력 처리는 사용자가 제어할 수 없다고 하니 도대체 무슨 소용입니까? 요소와 제대로 상호작용할 수도 없을 텐데요. 다른 것들을 제대로 가리는 것(occlusion)도 사실상 안 될 거라고 짐작합니다. 저로서는 말이 안 됩니다.
비교하자면, Win32에는 버튼이나 텍스트 입력 필드 같은 것을 창(= DOM 요소와 비슷한 것)을 만들지 않고도 그릴 수 있는 API가 있습니다. 다만 실제 창 없이 입력 처리를 어디까지 할 수 있는지는 저도 잘 모르겠습니다. 어쨌든 브라우저는 웹 페이지를 대신해 네이티브 컨트롤을 우스꽝스러운 모양으로 비틀어 주는 데 성공했으니, 그쪽 API가 더 많은 가능성을 제공하는 것만은 분명합니다.
HTML 요소에 캔버스를 붙이는 쪽이 더 논리적이지 않을까요? 예를 들면 checkbox.getContext("2d").fillRect(...) 같은 식으로요.
그런 쓸모가 있기야 하겠지만, 웹 게임 개발자인 저한테는 별로 도움이 안 됩니다. 핵심 기능은 입력과 텍스트 렌더링이거든요.
아니면 캔버스 연산을 CSS에 (간접적으로든?) 직접 넣어도 좋겠고요!
속성, 변수,
calc()값으로 채워지는, 채우기/선 페인트가 달린 경로의 목록을 선언해서 그릴 수 있다고 상상해 보세요... 꿈일 뿐이겠지만요.이미 있습니다. 실험적이고 Chromium 전용이긴 하지만요: https://developer.mozilla.org/en-US/docs/Web/API/CSS_Painting_API
네, 그 API는 알고 있습니다. 그런데 제 생각엔(IMHO) 바로 그게 문제예요. 그건 API일 뿐 CSS 자체에 내장된 게 아니라서 JavaScript를 쓸 수밖에 없잖아요.
제가 정말 원하는 건 뭔가 이런 형태입니다...
그리고 네, 이게 보기 흉하다는 건 저도 잘 압니다. 그래도 문자열이나 DOM으로 SVG를 만들어 내거나 캔버스에 그리는 것보다는 이쪽이 낫겠어요.
절대 안 됩니다. 정말로 원한다면 SVG를 데이터 URI로 이미 임베드할 수 있어요(두 배로 고생하고 싶다면 데이터 URI를 출력하는 SCSS로 구현해 볼 수도 있겠죠).
그러려면 JavaScript에서 계산과 레이아웃을 엄청 많이 해야 하잖아요. 저는 그 도형들이 일반 HTML 요소들의 사이, 주변, 뒤에 들어가야 하거든요(게임이랑 에디터를 만들고 있습니다).
그걸 전부 하려면 정말 끔찍하게 고통스러워요. SVG는 CSS나 캔버스로 제가 마음대로 그릴 수 있는 "조각"으로 쓰라고 만든 게 아니니까요.
이번 html-in-canvas API가 그 고통을 조금은 덜어 주겠죠, 적어도요.
캔버스에 그려진 3D 객체의 모양에 HTML이 맞춰져야 한다면 그렇게는 안 됩니다.
말씀하신 건 CSS Painting API(CSS Houdini의 일부)입니다.