diff --git a/JDK21_BOOTRUN_GUIDE.md b/JDK21_BOOTRUN_GUIDE.md new file mode 100644 index 0000000..0353031 --- /dev/null +++ b/JDK21_BOOTRUN_GUIDE.md @@ -0,0 +1,83 @@ +# JDK 21로 eapim-portal 기동 가이드 + +## 환경 + +- JDK 21 경로: `D:\installs\jdk-21` (jdk-21.0.10+7 폴더를 복사하여 이름 변경) +- Gradle 8.7 (JDK 21 지원) +- Spring Boot 2.7.18 + +> **주의:** 원본 폴더명(`jdk-21.0.10+7`)에 `+` 문자가 포함되어 있어 CMD에서 JAVA_HOME 설정 시 오류 발생. +> 탐색기에서 `D:\installs\jdk-21`로 복사하여 사용. + +--- + +## build.gradle 변경 사항 + +JDK 17+ 모듈 시스템(JPMS) 호환을 위해 `bootRun` 블록에 `--add-opens` JVM 인수 추가. +(Hibernate 5.6.x, Atomikos, JAXB 등의 리플렉션 접근 허용) + +```groovy +bootRun { + jvmArgs = [ + '--add-opens', 'java.base/java.lang=ALL-UNNAMED', + '--add-opens', 'java.base/java.math=ALL-UNNAMED', + '--add-opens', 'java.base/java.util=ALL-UNNAMED', + '--add-opens', 'java.base/java.util.concurrent=ALL-UNNAMED', + '--add-opens', 'java.base/java.net=ALL-UNNAMED', + '--add-opens', 'java.base/java.text=ALL-UNNAMED', + '--add-opens', 'java.base/java.io=ALL-UNNAMED', + '--add-opens', 'java.base/sun.util.calendar=ALL-UNNAMED', + '--add-opens', 'java.rmi/sun.rmi.transport=ALL-UNNAMED', + '--add-opens', 'java.sql/java.sql=ALL-UNNAMED', + ] + sourceResources sourceSets.main + args = ["--spring.profiles.active=dev"] +} +``` + +> `sourceCompatibility = "1.8"` 은 유지. `var` 키워드 관련 warning이 발생하지만 빌드/실행에는 영향 없음. + +--- + +## WAR 빌드 및 실행 (bootWarDev) + +### 1. JAVA_HOME 설정 + +```cmd +set JAVA_HOME=D:\installs\jdk-21 +set PATH=%JAVA_HOME%\bin;%PATH% +``` + +### 2. bootWarDev 빌드 + +```cmd +gradle bootWarDev +``` + +출력 파일: `build\libs\eapim-portal-dev.war` + +### 3. 실행 + +```cmd +chcp 65001 +D:\installs\jdk-21\bin\java -Dfile.encoding=UTF-8 -Dstdout.encoding=UTF-8 -jar build\libs\eapim-portal-dev.war --spring.profiles.active=dev +``` + +--- + +## 한글 인코딩 설정 + +| 항목 | 설정 | +|---|---| +| CMD 코드페이지 | `chcp 65001` (UTF-8) | +| JVM 인수 | `-Dfile.encoding=UTF-8 -Dstdout.encoding=UTF-8` | + +--- + +## bootWarDev vs bootWar 차이 + +| | `bootWar` | `bootWarDev` | +|---|---|---| +| 포함 yml | stage, prod | application.yml + application-dev.yml | +| 출력 파일 | `eapim-portal-boot.war` | `eapim-portal-dev.war` | +| 용도 | 운영/스테이징 배포 | 로컬 dev 실행 | diff --git a/build.gradle b/build.gradle index 918045e..f8cd5a3 100644 --- a/build.gradle +++ b/build.gradle @@ -123,6 +123,20 @@ bootRun { // 디버깅 사용시에는 아래 내용 주석 해제 하세요 // jvmArgs '-Xdebug', '-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005' + // JDK 17+ (모듈 시스템) 호환을 위한 설정 - Hibernate 5.x, Atomikos, JAXB 등 + jvmArgs = [ + '--add-opens', 'java.base/java.lang=ALL-UNNAMED', + '--add-opens', 'java.base/java.math=ALL-UNNAMED', + '--add-opens', 'java.base/java.util=ALL-UNNAMED', + '--add-opens', 'java.base/java.util.concurrent=ALL-UNNAMED', + '--add-opens', 'java.base/java.net=ALL-UNNAMED', + '--add-opens', 'java.base/java.text=ALL-UNNAMED', + '--add-opens', 'java.base/java.io=ALL-UNNAMED', + '--add-opens', 'java.base/sun.util.calendar=ALL-UNNAMED', + '--add-opens', 'java.rmi/sun.rmi.transport=ALL-UNNAMED', + '--add-opens', 'java.sql/java.sql=ALL-UNNAMED', + ] + sourceResources sourceSets.main // processResources 필터 우회 (dev yml 직접 참조) args = ["--spring.profiles.active=dev"] } @@ -164,6 +178,26 @@ bootWar { archiveFileName = "eapim-portal-boot.war" } +task bootWarDev(type: org.springframework.boot.gradle.tasks.bundling.BootWar) { + group = 'build' + description = 'dev 프로파일용 실행 가능 WAR (application.yml + application-dev.yml 포함)' + dependsOn compileJava + mainClass = bootWar.mainClass + classpath = sourceSets.main.runtimeClasspath + + // processResources 결과물 포함 (stage, prod yml 제외된 상태) + from(processResources.destinationDir) + + // application.yml, application-dev.yml 추가 (중복 시 srcDirs 파일 우선) + duplicatesStrategy = DuplicatesStrategy.INCLUDE + from(sourceSets.main.resources.srcDirs) { + include 'application.yml' + include 'application-dev.yml' + } + + archiveFileName = "eapim-portal-dev.war" +}//gradlew clean bootWarDev, java -jar build/libs/eapim-portal-dev.war --spring.profiles.active=dev + war { archiveFileName = "eapim-portal.war" @@ -197,4 +231,4 @@ task cryptoCli(type: JavaExec) { if (project.hasProperty('args')) { args project.args.split('\\s+') } -} \ No newline at end of file +}