Java 11+์šฉ ๊ธฐ์กด ๋ฒˆ๋“ค ์„œ๋น„์Šค์— ์•ก์„ธ์Šค

์ด ํŽ˜์ด์ง€์—์„œ๋Š” App Engine ํ‘œ์ค€ ํ™˜๊ฒฝ์—์„œ ์ง€์›๋˜๋Š” ์ตœ์‹  Java ๋ฒ„์ „์œผ๋กœ ๋ฒˆ๋“ค ์„œ๋น„์Šค๋ฅผ ์„ค์น˜ํ•˜๊ณ  ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค. ์•ฑ์€ App Engine API JAR์„ ํ†ตํ•ด ๋ฒˆ๋“ค ์„œ๋น„์Šค์— ์•ก์„ธ์Šคํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์‹œ์ž‘ํ•˜๊ธฐ ์ „์—

App Engine API JAR ์„ค์น˜

์ง€์›๋˜๋Š” ์ตœ์‹  Java ์•ฑ์—์„œ ๊ธฐ์กด ๋ฒˆ๋“ค ์„œ๋น„์Šค๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๋ฉด app.yaml ํŒŒ์ผ ๋Œ€์‹  appengine-web.xml ํŒŒ์ผ์„ ์‚ฌ์šฉํ•˜์—ฌ ์•ฑ์„ ๊ตฌ์„ฑํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๋‹ค์Œ ์˜ˆ์‹œ์—์„œ๋Š” EE10 ๋ฒ„์ „ 21 ์ด์ƒ(๊ธฐ๋ณธ๊ฐ’), EE8 ๋ฒ„์ „ 21 ๋ฐ ๋ฒ„์ „ 17 ์ดํ•˜์˜ appengine-web.xml์— ๊ตฌ์„ฑ ์„ค์ •์„ ์ถ”๊ฐ€ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋ณด์—ฌ ์ค๋‹ˆ๋‹ค. ๊ธฐ๋ณธ ๊ตฌ์„ฑ์—์„œ ์ง€์›๋˜๋Š” ์ตœ์‹  ๋ฒ„์ „์„ ์‚ฌ์šฉํ•˜๋ ค๋ฉด Jakarta ๋„ค์ž„์ŠคํŽ˜์ด์Šค๋ฅผ ํฌํ•จํ•˜๋„๋ก ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์„œ๋ธ”๋ฆฟ ๋ฐ ์ข…์† ํ•ญ๋ชฉ์„ ์—…๋ฐ์ดํŠธํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๊ตฌ์„ฑ ์˜ต์…˜์— ๋Œ€ํ•œ ์ž์„ธํ•œ ๋‚ด์šฉ์€ ๊ธฐ์กด ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์—…๊ทธ๋ ˆ์ด๋“œ๋ฅผ ์ฐธ์กฐํ•˜์„ธ์š”.

Java ๋ฒ„์ „์— ๋”ฐ๋ผ appengine-web.xml ํŒŒ์ผ์— ๋‹ค์Œ ์„ค์ •์„ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.

v21 ์ด์ƒ(EE10)

<?xml version="1.0" encoding="utf-8"?>
<appengine-web-app xmlns="http://appengine.google.com/ns/1.0">
  <runtime>java21</runtime> <!-- or another supported version -->
  <app-engine-apis>true</app-engine-apis>
</appengine-web-app>

v21(EE8)

<?xml version="1.0" encoding="utf-8"?>
<appengine-web-app xmlns="http://appengine.google.com/ns/1.0">
  <runtime>java21</runtime>
  <system-properties>   <!-- run your apps on EE8 -->
  <property name="appengine.use.EE8" value="true"/>
  </system-properties>
  <app-engine-apis>true</app-engine-apis>
</appengine-web-app>

v17 ์ดํ•˜

<?xml version="1.0" encoding="utf-8"?>
<appengine-web-app xmlns="http://appengine.google.com/ns/1.0">
  <runtime>java17</runtime> <!-- or another supported version -->
  <app-engine-apis>true</app-engine-apis>
</appengine-web-app>

๊ธฐ์กด ๋ฒˆ๋“ค ์„œ๋น„์Šค๋ฅผ ์ข…์† ํ•ญ๋ชฉ์œผ๋กœ ์ง€์ •ํ•˜๋ ค๋ฉด pom.xml ํŒŒ์ผ์— ๋‹ค์Œ ์ค„์„ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.

 <dependency>
    <groupId>com.google.appengine</groupId>
    <artifactId>appengine-api-1.0-sdk</artifactId>
    <version>2.0.31</version> <!-- or later-->
  </dependency>

์•ฑ์—์„œ web.xml ํŒŒ์ผ์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ <app-engine-apis> ์š”์†Œ๋ฅผ ์ถ”๊ฐ€ํ•˜๊ณ  ์ด๋ฅผ true๋กœ ์„ค์ •ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

  <app-engine-apis>true</app-engine-apis>

