마이크로소프트가 2007년 개발을 중단한 이후 비주얼 폭스프로(Visual FoxPro)는 버전 9, 그리고 32비트에서 시간이 멈췄다. 그러나 이 언어로 쓰인 업무용 애플리케이션은 여전히 적지 않은 조직에서 돌아가고 있고, 손대기 어려운 채로 유지되는 경우가 많다. 최근 공개된 폭스스크립트(FoxScript) 프로젝트와 그 통합개발환경인 폭스데브 스튜디오(FoxDev Studio)는 이 오래된 언어를 그대로 살려두되, 2007년에 얼어붙은 토대만 현대적인 것으로 바꾸겠다는 접근을 내세운다. 일렉트론(Electron)과 리액트(React)로 화면을 그리고, 러스트(Rust)로 작성해 웹어셈블리(WebAssembly)로 컴파일한 가상머신이 코드를 실행한다.
다시 쓰지 않고 그대로 여는 방식
이 도구가 강조하는 첫 번째 특징은 '변환 없음'이다. 수년간 열지 않았던 폴더를 가리키면 그 안에 있는 프로젝트, 폼, 클래스 라이브러리, 메뉴, 리포트가 마이그레이션 절차 없이 기존 파일에서 바로 열린다. 테이블, 인덱스, 메모, 데이터베이스는 원래 자리에서 읽고 쓰며, 작업이 끝난 뒤 디스크에 남는 파일도 이전과 같은 종류의 파일이다. 프로젝트 매니저, 커맨드 윈도우, 사용자가 지정한 줄에서 멈추는 디버거 같은 익숙한 구성요소도 예상하던 위치에 그대로 놓여 있다. 기존 애플리케이션이 의존하던 시스템 호출, 자동화 객체, 오래된 애드인 라이브러리도 계속 작동하도록 설계했다는 점이 핵심이다. 낡은 코드를 다시 쓰지 않아도 되는 것이 이 프로젝트의 존재 이유인 셈이다.
오래된 애플리케이션을 망가뜨리는 것은 대개 큰 변화가 아니라 사소한 차이다. 숫자가 한 칸 넓게 인쇄되거나, 이벤트가 한 박자 늦게 도착하거나, 오류 번호가 어긋나는 식이다. 그래서 이 런타임은 참고 문서를 읽고 동작을 추정하는 대신, 비주얼 폭스프로 자체에 직접 물어보고 그 답과 일치시키는 방식으로 동작을 결정했다고 설명한다. 그 결과 처음부터 새로 작성한 런타임은 시작이 빠르고 자체 완결적이며, 아직 도달하지 못한 부분에 대해서는 솔직하게 밝힌다고 덧붙인다.
32비트의 벽을 넘는다는 것
비주얼 폭스프로가 32비트 프로그램이라는 사실은 겉보기보다 많은 것을 결정한다. 테이블이 2기가바이트에서 멈추고, 메모 파일도 같은 한계에 걸리며, 여유 있는 메모리를 가진 컴퓨터에서도 큰 리포트가 메모리 부족으로 실패하는 이유가 여기에 있다. 이는 누군가 정한 라이선스 정책이 아니라 파일 처리 로직 깊숙이 박힌 부호 있는 32비트 정수의 한계다. 폭스데브 스튜디오는 전 구간이 64비트로, 모든 파일 오프셋이 64비트이며 테이블을 통째로 메모리에 올리지 않기 때문에 같은 .dbf 파일이 수백 기가바이트까지 커질 수 있다.
다만 여기에는 실무자가 반드시 알아야 할 단서가 붙는다. 2기가바이트를 넘어 커진 테이블은 원래의 비주얼 폭스프로에서 다시 열리지 않는다. 두 환경을 오가며 작업하는 조직이라면 이는 되돌릴 수 없는 일방통행 문이다. 마이그레이션 없이 병행 운영이 가능하다는 장점이 무색해질 수 있는 지점이므로, 대용량 테이블로의 확장은 신중하게 결정해야 한다.
러스트 VM과 파이버, 그리고 32비트 라이브러리 다리
실행 구조는 원래의 방식을 다시 만든 것이다. 러스트로 작성해 웹어셈블리로 컴파일한 컴파일러와 바이트코드 인터프리터가 p-code 실행 역할을 대신하므로, 애플리케이션이 어디서 돌든 같은 기계가 코드를 실행한다. 에디터가 입력을 검사할 때도 바로 그 컴파일러를 거치기 때문에, 에디터가 밑줄 긋는 것과 런타임이 거부하는 것이 서로 어긋날 수 없다. 실행 중인 프로그램은 파이버(fiber)로 다뤄져, 메시지 박스나 모달 폼, 다음 레코드가 필요할 때 블로킹으로 호출하는 대신 양보(yield)하고 결과를 넘겨받는다. 덕분에 MESSAGEBOX()가 뒤 창을 얼리지 않고 프로그램을 멈추며, READ EVENTS가 스핀 없이 대기하고, GotFocus나 Init 같은 이벤트가 폭스프로가 늘 하던 순서대로 발생한다. 화면은 객체 트리에서 리액트가 직접 그리는데, 각 객체가 자기 자신만 감시하므로 라벨 하나의 Caption을 바꾸면 폼 전체가 아니라 그 라벨만 다시 그려진다. 디자이너도 같은 트리를 편집하므로 폼과 디자이너가 서로 다른 이야기를 하기 시작하는 흔한 문제가 생기지 않는다.
64비트 애플리케이션 안에서 32비트 이미지인 .fll 라이브러리를 여는 것은 원리적으로 불가능하다. 이를 두고 불가능하다고만 말하는 대신, SET LIBRARY TO는 라이브러리만 붙들고 있는 작은 32비트 프로세스를 띄우고 런타임이 그와 통신한다. 표현식을 계산하는 도중에 라이브러리를 호출할 수 있기 때문에 이 호출은 동기식이다. 암호화 라이브러리, FoxTools, 마이크로소프트의 API 샘플로 만든 라이브러리 등 실제 라이브러리로 검증했다고 한다. 반면 DECLARE ... DLL로 현대적 라이브러리를 같은 프로세스에서 부르거나 자동화 객체를 예전처럼 다루는 64비트 경로에는 이 다리가 필요 없다.
언어를 바꾸지 않는 확장, 그리고 남은 과제
폭스스크립트가 기존 문법 위에 더하는 것은 두 가지다. 나중에 다른 곳에 넘겨 실행할 수 있는 블록(람다)과, 업무 로직을 이미 아는 코드에서 웹 요청에 응답하는 방법이다. 이 모든 것이 폼과 같은 런타임 위에서 돌아가며, 쿼리·커서·라이브러리 호출은 평범한 폭스프로 그대로다. 별도의 언어나 옆에 세워야 할 서비스가 없다는 점을 강조한다. 배포 측면에서 나이틀리 빌드는 main 브랜치에 대한 모든 푸시마다 다시 만들어져 깃허브에 사전 릴리스로 게시되며, 서명되지 않은 상태라 첫 실행 시 확인을 요구한다. 프로젝트 측은 아직 도달하지 못한 부분을 포함해 제품의 각 부분을 문서로 기록했고, 앞으로 만들 작업도 대략적인 순서로 공개하고 있다. 결국 이 프로젝트의 가치는 완성도라기보다, 단종된 언어의 자산을 그대로 유지하면서 32비트와 2007년이라는 두 개의 천장을 걷어내려는 구체적 설계에 있다. 실전 도입을 검토하는 실무자라면 대용량 테이블의 비가역성, 서명되지 않은 빌드, 그리고 아직 채워지지 않았다고 명시된 영역을 함께 저울질할 필요가 있다.