3시간 만에 스크린샷을 React 코드로 변환하는 생성기 제작
출처: Dev.to
소개
Figma 화면과 UI 스크린샷을 JSX로 변환하는 데 지쳐 버렸습니다. 실제 프론트엔드 작업—라우팅, 상태 관리, 아키텍처 등—에 들어가기 전에 이런 작업을 해야 했거든요. 그래서 자동으로 변환해 주는 도구를 만들었습니다.
스택
- Next.js 14 – 프론트엔드, 분할 패널 UI
- Go – 백엔드, 이미지 압축, SSE 스트리밍
- Claude API (claude‑sonnet‑4‑5) – 비전 + 코드 생성
- Babel Standalone + Tailwind CDN – 빌드 없이 iframe 미리보기
- localStorage – 변환 기록
작동 방식
스크린샷 → Go (압축 + 리사이즈) → Claude Vision (스트리밍) → SSE → Next.js → iframe 미리보기
- Go 백엔드가 이미지를 5 MB 이하로 압축하고 base64‑인코딩한 뒤 Claude API에 스트리밍 연결을 엽니다.
- 각 텍스트 델타가 JSON SSE 이벤트로 브라우저에 전달됩니다. 예시:
data: {"delta":"import"}
data: {"delta":" React from 'react';"}
- 프론트엔드가 스트림을 하나의 코드 문자열로 누적합니다.
- 생성이 끝나면
document.write()를 통해 iframe에 코드를 삽입합니다.- React, Babel, Tailwind는 CDN에서 로드됩니다.
- 빌드 단계 없이 즉시 컴포넌트가 렌더링됩니다.
문제점들
청크 연결
Claude는 토큰을 스트리밍하므로 import와 React가 별도의 이벤트로 도착할 수 있습니다. 단순히 이어 붙이면 importReact from 'react'와 같이 Babel이 거부하는 코드가 됩니다.
해결: Go 측에서 각 델타를 JSON 객체로 감싸고 프론트엔드에서는 obj.delta를 읽어 연결합니다. JSON은 공백을 정확히 보존합니다.
iframe 내 import 문
iframe이 이미 CDN을 통해 React를 로드하고 있습니다. 생성된 코드에 import React from 'react'가 포함되면 Babel이 오류를 발생시킵니다.
해결: 모든 import 문을 제거하고 기본 내보내기를 교체한 뒤 삽입합니다.
const clean = code
.replace(/^import\s+[\s\S]*?from\s+['"][^'"]*['"];?\s*$/gm, "")
.replace(/^export\s+default\s+/m, "const __Component__ = ")
.trim();
이미지 미디어 타입 불일치
.png 형식으로 저장된 스크린샷에 JPEG 바이트가 들어 있는 경우가 있어 Claude가 타입 불일치를 거부합니다.
해결: Go 압축기가 항상 JPEG를 출력하므로 입력 형식과 관계없이 선언된 미디어 타입을 image/jpeg로 고정합니다.
정상 작동하는 프롬프트
- Tailwind 유틸리티 클래스만 사용—인라인 스타일 금지.
- 현실적인 플레이스홀더 텍스트 사용, Lorem Ipsum 금지.
- 모바일 퍼스트 반응형 클래스를 포함.
- 인터랙티브 요소에 hover와 focus 상태 추가.
- 컴포넌트 코드만 반환, 마크다운 코드 블록은 제외 – Claude가 삼중 백틱으로 감싸면 Babel이 오류를 일으킵니다.
실제 출력물
이 도구는 미리보기 iframe에서 바로 렌더링할 수 있는 독립형 React 컴포넌트를 출력합니다. 추가 props가 필요 없으며 스타일링은 전부 Tailwind 유틸리티에 의존합니다.
저장소
github.com/norbertose/screenshot-figma-to-react
스택: Next.js · Go · Claude API. 클론한 뒤 ANTHROPIC_API_KEY를 교체하고 실행하면 됩니다. $5 구독은 아직 활성 상태입니다.