2025년 4월 4일 금요일

Gradio HTML Javascript 렌더링 방법

이 글은 Gradio HTML Javascript 렌더링 방법을 간략히 정리한다. 가끔, HTML, javascript(자바스크립트)를 Gradio 페이지에 표시하고 싶을 때가 있다. 예를 들어, Gradio 기존 컴포넌트에서 지원되지 않는 3D 그래픽을 렌더링해야 할 때가 있다.
Gradio 3차원 모델 렌더링 예시

하지만, Gradio는 HTML만 지원하고, javascript는 다양한 이유로 사용자가 직접 Gradio에서 실행하는 것을 허용하지 않는다. 이 경우, iframe 을 사용한다.
Gradio에서 three.js 코드 실행 예시

다음은 Gradio에서 3D graphic 렌더링을 위해 three.js를 사용하는 예를 보여준다.
import os, json, requests, gradio as gr
from gradio import Interface, File, Files, Button, Label, Markdown

class 3D_viewer_component:
    def __init__(self, gr):
        self.html_code = """
<iframe srcdoc="
<!DOCTYPE html>
<html>
  <head>
    <style>
      body, html { margin: 0; overflow: hidden; height: 100%; }
      canvas { display: block; }
    </style>
    <script src='https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js'></script>
  </head>
  <body>
    <script>
const WIDTH = window.innerWidth;
const HEIGHT = window.innerHeight;

const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(WIDTH, HEIGHT);
renderer.setClearColor(0x111111, 1);
document.body.appendChild(renderer.domElement);

const scene = new THREE.Scene();

const camera = new THREE.PerspectiveCamera(70, WIDTH / HEIGHT, 0.1, 10000);
camera.position.z = 30;
camera.position.y = 10;
scene.add(camera);

const boxGeometry = new THREE.BoxGeometry(10, 10, 10);
const basicMaterial = new THREE.MeshBasicMaterial({ color: 0x0095dd });
const cube = new THREE.Mesh(boxGeometry, basicMaterial);
cube.position.x = -25;
cube.rotation.set(0.4, 0.2, 0);
scene.add(cube);

const torusGeometry = new THREE.TorusGeometry(7, 1, 16, 32);
const phongMaterial = new THREE.MeshPhongMaterial({ color: 0xff9500 });
const torus = new THREE.Mesh(torusGeometry, phongMaterial);
torus.rotation.set(0.5, 0.5, 0);
scene.add(torus);

const light = new THREE.PointLight(0xffffff);
light.position.set(-10, 15, 50);
scene.add(light);

let t = 0;
function render() {
  t += 0.01;
  requestAnimationFrame(render);
  cube.rotation.y += 0.01;
  torus.scale.y = Math.abs(Math.sin(t));
  renderer.render(scene, camera);
}
render();
    </script>
  </body>
</html>
" width="100%" height="100%" style="border:none;"></iframe>
        """

        self.component = gr.HTML(self.html_code)

with gr.Blocks(title='3D viewer') as interface:
gr.Markdown("# 3D viewer")
with gr.Row(equal_height=True):
3D_viewer_component(gr)
3D_viewer_component(gr)

interface.launch(share=True)

참고로, Gradio에서 공식적으로 추천하는 방법은 다음과 같이 커스텀 컴포넌트를 개발한 것이다.
커스텀 컴포넌트 생성 명령 예시
명령 실행 순서(일부)

위 그림과 같이 컴포넌트 생성하면, 다음처럼 프로젝트 파일이 생성되고, 이를 수정해 개발하는 방식이다.
- backend/ <- The python code for your custom component
- frontend/ <- The javascript code for your custom component
- demo/     <- A sample app using your component. Modify this!
- pyproject.toml <- Used to build the package and specify package metadata.
Gradio 커스텀 컴포넌트 예시(Gradio Custom Components Gallery)

이외 3차원 모델 파일 뷰어는 Model3D 컴포넌트를 사용할 수도 있다.
Model3D 예시

레퍼런스