Windows EXE 시작 프로그램 생성
패키징 시 보호된 애플리케이션을 위한 네이티브 Windows 시작 프로그램을 생성할 수 있습니다. 이 프로그램은 순수한 Win32 실행 파일로, 더블클릭만으로 애플리케이션이 실행되며 사용자가 먼저 Java를 설치하거나 run.bat를 볼 필요가 없습니다.
EXE는 선택 사항이며 기본적으로는 생성되지 않습니다. 이 기능을 활성화하면 생성된 패키지에 기존의 run.sh / run.command / run.bat도 그대로 유지되며, 두 가지 시작 방식 모두 동일한 아카이브 구조, 클래스 경로, 메인 클래스 및 JVM 파라미터를 사용합니다.
1. 적용 범위
| 프로젝트 | 지원 여부 |
|---|---|
| 애플리케이션 유형 | Java Application, Spring Boot(세 가지 레이아웃 모두 지원), Tomcat |
| 대상 플랫폼 | windows-x64, windows-x86, windows-aarch64 |
| 지원되지 않음 | Library Encryption(단일 .p4jx 아카이브에는 실행 가능한 애플리케이션 디렉터리가 없음) |
최소 하나의 Windows 대상 플랫폼을 선택해야 합니다. Linux 또는 macOS 플랫폼도 함께 선택해도 작업이 실패하지는 않습니다. 이러한 플랫폼의 하위 패키지는 정상적으로 생성되지만 EXE는 포함되지 않으며 기존 시작 스크립트가 그대로 사용됩니다. 모든 대상 플랫폼이 Windows가 아닌 경우 작업은 즉시 오류가 발생합니다.
2. GUI 작업
- 입력 파일 및 대상 플랫폼을 선택하는 페이지에서 Windows 애플리케이션용 EXE 파일(x64/x86/ARM64) 생성를 선택하고 최소 하나의 Windows 대상 플랫폼을 지정해야 합니다.
- 이 스위치는 간단 모드와 고급 모드로 분기되기 전에 위치하므로 두 모드 모두에서 EXE를 생성할 수 있습니다.
- 이를 선택하면 파일명, 시작 프로그램 모드, 아이콘, Windows 버전 정보를 입력하는 Windows EXE 시작 프로그램 페이지가 추가로 나타납니다. 선택하지 않으면 바로 최종 확인 페이지로 이동합니다.
- EXE를 활성화하면 JVM 시작 파라미터 입력 필드가 이 시작기 페이지에만 표시되어 동일한 매개변수에 두 개의 입력 창이 생기는 것을 방지합니다. 입력된 매개변수는 EXE와 시작 스크립트에 동시에 저장됩니다.
- 최종 확인 페이지에는 실제로 EXE가 생성될 플랫폼과 입력된 시작기 필드들이 목록으로 표시됩니다.
3. CLI 예시
가장 간단한 형태로, --windows-exe만 필요합니다:
p4j --target-platform windows-x64 javaapp app.jar dist --windows-exe
파일명과 창 모드 지정:
p4j --target-platform windows-x64 javaapp app.jar dist \
--windows-exe \
--exe-name MyApp.exe \
--exe-mode gui \
--exe-icon assets/app.ico
한 번에 세 가지 Windows 아키텍처를 생성하고 완전한 버전 리소스를 입력합니다:
p4j --target-platform windows-x64,windows-x86,windows-aarch64 \
springboot app.jar dist \
--windows-exe \
--exe-name MyService \
--exe-file-version 1.4.2.0 \
--exe-product-version 1.4.2.0 \
--exe-company 'Example Inc.' \
--exe-product 'Example Service' \
--exe-description 'Example background service' \
--exe-copyright 'Copyright (C) 2026 Example Inc.'
Tomcat 패키지도 지원되며, 생성된 EXE는 내장된 Tomcat을 프론트엔드 방식으로 실행합니다:
p4j --target-platform windows-x64 tomcat app.war dist --context /demo --windows-exe
4. 매개변수 설명
| 옵션 | 설명 |
|---|---|
--windows-exe | EXE 생성 활성화 |
--exe-name <name> | EXE 파일명; 빈 값일 경우 입력된 파일명 사용, Tomcat의 경우 tomcat 사용 |
--exe-mode <mode> | console(기본값) 또는 gui |
--exe-icon <ico> | Windows 아이콘 파일, .ico 형식, 선택 사항 |
--exe-file-version <a.b.c.d> | PE 파일 버전 |
--exe-product-version <a.b.c.d> | PE 제품 버전 |
--exe-company <text> | 회사명 |
--exe-product <text> | 제품명 |
--exe-description <text> | 작업 관리자 및 파일 속성에 표시되는 파일 설명 |
--exe-copyright <text> | 저작권 정보 |
--exe-* 옵션 중 하나만 선택해도 자동으로 EXE 생성이 활성화되므로, 별도로 --windows-exe를 입력할 필요가 없습니다.
파일명은 오직 파일명으로만 사용되어야 하며, /, \ 또는 디렉터리 부분을 포함할 수 없습니다. .exe 접미사가 없을 경우 자동으로 추가됩니다.
두 버전 번호 필드의 규칙은 동일합니다: 1부터 4개의 구간으로 영문 점으로 구분된 숫자이며, 각 구간의 값은 0부터 65535까지입니다. 예: 1.0.0.1. Windows는 각 구간을 16비트 부호 없는 정수로 저장하므로, v1.0나 1.0-beta와 같이 문자나 공백이 포함된 형태는 허용되지 않습니다. 빈 값은 0.0.0.0를 의미합니다. 이 두 필드는 패키징이 시작되기 전에 검증되므로, 패키징 도중에야 실패가 발생하지 않습니다.
5. 출력 구조
Java Application을 예로 들면, EXE와 시작 스크립트가 패키지의 루트 디렉터리에 함께 위치합니다:
dist/
├── MyApp.exe # 새로 추가된 Windows 시작 프로그램
├── app.p4jx
├── vlxjre/
├── lib/
├── run.sh
├── run.command
├── run.bat
└── README.md
패키지 내의 README.md는 생성된 EXE 파일명을 표시하고, 코드 서명에 관한 안내를 함께 제공합니다.
6. 실행 동작
EXE가 있는 디렉터리가 바로 애플리케이션의 루트 디렉터리입니다. 시작 프로그램은 루트 디렉터리 내에 있는 런타임, 아카이브, 클래스 경로, 작업 디렉터리만 허용하며, 패키지 외부를 가리키는 경로나 심볼릭 링크, 접속 지점으로 대체된 경로는 거부되어 프로세스가 시작되지 않습니다. 이는 패키지 전체를 이동하거나 이름을 바꿀 수는 있지만, EXE만 따로 복사하여 사용할 수는 없음을 의미합니다.
| 동작 | 설명 |
|---|---|
| 런타임 | 패키지 내에 있는 vlxjre\bin\java.exe만 고정적으로 사용하며, 시스템 Java는 사용하지 않고 JAVA_HOME도 읽지 않음 |
| 명령줄 인수 | EXE에 전달된 인수를 그대로 애플리케이션 인수 뒤에 추가함 |
| 콘솔 모드 | 현재 콘솔의 표준 입력/출력을 상속받아 애플리케이션이 종료될 때까지 대기한 후 종료 코드를 반환함 |
| GUI 모드 | 콘솔 창을 생성하지 않으며 데스크톱 애플리케이션에 적합함 |
| 환경 변수 | 시작하기 전에 JAVA_TOOL_OPTIONS, _JAVA_OPTIONS, JDK_JAVA_OPTIONS 및 CLASSPATH를 삭제하여 외부로부터의 주입으로 인해 시작 파라미터가 변경되는 것을 방지합니다. |
EXE의 JVM 파라미터는 패키징 시 고정되어 파라미터 블록과 함께 서명되며, 실행 시에 검증되므로 배포 후에는 수정할 수 없습니다. APP_JAVA_OPTS는 run.bat에 대해서만 유효하며, EXE는 이를 읽지 않습니다. EXE의 JVM 파라미터를 변경해야 하는 경우에는 다시 패키징해야 합니다.
같은 이유로 -javaagent, -agentlib, -agentpath, -Xbootclasspath 및 --patch-module는 EXE의 시작 파라미터에 쓰기가 허용되지 않습니다. --jvm-option를 사용해 이러한 파라미터를 전달할 경우 패키징이 즉시 실패합니다.
7. 코드 서명
Protector4J는 생성된 EXE에 발행자 서명을 추가하지 않으며, 어떠한 Authenticode 자격 증명도 다루지 않습니다. 아이콘, 버전 리소스, 시작 파라미터 등 모든 PE 관련 수정은 패키징 단계에서 이루어지므로 서명 단계는 마지막에 수행되어야 합니다.
- 패키징을 완료하고 EXE가 애플리케이션을 정상적으로 시작할 수 있는지 확인합니다.
- 자신의 인증서를 사용하여 Authenticode 서명을 하고 RFC3161 타임스탬프를 추가합니다.
- Windows의
/pa정책을 사용하여 서명을 검증합니다.
서명이 완료된 후에는 이 PE 파일을 더 이상 수정하지 마십시오. 어떠한 변경이라도 서명을 무효화시킬 수 있습니다. 아이콘이나 버전 번호를 변경해야 하는 경우에는 파일을 다시 패키징한 뒤 재서명해 주십시오.
8. 작업 파일 필드
내보내진 p4j-task.yml는 버전 2를 사용하며, EXE를 활성화할 경우 다음 필드들이 저장됩니다. 버전 1의 작업 파일은 여전히 정상적으로 읽을 수 있습니다.
windowsExe: true
exeName: MyApp.exe
exeMode: console
exeIcon: assets/app.ico
exeFileVersion: 1.4.2.0
exeProductVersion: 1.4.2.0
exeCompany: Example Inc.
exeProduct: Example Service
exeDescription: Example background service
exeCopyright: Copyright (C) 2026 Example Inc.
9. 자주 묻는 질문
| 현상 | 원인 및 해결 방법 |
|---|---|
| Windows 목표 플랫폼이 필요하다는 메시지가 표시됨 | EXE가 활성화되었지만 windows-x64, windows-x86 또는 windows-aarch64 목표가 선택되지 않음 |
| 버전 번호 형식이 올바르지 않다는 메시지가 표시됨 | 버전 필드에 문자, 공백이 포함되어 있거나 4개 섹션을 초과하며, 특정 섹션의 값이 0에서 65535 범위를 벗어남 |
| EXE 이름은 파일명으로만 설정해야 한다는 메시지가 표시됨 | 파일명에 경로 구분자가 포함되어 있으니, 디렉터리가 포함되지 않은 이름으로 변경해야 함 |
| 아이콘 파일을 찾을 수 없다는 메시지가 표시됨 | --exe-icon가 가리키는 .ico가 존재하지 않으니 경로를 확인해야 함 |
| 더블클릭 후 애플리케이션이 즉시 종료되고 창이 나타나지 않음 | GUI 모드를 사용하고 있어 애플리케이션이 시작되지 않으니, 콘솔 모드로 다시 패키징하면 오류 출력을 확인할 수 있음 |
| 단독으로 복사된 EXE는 실행될 수 없습니다. | 시작 프로그램은 실행 시 파일과 아카이브가 동일한 패키지 디렉터리에 있어야 하므로, 전체 출력 디렉터리를 복사해 주십시오. |
전체 CLI 옵션은 CLI 매개변수 참고를 참조하시고, GUI 가이드 프로세스는 GUI 사용 가이드를 참조하십시오.