Java 21 ์•ฑ์„ ๋ฐฐํฌํ•˜๋ ค๋ฉด ์ปดํŒŒ์ผ๋˜๊ณ  ์Šคํ…Œ์ด์ง•๋œ ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ mvn appengine:deploy ๋ช…๋ น์–ด ๋˜๋Š” gcloud app deploy ~/my_app/WEB-INF/appengine-web.xml ๋ช…๋ น์–ด๋ฅผ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.

Java 21์— ์‚ฌ์šฉ๋˜๋Š” ๊ธฐ๋ณธ ์ง„์ž…์ 

Java 21 ์•ฑ์€ ์›น ์•ฑ์šฉ JVM์„ ์‹œ์ž‘ํ•  ๋•Œ ์ถ”๊ฐ€ ์‚ฌ์šฉ์ž ๊ตฌ์„ฑ์„ ์ด์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

JVM ๋ถ€ํŒ…์— ์‚ฌ์šฉ๋˜๋Š” ๊ธฐ๋ณธ ์ง„์ž…์ ์€ App Engine ๋นŒ๋“œ ํŒฉ์œผ๋กœ ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค. ๊ธฐ๋ณธ์ ์œผ๋กœ appengine-web.xml ํŒŒ์ผ์—์„œ ์ด ์ง„์ž…์ ์„ ์ •์˜ํ•˜๋Š” ๊ฒƒ์€ ๋™์ผํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

java --add-opens java.base/java.lang=ALL-UNNAMED  --add-opens java.base/java.nio.charset=ALL-UNNAMED -showversion -Xms32M -Xmx204M -XX:+UseG1GC -XX:+ParallelRefProcEnabled -XX:+PrintCommandLineFlags -Dclasspath.runtimebase=/base/java_runtime -Djava.class.path=/base/java_runtime/runtime-main.jar -Djava.library.path=/base/java_runtime: com/google/apphosting/runtime/JavaRuntimeMainWithDefaults --fixed_application_path=/workspace /base/java_runtime

๋ฉ”๋ชจ๋ฆฌ ์„ค์ •์€ ์ธ์Šคํ„ด์Šค ์œ ํ˜•(F1, F2, F4) ๋ฐ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ๊ณ„์‚ฐ๋˜๋ฏ€๋กœ ์ด ๊ธฐ๋ณธ ์ง„์ž…์ ์„ ๋ณ€๊ฒฝํ•˜์ง€ ์•Š๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.

๊ธฐ๋ณธ์ ์œผ๋กœ --add-opens java.base/java.lang=ALL-UNNAMED --add-opens java.base/java.nio.charset=ALL-UNNAMED๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ•„์š”ํ•œ JDK API๋ฅผ ์—ฝ๋‹ˆ๋‹ค.

์ง„์ž…์  ๊ธฐ๋Šฅ

appengine-web.xml ๊ตฌ์„ฑ ํŒŒ์ผ์— ์ถ”๊ฐ€๋œ ์‚ฌ์šฉ์ž ์ •์˜๋œ ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ 2์„ธ๋Œ€ Java ๋ฒ„์ „์˜ ์ง„์ž…์ ์„ ๋งž์ถค์„ค์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋‹ค์Œ ํ‘œ์—์„œ๋Š” ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉ ์„ค์ •/์‚ฌ์šฉ ์ค‘์ง€/๊ตฌ์„ฑํ•˜๋Š” ๋ฐ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ํ™˜๊ฒฝ ๋ณ€์ˆ˜์™€ ๊ธฐ๋ณธ๊ฐ’์ด ์„ค์ •๋˜์ง€ ์•Š์€ ๊ฒฝ์šฐ์˜ ๊ธฐ๋ณธ๊ฐ’์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.

ํ™˜๊ฒฝ ๋ณ€์ˆ˜ ์„ค๋ช… ์œ ํ˜• ๊ธฐ๋ณธ๊ฐ’
CPROF_ENABLE Stackdriver Profiler ๋ถ€์šธ false
GAE_MEMORY_MB ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ๋ฉ”๋ชจ๋ฆฌ ํฌ๊ธฐ App Engine ๋˜๋Š” /proc/meminfo-400M์—์„œ ์„ค์ •
HEAP_SIZE_RATIO ํž™์šฉ ๋ฉ”๋ชจ๋ฆฌ ํผ์„ผํŠธ 80
HEAP_SIZE_MB ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ํž™ ํฌ๊ธฐ ${GAE_MEMORY_MB}์˜ ${HEAP_SIZE_RATIO}%
JAVA_HEAP_OPTS JVM ํž™ ์ธ์ˆ˜ JVM ์ธ์ˆ˜ -Xms${HEAP_SIZE_MB}M -Xmx${HEAP_SIZE_MB}M
JAVA_GC_OPTS JVM GC ์ธ์ˆ˜ JVM ์ธ์ˆ˜ -XX:+UseG1GC ๋ฐ ๊ตฌ์„ฑ
JAVA_USER_OPTS JVM ๊ธฐํƒ€ ์ธ์ˆ˜ JVM ์ธ์ˆ˜
JAVA_OPTS JVM ์ธ์ˆ˜ JVM ์ธ์ˆ˜ ์•„๋ž˜ ์ฐธ์กฐ

