
20년 전 VB6 앱을 설치 프로그램 없이 실행하는 방법: 'AI 시대의 소프트웨어 수명 연장술?'
요약
레거시 VB6 앱을 설치 프로그램 없이 실행 가능한 포터블(Portable) 구성으로 전환하는 방법을 다룹니다. Registration-Free COM 기술을 활용하여 OCX 의존성 문제를 해결하고, 레지스트리 등록 없이도 동작하는 배포 전략을 제시합니다.
핵심 포인트
- Registration-Free COM을 활용한 포터블 구성 가능
- OCX 및 매니페스트 파일의 정합성 확보가 핵심
- VB6 프로젝트 파일(.vbp)을 통한 의존성 파악 필요
- 레지스트리 등록 없이 폴더 복사만으로 실행 환경 구축

"이 앱, 폴더를 복사하는 것만으로 실행할 수 없을까?"
오래된 Windows 앱을 현대적인 배포 환경으로 가져가려 하면, 높은 확률로 이 질문에 부딪히게 된다.
이번에 다룬 것은 OCX에 의존하는 32bit VB6 제작 데스크톱 앱이다.
개발 환경에서는 정상적으로 동작한다. 하지만 다른 PC로 EXE 파일만 가져가면, OCX를 찾을 수 없다거나, COM 컴포넌트를 생성할 수 없다거나, 관리자 권한을 요구하는 등—그런 "오래된 앱의 흔한 문제"들이 차례로 나타난다.
그래서 Codex와 함께, 설치 프로그램(Installer), regsvr32, 레지스트리 등록을 전제로 하지 않는 포터블(Portable) 구성으로 다시 만들었다.
이 기사에서는 특정 개인·조직·제품을 식별할 수 있는 정보나 실제 작업 경로, 내부 파일 이름의 일부를 일반화하였다. 대신, 다른 VB6 앱에도 응용할 수 있는 사고방식과 절차에 집중하여 정리한다.
먼저 결론부터: VB6+OCX라도 포터블화는 가능하다
조건이 갖춰지면, OCX를 사용하는 VB6 앱이라도 폴더 전체를 복사하는 것만으로 동작하는 구성으로 만들 수 있다.
이번에 도달한 결과물은 다음과 같다.
PortableApp/
LegacyApp.exe
MSCOMCTL.OCX
...
사용자는 외부 설치 프로그램을 실행하지 않는다. regsvr32도 사용하지 않는다. Program Files에 배치하거나 시스템 전체에 COM을 등록하는 것도 전제로 하지 않는다.
실현의 핵심이 된 것은 Registration-Free COM, 이른바 "reg-free COM"이다.
단, OCX와 매니페스트(manifest)를 같은 폴더에 넣기만 하면 완성되는 마법은 아니다.
실제 OCX에서 의존성 정보를 조사하고, 기존 매니페스트와 정합성을 맞추며, 쓰기 대상과 UAC 설정을 재검토한 뒤, 마지막으로 "아무것도 설치되지 않은 Windows"에서 동작 확인을 할 필요가 있다.
왜 오래된 VB6 앱은 그대로 복사해도 동작하지 않는가
VB6 앱은 다음과 같은 ActiveX 컨트롤에 의존하는 경우가 있다.
MSCOMCTL.OCX
COMDLG32.OCX
일반적인 설치 프로그램은 이것들을 지정된 장소로 복사하고, COM 정보를 Windows 레지스트리에 등록한다.
개발 PC나 과거에 설치 프로그램을 실행했던 PC에서는 그 준비가 이미 완료되어 있다. 그렇기 때문에 EXE가 단독으로 동작하는 것처럼 보일 뿐이다.
하지만 클린한 PC에서는 Windows가 "이 CLSID의 컴포넌트가 어디에 있는지" 알지 못한다.
즉, 문제는 OCX 파일이 존재하는지 여부만이 아니다. COM 클래스, TypeLib, ProgID, 버전, 의존 DLL 등을 앱이 올바르게 해결(resolve)할 수 있어야 한다.
가장 먼저 할 일은 "의존 관계 파악"
첫 번째 재료는 VB6 프로젝트 파일인 .vbp이다.
.vbp에는 참조하고 있는 OCX나 모듈이 기록되어 있다.
Object={<OCX_GUID>}#<TYPELIB_VERSION>#0; MSCOMCTL.OCX
Object={<OCX_GUID>}#<TYPELIB_VERSION>#0; COMDLG32.OCX
여기서는 구체적인 GUID나 버전은 생략하였다. 인터넷상의 값을 그대로 붙여넣지 말고, 반드시 자신이 실제로 동봉할 OCX와 대상 프로젝트의 정보를 확인하기 바란다.
또한, .vbp만으로는 부족한 경우가 있다.
오래된 설치 프로그램 설정에는 VB6 런타임(Runtime), 언어 리소스 DLL, 앱 소재, 도움말, 샘플 데이터 등 프로젝트 파일에서는 보이지 않는 의존물들이 기록되어 있을 수 있다.
이번에는 다음 정보들을 대조하였다.
- VB6 프로젝트 파일
- 기존 설치 프로그램 설정
- 정상 작동 중인 PC의 파일 구성
- 실제로 로드되고 있는 OCX와 DLL
- Windows Sandbox에서의 부족한 파일 및 에러
오래된 설치 프로그램은 버려야 할 대상이 아니었다. 오히려 "과거에 올바르게 배포했던 파일 목록"이라는 귀중한 설계 자료였다.
기존 폴더에서 깎아내지 말고, 새로운 폴더로 모으기
기존 개발 폴더에서 불필요한 파일을 깎아내어 배포용으로 정리하고 싶어질 수 있다.
이것은 상당히 위험하다.
오랫동안 사용된 폴더에는 메모, 과거 버전, 백업, 검증 이미지, 임시 파일, 사내용 자료 등이 섞여 있다. 실수로 공개물에 포함하면 정보 유출이 되고, 반대로 필요한 파일을 지우면 앱이 동작하지 않게 된다.
그래서 이번에는 깎아내는 방식을 포기했다.
old_work_folder/ ← 오랜 세월의 퇴적물이 쌓여 있음
portable_build_clean/ ← 비어 있는 신규 폴더
기존 인스톨러(Installer)에 포함된 정규 파일 목록을 화이트리스트(Whitelist)로 사용하여, 비어 있는 portable_build_clean 폴더로 필요한 것만 복사한다.
이 방식이라면 "무엇을 지웠는가"가 아니라 "무엇을 넣었는가"를 설명할 수 있다. 재현성(Reproducibility)과 감사성(Auditability)이 높으며, 사고가 상당히 줄어든다.
이 작업에서 가장 효과적이었던 방침은 다음의 한 문장이었다.
기존 폴더에서 불필요한 파일을 깎아내는 것이 아니라, 인스톨러 설정에 포함된 정규 파일 목록을 기반으로 비어 있는 폴더에 필요 파일만 복사한다.
단순하지만 강력하다.
Reg-free COM으로 레지스트리 등록을 중단하기
Reg-free COM은 COM 컴포넌트의 정보를 Windows 전체의 레지스트리(Registry)가 아니라, 앱 측의 매니페스트(Manifest)에서 선언하는 메커니즘이다.
기본 구성은 다음과 같다.
LegacyApp.exe
LegacyApp.exe.manifest
MSCOMCTL.OCX
...
앱과 같은 폴더에 OCX를 두고, 매니페스트에 COM 정보를 기술한다. Windows는 해당 앱을 실행할 때만 동봉된 OCX를 해결(Resolve)한다.
이를 통해 다음과 같은 이점을 얻을 수 있다.
regsvr32가 불필요함 - 관리자 권한으로 COM을 등록할 필요가 없음- 다른 앱이 사용하는 OCX 등록을 덮어쓰지 않음
- 앱마다 의존 버전(Dependency version)을 격리할 수 있음
- 폴더 단위로 배포 및 삭제가 용이함
반면, 매니페스트에는 실제 OCX와 일치하는 정보가 필요하다.
TypeLib, CLSID, ProgID, comClass, 그리고 필요에 따라 프록시(Proxy) 정보 등이 서로 맞지 않으면, OCX가 바로 옆에 있어도 로드되지 않는다.
매니페스트는 인터넷 샘플이 아니라 "실물"로 만들기
Reg-free COM에서 가장 위험한 것은 검색해서 찾은 매니페스트 조각을 그대로 사용하는 것이다.
동일한 이름의 OCX라도 배포된 시기나 환경에 따라 파일 버전, TypeLib 버전, 의존 관계가 다를 수 있다.
이번에는 정상적으로 동작하고 있는 환경과 실제로 동봉할 파일로부터 다음 사항들을 확인했다.
- OCX 파일의 실체
- 등록된 CLSID 정보
- TypeLib 정보
- 파일과 라이브러리의 버전
- 의존 DLL
그리고 그것들을 기반으로 매니페스트를 구성했다.
중요한 것은 "어딘가에서 동작했던 예시"가 아니라, "이번에 배포할 OCX 그 자체"를 정답으로 삼는 것이다.
참고로, 대상 EXE에 이미 UAC용 매니페스트가 내장되어 있는 경우, 외부 매니페스트를 추가하는 것만으로는 기대한 대로 동작하지 않을 수 있다.
이번에도 기존 매니페스트를 한 번 추출한 뒤, Reg-free COM에 필요한 요소를 통합하여 EXE에 다시 내장(Embed)했다.
XML 네임스페이스(Namespace)나 기존 설정을 망가뜨리면 다른 문제가 발생한다. 새로운 매니페스트로 통째로 덮어쓰는 것보다, 기존 내용을 존중하며 통합하는 것이 더 안전하다.
Common Controls v6와 MSCOMCTL.OCX를 혼동하지 말 것
이 부분은 이름이 비슷해서 매우 혼란스럽기 쉽다.
MSCOMCTL.OCX를 사용하는 앱에서는 Windows의 비주얼 스타일(Visual Style)을 활성화하기 위해, 매니페스트에 Microsoft.Windows.Common-Controls v6 의존성 지정을 넣는 경우가 있다.
<dependency>
<dependentAssembly>
<assemblyIdentity
...
하지만 이것은 MSCOMCTL.OCX 자체의 COM 등록 정보가 아니다.
위의 조각만 붙여넣는다고 해서 MSCOMCTL.OCX의 Reg-free COM화가 완성되지는 않는다.
"Windows의 Common Controls v6를 사용한다는 선언"과 "MSCOMCTL.OCX의 TypeLib·COM 클래스를 선언하는 정보"는 별개로 취급해야 한다.
이름만 비슷할 뿐 담당 부서가 다르다. 오래된 Windows 기술은 가끔 동명이인 함정을 파놓곤 한다.
UAC를 없애기 전에, 쓰기 권한을 수정하기
오래된 VB6 앱의 매니페스트에는 다음과 같은 지정이 남아 있는 경우가 있다.
<requestedExecutionLevel
level="requireAdministrator"
uiAccess="false" />
이것을 asInvoker로 바꾸면 실행 시의 UAC 확인은 없앨 수 있다.
단, 기계적으로 치환해서는 안 된다.
오래된 앱은 앱 폴더나 Program Files 하위 디렉터리에 설정 파일, 임시 파일, 전개(展開) 데이터 등을 기록하도록 설계되어 있는 경우가 있다. 관리자 권한만 제거하면, 실행은 되더라도 저장, 인쇄, 압축, 이미지 생성, 설정 유지 등이 망가질 수 있다.
이번에는 임시 작업 데이터를 다음과 같은 사용자 쓰기 가능 영역으로 옮겼다.
%LOCALAPPDATA%\Vendor\Product\Temp
실제 제조사 명칭·제품명·내부 경로는 일반화하였다.
압축·전개, 모델 저장, 이미지 생성 등의 임시 파일도 같은 방식으로 사용자 영역으로 옮겼다.
확인 항목은 단순히 "실행되는가"만이 아니다.
- 파일을 열 수 있는가
- 저장할 수 있는가
- 인쇄할 수 있는가
- 설정을 저장할 수 있는가
- 종료 후, 재시작했을 때 상태가 유지되는가
- 앱 폴더 내에서 쓰기 오류가 발생하지 않는가
UAC가 나타나지 않게 된 것이 목표가 아니다. 관리자 권한 없이도 마지막까지 정상적으로 사용할 수 있는 것이 목표다.
Windows Sandbox에서 "정말로 포터블(Portable)인가"를 확인하기
개발 PC에서 작동했다는 결과는 포터블화의 증명이 되지 않는다.
이미 OCX가 등록되어 있을지도 모른다. 필요한 DLL이 시스템 폴더에 들어 있을지도 모른다. 과거의 인스톨러가 보이지 않는 곳에서 환경을 갖춰주었을 가능성이 있다.
그래서 Windows Sandbox나 깨끗한 가상 환경을 사용했다.
1. 깨끗한 Windows 환경을 실행
2. portable_build_clean만 복사
3. EXE를 더블 클릭
...
특히 중요했던 점은, 다른 언어의 Windows 환경에서도 대상 언어 버전의 앱을 실행하여 인쇄까지 통과했다는 것이다.
언어 리소스, 폰트, 프린터 주변 환경, 파일 경로는 로컬 환경에서는 숨겨져 있던 문제를 표면화시킨다.
성공 버전은 동결하고, 최소화는 복사본 측에서 수행
한 번 작동한 폴더를 그 자리에서 바로 정리해서는 안 된다.
먼저 성공 버전으로서 저장한다.
portable_build_success_001/
portable_build_min_test/
불필요해 보이는 파일을 줄이는 작업은 반드시 복사본 측에서 수행한다.
삭제하기 전에 격리(quarantine) 폴더로 옮기는 방법도 유효하다.
_quarantine/
단, 정식 인스톨러 설정이 남아 있다면, 성공 버전에서 조금씩 깎아내기보다는 화이트리스트로부터 매번 재구축하는 편이 더 안전했다.
"작동하는 상태"를 표본으로서 남겨둔다. 이는 레거시(Legacy) 앱 재생에 있어 상당히 중요한 습관이다.
Codex에 맡긴 작업
이번에 모든 것을 사람이 수작업으로 추적한 것은 아니다.
Codex에는 주로 다음 작업을 맡겼다.
- VB6 프로젝트의 의존성 분석 (Dependency Analysis)
- 기존 인스톨러 설정 분석
- 정식 파일 목록 추출
- OCX와 DLL 수집
- reg-free COM 매니페스트 (manifest) 조립
- 기존 매니페스트 추출 및 통합
- EXE에 매니페스트 재삽입
- 포터블 폴더 구축
- 혼입 파일 검사
- Windows Sandbox용 테스트 절차 작성
AI 에이전트가 특히 잘했던 부분은 대량의 설정과 파일을 횡단하며 "무엇이 의존물이고, 무엇이 단순한 작업 잔해인가"를 정리하는 부분이다.
반면, 실행 결과를 보고 채택할지 여부를 결정하는 것, OCX의 재배포 라이선스를 확인하는 것, 실기에서 인쇄나 저장을 시도하는 것은 인간 측의 판단으로 남는다.
AI에게 전부 떠넘기는 것이 아니라, 조사·구축·반복 작업을 맡기고 인간이 경계 조건과 제품 책임을 쥐는 방식이다. 이 분담이 상당히 효과적이었다.
이 방법의 주의점
reg-free COM은 강력하지만 만능은 아니다.
적어도 다음 사항들은 확인해야 한다.
- OCX나 DLL의 재배포 라이선스
- 동봉하는 파일의 출처와 버전
- 매니페스트의 CLSID와 TypeLib가 실제물과 일치하는지
- 개발 환경이 아닌 깨끗한 환경에서 작동하는지
- UAC 변경 후에도 저장·인쇄·설정 유지가 정상적인지
- Program Files를 전제로 한 쓰기가 남아 있지 않은지
- Windows 11에서 주요 기능이 작동하는지
"내 PC에서 작동했다"는 시작점에 불과하다.
환경 의존성을 없애는 작업에서는 환경을 없앤 장소에서 테스트할 필요가 있다.
요약: 오래된 자산을 현대적인 배포 형식으로 재구성하기
OCX에 의존하는 VB6 앱이라도 조건을 갖추면 인스톨러 없이 작동시킬 수 있다.
이번 작업의 요점은 다음과 같다.
- reg-free COM (레지스트리 등록이 필요 없는 COM) 사용하기
- manifest (매니페스트)는 실제로 동봉할 OCX로부터 생성하기
- 기존 manifest를 손상시키지 않고 통합하기
- 오래된 인스톨러를 정식 파일 목록으로 재사용하기
- UAC (사용자 계정 컨트롤)를 해제하기 전에, 쓰기 경로를 사용자 영역으로 이동하기
- Windows Sandbox나 다른 언어 설정의 Windows에서 확인하기
- 성공한 버전을 동결(Freeze)한 후 최소화하기
오래된 VB6 앱은 현대의 배포 기반 관점에서 보면 다소 서툰 존재다.
하지만 의존성(Dependency)을 하나씩 가시화하고, manifest와 폴더 구조를 다시 구성하면 여전히 현역으로 구동할 수 있다.
오래된 자산을 버리는 것이 아니라, 현대의 규칙으로 번역하는 것.
이것이 AI 시대만의 소프트웨어 수명 연장술이라고 생각한다.
그리고 이러한 재생 작업을 거친 디지털 페이퍼 크래프트 제작 소프트웨어 「紙龍 (Kamiryu)」는 일본어판과 영어판 모두 Microsoft Store에서 공개 중입니다!
문책: 米村貴裕 (Yoneura Takahiro)
Discussion

AI 자동 생성 콘텐츠
본 콘텐츠는 Zenn AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기