From a6118039a3b3734ad2edc863e21e191ba3285757 Mon Sep 17 00:00:00 2001 From: claude-bot Date: Fri, 17 Jul 2026 00:45:06 +0900 Subject: [PATCH] =?UTF-8?q?fix(server):=20=EC=A7=81=EC=A0=91=20=EC=84=A0?= =?UTF-8?q?=ED=83=9D=ED=95=9C=20JDK=20=EB=8F=84=20Java=2025+=20=EA=B2=80?= =?UTF-8?q?=EC=A6=9D=20=ED=9B=84=20=EC=A7=84=ED=96=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 자동 탐색은 Java 25 미만을 걸렀지만, 사용자가 직접 입력/폴더선택한 JDK 는 버전 검증 없이 다음 단계로 넘어가 run.bat 이 낡은 자바로 패치될 수 있었다. 그러면 서버가 여전히 UnsupportedClassVersionError 로 뜨지 않는다. - jdk:verify IPC 추가(java -version 으로 메이저 버전 확인) + preload 노출. - JDK 단계 "다음" 에서 선택 경로를 검증해 Java 25 미만이거나 버전을 못 읽으면 진행을 막고 안내. 자동 설치/자동 탐색 경로도 이 게이트를 통과. - 버전 0.4.4→0.4.5. Co-Authored-By: Claude Opus 4.7 --- installer/renderer.js | 29 ++++++++++++++++++++++++++--- locales/installer/ko-kr.json | 5 ++++- package.json | 2 +- src/installer/main.ts | 9 +++++++++ src/installer/preload.ts | 2 ++ 5 files changed, 42 insertions(+), 5 deletions(-) diff --git a/installer/renderer.js b/installer/renderer.js index 536ebbd..392b098 100644 --- a/installer/renderer.js +++ b/installer/renderer.js @@ -686,14 +686,37 @@ function renderSubStep32(host, back, done) { if (installing) return back() }) - nextBtn.addEventListener('click', function () { + nextBtn.addEventListener('click', async function () { if (installing) return - if (!input.value.trim()) { + var val = input.value.trim() + if (!val) { msg.textContent = tt('step3.sub32.pathRequired') msg.classList.add('error') return } - state.serverInstall.jdk = input.value.trim() + // 직접 입력/선택한 JDK 도 서버 실행에 충분한 버전(Java 25+)인지 검증한다. + // 너무 낮으면 run.bat 이 그 자바를 써도 UnsupportedClassVersionError 로 서버가 안 뜬다. + nextBtn.disabled = true + msg.classList.remove('success', 'error') + msg.textContent = tt('step3.sub32.verifying') + try { + var v = await installerApi.verifyJdk(val) + if (!v || !v.ok) { + msg.classList.add('error') + msg.textContent = (v && v.major) + ? tt('step3.sub32.versionTooLow', { major: v.major, required: (v && v.required) || 25 }) + : tt('step3.sub32.versionUnknown') + nextBtn.disabled = false + return + } + } catch (err) { + msg.classList.add('error') + msg.textContent = tt('step3.sub32.versionUnknown') + nextBtn.disabled = false + return + } + nextBtn.disabled = false + state.serverInstall.jdk = val done() }) ;(async function () { diff --git a/locales/installer/ko-kr.json b/locales/installer/ko-kr.json index 1d29aa9..4f1552a 100644 --- a/locales/installer/ko-kr.json +++ b/locales/installer/ko-kr.json @@ -100,7 +100,10 @@ "installCanceled": "JDK 설치 취소됨", "installFailed": "JDK 설치 실패: {{message}}", "installError": "JDK 설치 오류: {{message}}", - "pathRequired": "JDK 경로를 입력해 주세요." + "pathRequired": "JDK 경로를 입력해 주세요.", + "verifying": "선택한 JDK 버전을 확인하는 중…", + "versionTooLow": "선택한 Java {{major}} 는 너무 낮습니다. 서버 실행에는 Java {{required}} 이상이 필요합니다. \"자동 설치\" 로 Temurin 25 를 받거나 Java 25 이상 폴더를 선택해 주세요.", + "versionUnknown": "선택한 경로에서 Java 실행 파일을 찾지 못했거나 버전을 확인할 수 없습니다. JDK 폴더(bin\\java.exe 가 있는 곳)를 선택하거나 \"자동 설치\" 를 눌러 주세요." }, "sub33": { "heading": "서버 다운로드 및 설치", diff --git a/package.json b/package.json index e556c7a..372ac26 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "minecraft-music-quiz-installer", - "version": "0.4.4", + "version": "0.4.5", "description": "마인크래프트 음악퀴즈 간편설치기 + 관리 사이트", "main": "dist/installer/main.js", "scripts": { diff --git a/src/installer/main.ts b/src/installer/main.ts index 9778876..c26ebe8 100644 --- a/src/installer/main.ts +++ b/src/installer/main.ts @@ -320,6 +320,15 @@ ipcMain.handle('jdk:detect', async () => { return { found: false, path: '' } }) +// 사용자가 직접 입력/선택한 JDK 경로가 서버 실행에 충분한 버전인지 확인한다. +// ok=true → major >= 요구 버전(25). +// major=0 → 경로에서 java 를 못 찾거나 버전을 못 읽음(실행 실패 등). +ipcMain.handle('jdk:verify', async (_event, jdkPath: string): Promise<{ ok: boolean; major: number; required: number }> => { + const javaExe = jdkPath ? findJavaExeInHome(jdkPath) : '' + const major = javaExe ? getJavaMajor(javaExe) : 0 + return { ok: major >= REQUIRED_JAVA_MAJOR, major, required: REQUIRED_JAVA_MAJOR } +}) + // ── JDK 자동 설치(Temurin 25, 취소 가능) ────────────────────────────── interface JdkInstallState { controller: AbortController | null diff --git a/src/installer/preload.ts b/src/installer/preload.ts index df8e39a..4673e9a 100644 --- a/src/installer/preload.ts +++ b/src/installer/preload.ts @@ -25,6 +25,8 @@ const api = { // 3-2 detectJdk: (): Promise<{ found: boolean; path: string }> => ipcRenderer.invoke('jdk:detect'), + verifyJdk: (jdkPath: string): Promise<{ ok: boolean; major: number; required: number }> => + ipcRenderer.invoke('jdk:verify', jdkPath), installJdk: (): Promise<{ ok: boolean; path?: string; message?: string }> => ipcRenderer.invoke('jdk:install'), cancelJdkInstall: (): Promise<{ ok: boolean }> => ipcRenderer.invoke('jdk:cancelInstall'),