JAVA_OPTS๋ฅผ ๋ช…์‹œ์ ์œผ๋กœ ์„ค์ •ํ•˜์ง€ ์•Š์œผ๋ฉด ๋‹ค์Œ ๊ธฐ๋ณธ๊ฐ’์ด ์ ์šฉ๋ฉ๋‹ˆ๋‹ค.

   JAVA_OPTS:=-showversion \
              $JAVA_HEAP_OPTS \
              $JAVA_GC_OPTS \
              $JAVA_USER_OPTS

CPROF_ENABLE์ด true์ด๋ฉด ๊ธฐ๋ณธ ์ง„์ž…์ ์ด PROFILER_AGENT๋ฅผ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.

-agentpath:/opt/cprof/profiler_java_agent.so=--logtostderr

์˜ˆ๋ฅผ ๋“ค์–ด ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ฝ”๋“œ์— -add-opens ํ”Œ๋ž˜๊ทธ๊ฐ€ ๋” ํ•„์š”ํ•˜๋ฉด appengine-web.xml ํŒŒ์ผ์— ์ •์˜๋œ JAVA_USER_OPTS ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

    <env-variables>
       <env-var name="JAVA_USER_OPTS" value="--add-opens java.base/java.util=ALL-UNNAMED" />
     </env-variables>

๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ๊ณ ๋ ค์‚ฌํ•ญ

2์„ธ๋Œ€ Java ๋Ÿฐํƒ€์ž„์œผ๋กœ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ํ•  ๋•Œ ๊ทธ๋ฆฌ๊ณ  ์•ฑ์— ๊ธฐ์กด ๋ฒˆ๋“ค ์„œ๋น„์Šค๊ฐ€ ์‚ฌ์šฉ๋˜๋Š” ๊ฒฝ์šฐ์—๋Š” ๋‹ค์Œ ๊ณ ๋ ค์‚ฌํ•ญ์— ์ฃผ์˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.s:

  • 2์„ธ๋Œ€ Java ์•ฑ์—์„œ ๊ธฐ์กด ๋ฒˆ๋“ค ์„œ๋น„์Šค ๊ธฐ๋Šฅ์„ ํ…Œ์ŠคํŠธํ•˜๋ ค๋ฉด ๋กœ์ปฌ ๊ฐœ๋ฐœ ์„œ๋ฒ„๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.
  • Java 8 ๋Ÿฐํƒ€์ž„๊ณผ ๋‹ฌ๋ฆฌ 2์„ธ๋Œ€ Java ๋Ÿฐํƒ€์ž„์—๋Š” JVM์ด ์ธ์Šคํ„ด์Šค ๋ฉ”๋ชจ๋ฆฌ์˜ ์ผ๋ถ€๋กœ ํฌํ•จ๋ฉ๋‹ˆ๋‹ค. ๋กœ๊ทธ์— ๋ฉ”๋ชจ๋ฆฌ ๊ด€๋ จ ์˜ค๋ฅ˜๊ฐ€ ํ‘œ์‹œ๋˜๋ฉด appengine-web.xml ํŒŒ์ผ์—์„œ ์ธ์Šคํ„ด์Šค ํด๋ž˜์Šค ํฌ๊ธฐ๋ฅผ ๋Š˜๋ฆฌ๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.
  • 2์„ธ๋Œ€ Java ๋Ÿฐํƒ€์ž„์—์„œ ์‚ฌ์šฉ ์„ค์ •๋˜์ง€ ์•Š์€ API๋ฅผ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ํ˜ธ์ถœํ•˜๋ ค๊ณ  ํ•˜๋ฉด com.google.apphosting.api.ApiProxy$FeatureNotEnabledException ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.
  • ๋ชจ๋“  ์•ฑ์€ 2์„ธ๋Œ€ Java ๋Ÿฐํƒ€์ž„์—์„œ ์Šค๋ ˆ๋“œ ์•ˆ์ „์œผ๋กœ ๊ฐ„์ฃผ๋ฉ๋‹ˆ๋‹ค. Java 8์—์„œ ์ตœ์‹  Java ๋Ÿฐํƒ€์ž„์œผ๋กœ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ํ•  ๋•Œ app.yaml ๋˜๋Š” appengine-web.xml ํŒŒ์ผ์—์„œ threadsafe ์š”์†Œ๋ฅผ ์‚ญ์ œํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์˜ˆ์‹œ(Datastore)

Datastore ๋ชจ๋“œ(Datastore)์—์„œ Firestore๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์˜ ์˜ˆ์‹œ๋Š” Java 11์šฉ ๊ธฐ์กด ๋ฒˆ๋“ค ์„œ๋น„์Šค์— ๋Œ€ํ•œ GitHub ์ฝ”๋“œ ์ƒ˜ํ”Œ์„ ์ฐธ์กฐํ•˜์„ธ์š”.