WebSquare 화면을 React로.
통과한 코드만 남깁니다.
레거시 UI 현대화 도구 ws2react는 WebSquare(웹스퀘어) 화면 XML을 React(Vite) 코드로 변환하는 로컬 CLI입니다. 규칙 파서가 구조를 뽑고, LLM이 스크립트 로직을 옮기고, 검증 루프(tsc → build → 렌더·시나리오 테스트)가 실패하면 에러를 피드백해 다시 시도합니다. 백엔드(Spring 등)는 한 줄도 바꾸지 않습니다.
무료로 체험하기 — 내 화면 2개 가격 보기어떻게 동작하나
"규칙으로 100%"를 좇던 옛 컨버터가 멈춘 지점 — 화면마다 제각각인 스크립트 로직 — 을 LLM에 맡기고, LLM의 불확실성은 검증 루프가 걸러냅니다. 규칙과 LLM의 역할이 분리돼 있어 결과가 재현 가능합니다.
① 파서 (규칙)
XML → 중간 표현(IR): 데이터 컬렉션, Submission, 컴포넌트 트리, 이벤트 바인딩, 의존성 목록. 결정론적.
② LLM 변환
IR + 런타임 API 명세 + 변환 규약을 프롬프트로. 도구 권한 없이 텍스트만 생성 — 리포지토리를 읽거나 쓰지 못합니다.
③ 검증 루프
tsc → vite build → 렌더 스모크 → 시나리오(클릭·통신 라운드트립) → IR 대조. 실패하면 에러를 피드백해 재시도(기본 3회).
④ 결과
통과본만 output/app/src/screens/에. 한도 내 실패는 수작업 큐로 — 100%를 약속하는 대신, 남은 것은 검증된 것입니다.
Before / After 배포물에 포함된 샘플 sample_side
WebSquare 트리 메뉴 화면과 변환된 React 코드의 앞부분입니다. 컬렉션은 WsDataList, 컴포넌트는 호환 래퍼(WsTreeView)로 옮겨져 원본 스크립트의 호출 형태가 그대로 살아 있습니다.
Before — sample_side.xml (WebSquare)
<w2:dataList id="dlTrvMenu" baseNode="list" repeatNode="map">
<w2:columnInfo>
<w2:column id="name" name="이름" dataType="text"/>
<w2:column id="value" name="값" dataType="text"/>
<w2:column id="dept" name="단계" dataType="text"/>
<w2:column id="url" name="화면Url" dataType="text"/>
</w2:columnInfo>
<w2:data use="true">
<w2:row><name>test 1</name><value>t1</value>
<dept>1</dept><url>/WS/WebSquare.xml</url></w2:row>
...
</w2:data>
</w2:dataList>
<script><![CDATA[
scwin.tv_menu_onclick = function() {
var label = tv_menu.getSelectedLabel();
var value = tv_menu.getSelectedValue();
var url = WebSquare.xml.getValue(
tv_menu.getSelectedElement(), "url");
scwin.setMenuRelation(label, value, url);
};
scwin.setMenuRelation = function(label, value, url) {
var menuList = dlTrvMenu.getMatchedJSON("value", value, true);
if (menuList.length > 0) {
scwin.openMenu(menuList[0].name,
menuList[0].url, menuList[0].value);
}
};
]]></script>After — sample_side.tsx (React, 자동 생성·검증 통과)
import { createRef, useEffect } from 'react';
import { WsDataList, WsTreeView,
type WsTreeViewHandle } from 'ws-react-runtime';
const dlTrvMenu = new WsDataList('dlTrvMenu',
['name', 'value', 'dept', 'url']);
dlTrvMenu.setJSON([
{ name: 'test 1', value: 't1', dept: '1', url: '/WS/WebSquare.xml' },
{ name: 'test 2', value: 't2', dept: '1', url: '/WS/WebSquare1.xml' },
]);
const tv_menu = createRef<WsTreeViewHandle>();
function tv_menu_onclick(): void {
const label = String(tv_menu.current?.getSelectedLabel() ?? '');
const value = String(tv_menu.current?.getSelectedValue() ?? '');
const url = String(
tv_menu.current?.getSelectedRowJSON()?.['url'] ?? '');
setMenuRelation(label, value, url);
}
function setMenuRelation(_label: string, value: string,
_url: string): void {
const menuList = dlTrvMenu.getMatchedJSON('value', value, true);
const first = menuList[0];
if (menuList.length > 0 && first !== undefined) {
openMenu(String(first['name'] ?? ''),
String(first['url'] ?? ''), String(first['value'] ?? ''));
}
}
// ... TODO(manual): 원본 데드코드는 주석으로 보존▶ 시도 1/3: LLM 변환 호출… 응답: claude-opus-5 [claude-cli] (≈ $0.196 API 정가 환산)
✓ typecheck (4.0s) ✓ build (2.9s) ✓ smoke (7.5s)
🎯 변환 성공 | 시도 1회 | 96s — 리포트: output/reports/sample_side_….json
보안 규정이 까다로운 곳을 위해 만들었습니다
소스는 PC 안에
업로드형 웹 서비스가 아닙니다. 파일 읽기·쓰기는 전부 로컬 파이프라인이 합니다.
LLM에는 텍스트만
화면 구조(IR)와 스크립트가 본인 Claude 계정/API 키로 Anthropic에 전송되고, 코드가 텍스트로 돌아옵니다. 모델에 도구 권한이 없습니다.
오프라인 라이선스
라이선스 키는 서명 검증(Ed25519)이라 네트워크·계정 서버가 필요 없습니다. 폐쇄망에서도 동작합니다.
백엔드 무수정
Submission 호환 통신 계층이 기존 API 규약(요청 래핑·응답 봉투)에 맞춥니다. Spring 쪽은 그대로 둡니다.
가격
연간 라이선스. 프로젝트·화면 수 무제한. LLM 비용은 별도(본인 구독이면 0, API 키면 화면당 수백~수천 원)이며 우리는 토큰 마진을 얹지 않습니다. 만료 후에도 도구는 체험 모드로 계속 동작하고, 변환된 코드는 당연히 여러분 것입니다. 결제 후 14일 환불.
5분 체험
zip 하나 — 설치 스크립트가 Node.js·Claude Code 확인/설치, 압축 해제, 의존성 설치, 환경 점검까지 처리합니다.
powershell -ExecutionPolicy Bypass -File .\install-ws2react.ps1 # Windows (macOS/Linux: bash ./install-ws2react.sh) cd %USERPROFILE%\ws2react npx ws2react convert samples/vos-ocean/screens/sample/sample_side.xml npx ws2react report --html --open # Before/After · 검증 루프 타임라인 · 비용
ws2react-0.1.0.zip 다운로드 내 프로젝트 투입 절차(어댑터 부트스트랩 → 이식 → 변환 → 회귀)는 배포물의 docs/getting-started.md
자주 묻는 질문
LLM이 꼭 필요한가요? 토큰 비용이 부담됩니다.
구조(컬렉션·통신·JSX)는 규칙이, 화면마다 다른 스크립트 로직은 LLM이 옮깁니다. 비용은 본인 Claude 구독이면 추가 과금이 없고, API 키를 쓰면 실측 화면당 $0.3~6(대형 화면·재시도에 비례)입니다. 사람이 화면 하나를 옮기는 하루 이틀의 인건비와는 자릿수가 다릅니다.
100% 자동인가요?
아닙니다 — 그래서 믿을 수 있습니다. 검증(tsc·build·렌더·시나리오·IR 대조)을 통과한 화면만 산출물로 남고, 한도 안에 통과하지 못한 화면은 마지막 에러와 함께 수작업 큐에 기록됩니다. 두 업무 시스템 64화면 실측에서는 전부 자동 통과했습니다.
우리 프로젝트의 공통 스크립트(com.*, 팝업, 통신 래퍼)는요?
프로젝트 편차는 엔진이 아니라 어댑터에 담깁니다. bootstrap이 화면이 실제 호출하는 공통 스크립트 표면과 규약을 뽑고, port가 어댑터 모듈을 생성·타입검사합니다. 서버 규약은 운영 캡처로 확정합니다.
그리드 같은 무거운 컴포넌트는?
1:1 매핑 대신 호환 래퍼(외부 API는 WebSquare 스타일, 내부는 React)로 감쌉니다. 편집 그리드·트리·캘린더·탭·팝업·파일첨부가 포함돼 있고, 미지원 항목은 문서에 명시돼 있습니다.
Next.js로도 뽑을 수 있나요?
산출물은 React 컴포넌트 + 런타임이라 프레임워크 중립입니다. 기본 셸은 Vite SPA이며(온프레미스 배포에 가장 단순), Next.js 셸 템플릿은 옵션으로 검토 중입니다.