Porting the Moebius 0.2B image inpainting model to run in the browser with Claude Code
가벼운 이미지 인페인팅 모델인 Moebius 0.2B를 Claude Code를 활용해 브라우저(WebGPU)에서 직접 구동하도록 포팅한 흥미로운 여정을 소개합니다. 코드를 직접 한 줄도 작성하지 않고도 PyTorch

가벼운 이미지 인페인팅 모델인 Moebius 0.2B를 Claude Code를 활용해 브라우저(WebGPU)에서 직접 구동하도록 포팅한 흥미로운 여정을 소개합니다. 코드를 직접 한 줄도 작성하지 않고도 PyTorch 모델을 ONNX로 변환하고 브라우저 캐싱까지 적용해 낸 생생한 '바이브 코딩' 개발기를 만나보세요.
가볍지만 강력한 인페인팅 모델, Moebius의 발견
어느 날 아침, 해커뉴스에서 Moebius: 10B급 성능을 내는 0.2B 초경량 이미지 인페인팅 프레임워크라는 흥미로운 글을 발견했어요. 인페인팅(Inpainting)이란 이미지에서 지우고 싶은 영역을 마킹하면 AI가 그 자리를 자연스럽게 채워주는 기술을 말해요.
공개된 Moebius 모델은 원래 PyTorch와 NVIDIA CUDA 환경을 요구했어요. 하지만 크기가 0.2B(약 2억 개의 매개변수)로 매우 가벼운 수준이었기 때문에, 브라우저에서 WebGPU를 이용해 구동할 수 있겠다는 생각이 번뜩 들었습니다. 결론부터 말씀드리면 성공적으로 구현해 냈으며, 여러분도 simonw.github.io/moebius-web/에서 데모를 직접 체험해 보실 수 있어요.
완성된 도구의 모습
데모 페이지에 접속하면 어떤 이미지든 불러올 수 있으며(정사각형이 아닌 이미지는 레터박스 처리됩니다), 지우고 싶은 영역을 하이라이트한 뒤 "Run inpaint" 버튼을 누르면 모델이 마법처럼 빈 공간을 채워줍니다.
메인 프로젝트의 틈새를 공략한 '병렬 에이전트 프로젝트'
사실 이날 저의 메인 프로젝트는 데이터셋(Datasette) 테이블 생성 및 수정 UI를 만드는 까다로운 작업이었어요. 코드 리팩토링이나 UI 마무리를 위해 에이전트(Codex Desktop)를 실행해 두고 결과를 기다리는 동안, 종종 5~10분씩 시간이 뜨곤 했습니다. 코딩 에이전트가 무거운 연산을 처리하는 대기 시간 동안 멍하니 기다리기보다는, 터미널 창에 Claude Code를 하나 더 띄워서 Moebius 모델을 웹으로 포팅하는 서브 프로젝트를 병렬로 진행해 보기로 했습니다.
Claude와의 사전 탐색 및 연구
먼저 깃허브 저장소를 직접 클론해 분석할 수 있는 Claude.ai 웹 인터페이스를 이용해 프로젝트의 실현 가능성을 물어보았습니다.
질문 1: "https://github.com/hustvl/Moebius/ 를 클론하고, 이 모델을 실행하기 위한 코드와 가중치(weights)가 어디에 공개되어 있는지 알려줘." (모델 가중치 링크는 소식 섹션 구석에 숨겨져 있었는데, Claude가 금방 찾아내더군요.)
질문 2: "Moebius를 지금 바로 실행하려면 파이썬과 NVIDIA CUDA 환경만 가능한가요? 아니면 다른 옵션도 있나요?"
질문 3: "이 모델을 Transformers.js나 유사한 라이브러리로 변환해서 브라우저에서 실행하는 방안에 대해 자유롭게 고찰(Muse)해 줘."
여기서 "~에 대해 자유롭게 고찰해 줘(Muse on X)"라는 프롬프트는 구체적인 목표를 지정하지 않고 AI가 문제를 다각도로 숙고하도록 만들 때 제가 자주 쓰는 아주 유용한 팁이랍니다. Claude는 WebGPU 백엔드 기반의 ONNX Runtime Web을 사용할 것을 제안했고, 저는 충분히 도전해 볼 가치가 있다고 판단하여 본격적으로 Claude Code를 작동시켰습니다.
개발을 시작하기에 앞서 필요한 소스코드와 데이터들을 /tmp 폴더 아래에 미리 모아두었습니다.
cd /tmp
mkdir Moebius
cd Moebius
# Moebius 파이썬 코드 가져오기
git clone https://github.com/hustvl/Moebius
# 모델 가중치 가져오기
GIT_LFS_SKIP_SMUDGE=0 git clone https://huggingface.co/hustvl/Moebius Moebius-weights
# 참고할 라이브러리들
git clone https://github.com/huggingface/transformers.js
git clone https://github.com/microsoft/onnxruntimeClaude Code 가동하기
이제 웹 앱 코드가 들어갈 폴더를 만들고 깃을 초기화한 뒤, 앞서 웹 Claude와 대화하며 정리해 둔 리서치 노트를 research.md 파일로 저장했습니다.
mkdir /tmp/Moebius/moebius-web
cd /tmp/Moebius/moebius-web
git init
git add research.md
git commit -m "Initial research by Claude Opus 4.8"그런 다음 폴더 상위 경로에서 Claude Code를 실행하고 다음과 같이 프롬프트를 보냈습니다.
"./moebius-web/research.md를 읽고 시작해 줘. 네 목표는 이 모델을 ONNX와 WebGPU로 포팅해서 간단한 UI와 함께 브라우저에서 직접 실행할 수 있도록 만드는 거야."
여기에 한 가지 팁을 덧붙였습니다.
"/tmp/Moebius/moebius-web 폴더 안에 작업물을 만들어 주고, 커밋을 자주 진행해 줘. 그리고 작업하면서 알게 된 내용들을 기록하는notes.md파일과, 앞으로의 계획을 담은plan.md파일을 작성하고 수시로 업데이트해 줘."
Claude Code가 작동하는 동안 저는 다시 제 메인 작업으로 돌아갔고, 가끔 터미널을 확인하며 진행 상황을 지켜보았습니다. 어느 정도 구동 가능한 형태가 완성되었을 때, 테스트해 볼 수 있는 로컬 URL을 알려달라고 요청했고 브라우저에서 실행하면서 생긴 오류 메시지와 화면 캡처본을 다시 Claude에게 피드백으로 전달했습니다. 몇 번의 디버깅 과정을 거치자 마침내 정상 작동하는 모습을 확인할 수 있었습니다!
| 개발 단계 | 주요 작업 내용 | 활용한 도구 및 리소스 |
|---|---|---|
| 1. 준비 & 분석 | 모델 구조 분석 및 타당성 검토 | Claude.ai, GitHub Repo |
| 2. 로컬 환경 구성 | 가중치(LFS) 다운로드 및 참고 라이브러리 클론 | Git, Hugging Face |
| 3. 포팅 및 최적화 | PyTorch 모델의 ONNX 변환 및 WebGPU 연결 | Claude Code, ONNX Runtime Web |
| 4. 웹 배포 및 캐싱 | 배포 자동화 및 재다운로드 방지 최적화 | Hugging Face, Service Worker, GitHub Pages |
Hugging Face 배포와 캐싱 문제 해결하기
로컬에서 작동하는 것을 확인했으니 이제 세상에 공개할 차례였습니다. 저는 Claude에게 Hugging Face Spaces에 데모를 올리고 모델 가중치를 호스팅할 방법을 물었습니다. Claude Code는 Hugging Face CLI를 다룰 줄 알기 때문에, 제가 쓰기 권한이 있는 토큰을 전달해 주자 약 1.24GB에 달하는 변환된 ONNX 가중치를 제 Hugging Face 저장소(huggingface.co/simonw/Moebius-ONNX)로 알아서 척척 업로드해 주었습니다.
웹 프론트엔드는 제 개인 GitHub Pages로 호스팅하기로 하고, 경로 처리가 꼬이지 않도록 배포될 URL(https://simonw.github.io/moebius-web/)을 Claude에게 정확히 알려주며 코드를 수정하도록 유도했습니다.
치명적인 문제: 매번 1.3GB씩 다운로드되는 현상
배포는 성공적이었지만, 페이지를 새로고침할 때마다 1.3GB에 달하는 가중치 파일을 매번 다시 다운로드하는 치명적인 문제가 있었습니다. 브라우저 캐싱이 필수적이었습니다.
저는 Transformers.js 기반 프로젝트들이 캐싱을 어떻게 처리하는지 파악하기 위해, 오픈소스 Whisper 웹 데모 프로젝트를 복제해 와서 Claude의 서브에이전트에게 분석을 시켰습니다.
"/tmp/Moebius/whisper-web 폴더 안을 서브에이전트로 살펴보고, 가중치 캐싱을 어떻게 구현했는지 분석해 줘."
서브에이전트를 활용한 덕분에 메인 컨텍스트 토큰을 낭비하지 않고도 유용한 정보를 빠르게 얻어낼 수 있었습니다. Claude는 해당 프로젝트가 브라우저의 CacheStorage API(caches.open("transformers-cache"))를 사용한다는 사실을 밝혀냈고, 저희 프로젝트에도 이를 성공적으로 이식해 주었습니다.
이번 여정을 통해 배운 점
이번 프로젝트는 완벽한 바이브 코딩(Vibe Coding)의 전형이었습니다. 저는 프로젝트가 진행되는 동안 실제 코드를 단 한 줄도 직접 들여다보지 않았습니다. 오직 테스트하고, 다운로드 진행률 표시바 같은 개선 아이디어를 제안하고, 작동 방식을 가이드하는 역할만 수행했습니다.
그만큼 WebGPU나 ONNX의 내부 기술을 깊이 공부하진 못했지만, 대신 '무엇이 가능한지'에 대한 아주 값진 통찰을 얻을 수 있었습니다.
- Claude Opus 4.8은 스스로 PyTorch 모델을 ONNX로 변환하고, 그 결과를 Hugging Face에 업로드하며, 이를 로드해 실행하는 웹 인터페이스까지 원스톱으로 빌드해 낼 수 있습니다.
- 현재 크롬, 파이어폭스, 사파리 모든 브라우저가 이러한 로컬 WebGPU 모델을 지원합니다.
- CacheStorage API는 1.3GB가 넘는 거대한 모델 파일도 안정적으로 캐싱해 줍니다.
- 결과적으로, 사용자가 최초 1.3GB의 다운로드 장벽만 감당할 수 있다면 완벽히 클라이언트 측에서만 동작하는 무거운 AI 인페인팅 웹 앱을 서비스할 수 있습니다.
ONNX와 모델 변환 과정 깊이 이해하기
작업이 끝난 후 저도 기술적 배경을 조금 더 이해하고 싶어 Claude.ai에게 제가 완성한 깃허브 저장소를 분석해 강의를 해달라고 요청했습니다. 특히 ONNX에 관한 설명이 무척 명쾌했습니다.
ONNX(Open Neural Network Exchange)는 프레임워크에 독립적인 이식성 높은 신경망 파일 포맷입니다. .onnx 파일은 크게 두 가지 요소가 결합한 형태입니다. 1. 연산 그래프(Computation Graph): 노드로 연결된 방향성 그래프로, 각 노드는 텐서들이 흘러가며 수행하는 연산(Conv, MatMul, Add, Softmax 등)의 '레시피' 역할을 합니다. 2. 가중치(Weights): 그래프 내부에 이니셜라이저로 저장된 학습된 매개변수 값들입니다. ONNX는 하드웨어가 무엇인지 상관없이 '무엇을 연산해야 하는가'를 추상적으로 묘사합니다.실제 파이썬 코드 내에서 PyTorch의 빌트인 메커니즘을 사용해 ONNX로 내보내는 핵심 코드는 다음과 같이 작성되어 있었습니다.
torch.onnx.export(
dec,
(lat,),
dec_path,
opset_version=args.opset,
input_names=["latent"],
output_names=["image"],
dynamic_axes={"latent": {0: "B"}, "image": {0: "B"}},
)에이전트 기술이 발전하면서 이제 아이디어만 있다면 복잡한 하위 수준의 기술 명세를 직접 다 파헤치지 않고도, 단 몇 시간 만에 브라우저에서 돌아가는 고성능 AI 도구를 뚝딱 만들어낼 수 있는 시대가 되었습니다. 여러분도 일상적인 업무 대기 시간을 활용해 재미있는 AI 사이드 프로젝트에 도전해 보세요!
아직 이 아티클로 만든 공식이 없어요. 첫 번째 공식을 남겨보세요!
나도 공식 만들기
댓글
6댓글을 남기려면 로그인이 필요해요.
0.2B 규모의 경량 인페인팅 모델임에도 불구하고 ONNX 변환 파일의 용량이 1.3GB에 달해 브라우저 환경에서의 실용성에 의문이 듭니다. 게다가 PyTorch 코드를 ONNX(opset 18)로 변환하는 과정에서 원본 모델의 추론 성능이나 정밀도가 정량적으로 얼마나 유지되었는지에 대한 검증 데이터가 부족해 보입니다. 브라우저의 WebGPU 백엔드가 아직 과도기인 상황에서, 이식된 모델이 다양한 기기에서 원래의 성능을 온전히 발휘할 수 있을까요?
작성자가 코드 한 줄 직접 보지 않는 '바이브 코딩'으로 프로젝트를 진행했기 때문에, 아쉽게도 ONNX 변환 과정에서의 정밀도 저하나 정량적 성능 분석 데이터는 본문에 제시되어 있지 않아요. 다만 Chrome, Firefox, Safari 브라우저에서 모두 실제로 작동함을 검증했다는 점에 의의가 있습니다. WebGPU 환경에서의 구체적인 기기별 최적화 수준이나 한계점에 대해서는 추가적인 벤치마크 연구가 필요한 상황이에요.
서버 GPU 비용 부담 없이 클라이언트 환경에서 직접 인페인팅을 실행할 수 있는 점은 운영 비용 면에서 획기적입니다. 다만 아무리 CacheStorage API로 브라우저 캐싱을 처리하더라도 최초 실행 시 1.3GB에 달하는 모델 가중치를 받아야 하므로 네트워크 트래픽 비용과 다운로드 대기 시간이 발생하네요. 사용자 기기의 WebGPU 연산 능력에 의존하는 방식이 실제 대규모 트래픽 환경에서 API 호출 방식보다 정말 효율적일지 궁금한데, 이에 대해 어떻게 생각하시나요?
지적해 주신 대로 최초 실행 시 1.3GB에 달하는 대용량 모델 가중치를 다운로드해야 하는 네트워크 트래픽과 대기 시간 부담이 존재해요. 비록 CacheStorage API를 도입해 두 번째 실행부터는 캐시를 활용해 재다운로드를 방지하지만, 초기 허들은 여전히 존재합니다. 따라서 사용자가 첫 다운로드를 감내할 수 있는 서비스 시나리오인지와 비싼 GPU 서버 운영 비용 중 어느 쪽이 더 이득일지 비교해 보셔야 해요.
Claude Code와 에이전트를 활용해 PyTorch 모델을 웹 브라우저용 ONNX와 WebGPU 환경으로 포팅한 과정이 정말 흥미롭네요. 개발자가 코드 한 줄 직접 쓰지 않는 '바이브 코딩'만으로도 복잡한 캐싱 설계와 Hugging Face 배포까지 성공했다는 점이 놀랍습니다. 우리도 사내에서 활용 중인 경량 딥러닝 모델들을 이와 같은 방식으로 웹 애플리케이션에 직접 이식해 보면 어떨까요? 여러분은 어떤 모델을 브라우저에 가장 먼저 올려보고 싶으신가요?
Claude Code를 활용하면 PyTorch 내장 함수인 torch.onnx.export를 사용하는 복잡한 변환 과정을 에이전트에게 전적으로 맡길 수 있어요. 이번 실험을 통해 Chrome, Firefox, Safari 브라우저 모두에서 WebGPU를 통한 실행이 가능하다는 점이 확인되었습니다. 사내에 보유 중인 0.2B 규모 이하의 가벼운 모델이 있다면, 이와 같은 방식으로 브라우저 구동 가능성을 먼저 타진해 보시는 것을 추천해요.