단계 1: 초기 jpackage 실행 실패
현상: 생성된 설치 파일(.exe)이 실행되지 않거나, 설치 후 프로그램이 무반응.
원인: jpackage 명령어에 JavaFX 모듈 경로(--module-path) 및 사용 모듈(--add-modules) 옵션 누락.
해결: 명령어에 --module-path와 --add-modules 옵션을 추가하여 JavaFX 라이브러리 위치 명시.
단계 2: .jar 파일 단독 실행 검증 중 문제 발생
이슈 2-1: Fat Jar와 Module Path 충돌
현상: 의존성이 포함된 Jar 파일(Fat Jar)을 --module-path 옵션과 함께 실행 시, java.lang.module.FindException: Module javafx.controls not found 에러 발생.
원인: Jar 파일 내부에 포함된 JavaFX와 외부 --module-path로 지정된 JavaFX 간의 모듈 충돌.
해결: pom.xml의 JavaFX 의존성에 provided를 추가하여 최종 빌드된 Jar에서 JavaFX를 제외시킴.
이슈 2-2: Java 버전 불일치
현상: .jar 실행 시 Unsupported major.minor version 66.0 에러 발생.
원인: 프로젝트 JDK 버전(21)과 사용한 JavaFX SDK 버전이 요구하는 Java 버전이 달라 발생한 호환성 문제.
해결: 프로젝트 JDK와 동일한 버전의 JavaFX SDK(v21)로 교체.
단계 3: jpackage 명령어 완성 중 문제 발생
이슈 3-1: UUID 형식 오류
현상: IllegalArgumentException: UUID string too large 에러 발생.
원인: --win-upgrade-uuid 옵션에 전달된 UUID 값의 일부가 12자리가 아닌 13자리로 입력된 오타.
해결: 올바른 형식의 UUID로 수정.
이슈 3-2: Main Jar 경로 문제
현상: The configured main jar does not exist in the input directory 에러 발생.
원인: pom.xml 설정상 --main-jar로 지정된 파일은 target/에, --input으로 지정된 의존성 폴더는 target/dependencies/에 생성되어 경로 불일치 발생.
해결: maven-resources-plugin을 사용해 빌드된 main-jar를 target/dependencies 폴더 내로 복사하도록 pom.xml 수정.
단계 4: 최종 설치 파일 실행 오류
이슈 4-1: "Failed to launch JVM"
현상: .msi로 설치된 프로그램 실행 시 Failed to launch JVM 에러 발생.
원인: jpackage의 모듈 경로와 클래스 경로 동시 처리 과정의 불안정성으로 인해, 런처 설정 파일(.cfg)이 올바르게 생성되지 않음.
해결: jpackage 명령어에서 --module-path, --add-modules 옵션을 모두 제거하고, JavaFX 라이브러리까지 모두 --input 폴더에 포함시켜 순수 클래스패스(Classpath) 방식으로 전환.
이슈 4-2: 에러 메시지 없이 즉시 종료 (Silent Crash)
현상: 클래스패스 방식으로 생성된 프로그램 실행 시, 에러 로그 없이 즉시 종료됨.
원인: 메인 클래스가 javafx.application.Application을 직접 상속할 경우, JVM 시작 단계와 JavaFX 초기화 단계가 충돌. 해당 충돌은 try-catch로 포착할 수 없는 low-level에서 발생.
단계 5: 최종 해결책 - Launcher 클래스 도입
개요: 'Silent Crash' 문제를 해결하기 위한 최종 방안.
구현:
JavaFX와 무관한 일반 Java 클래스(Launcher.java)를 생성.
Launcher 클래스의 main 메소드에서 실제 애플리케이션인 App.main()을 호출하도록 구현.
pom.xml 및 jpackage 명령어의 메인 클래스 진입점(entry point)을 모두 이 Launcher 클래스로 지정.
효과: JVM이 JavaFX 모듈과 관계없이 먼저 안정적으로 시작된 후, Launcher를 통해 JavaFX 애플리케이션을 실행. 이를 통해 JVM 시작과 JavaFX 초기화 프로세스를 분리하여 충돌의 근본 원인을 제거함._
오늘 처음으로 내 손으로 만든 설치 파일(.msi)을 갖게 되었다.
브라우저라는 가상 머신 위에서 동작하는 웹 서비스만 만들다가, 사용자의 PC에 직접 설치되는 독립적인 애플리케이션을 완성하니 기분이 묘했다.
오늘 만든 것이 게임은 아니었지만, JavaFX를 통해 UI를 구성하고 사용자의 인터랙션을 고민하는 과정은 UI/UX 감각을 기르는 데 좋은 훈련이 되었다.
사용자의 입장에서 어떻게 하면 더 편리할지 고민하는 경험은 어떤 분야에서든 중요하기에 의미 있는 외도였다고 생각한다.
나는 여전히 '개발자는 AI를 활용하더라도 전체적인 코드의 작동 방식을 파악해야 한다'는 생각에 변함이 없다.
하지만 오늘 실험에서는 의도적으로 그 원칙을 깨보았다.
내부 소스 코드의 작동 방식을 완전히 이해하지 않은 상태에서, 발생하는 모든 에러를 직접 해결하는 대신 AI에게 그대로 위임했다.
AI가 순차적으로 웹상의 정보를 찾고, 컨텍스트를 파악해 파일을 직접 수정하며 문제를 해결해나가는 모습은 상당히 인상적이었다.
이번 경험은 개발자 앞에 놓인 AI라는 도구에 대해 더 깊은 생각을 하게 만들었다.
단순히 코드를 생성하는 것을 넘어, 문제 해결의 파트너로서 어디까지 활용할 수 있을지에 대한 새로운 가능성을 엿본 하루였다.