- Published on
모던 Java 2026 — Java 25 LTS / Spring Boot 3.5 / Quarkus / 가상 스레드 / GraalVM 25 / Loom / Panama 심층 가이드
- Authors

- Name
- Youngju Kim
- @fjvbn20031
모던 Java 2026 — Java 25 LTS / Spring Boot 3.5 / Quarkus 심층 가이드
2026년의 Java는 더 이상 "보수적인 엔터프라이즈 언어"가 아니다. Java 21 LTS(2023.9)에서 가상 스레드가 GA로 들어왔고, Java 25 LTS(2025.9)에서는 패턴 매칭이 완성되었으며 가상 스레드는 사실상 기본 모델이 되었다. GraalVM 25 네이티브 이미지는 Spring Boot 3.5에서 일등 시민이 되었고, Quarkus 3.20은 람다와 K8s에서 supersonic / subatomic 부팅 시간을 제공한다. 동시에 토스·카카오 페이·Mercari·LINE·NTT Data·楽天 같은 대형 트래픽 서비스가 여전히 Java/Kotlin/Spring으로 코어를 굴리고 있다. 이 글은 2026년 5월 기준으로 모던 Java 생태계 전체를 한 번에 정리한다.
1. 2026년 모던 Java — Java 21 LTS가 바꾼 것, Java 25 LTS가 마무리한 것
먼저 시계열로 정리하면 다음과 같다.
- Java 17 LTS (2021.9) — Record, Sealed Classes, Pattern matching for
instanceof정착. 많은 엔터프라이즈 코드의 baseline. - Java 21 LTS (2023.9) — Virtual Threads(가상 스레드) GA, Record Patterns, Pattern Matching for switch GA, Sequenced Collections, Generational ZGC(preview). 모던 Java의 분기점.
- Java 22 (2024.3) — Project Panama 의 Foreign Function & Memory API(FFM) GA, Unnamed Variables and Patterns, String Templates(preview).
- Java 23 (2024.9) — Markdown JavaDoc, Primitive Types in Patterns(preview), ZGC default 모드를 Generational 로 전환.
- Java 24 (2025.3) — Compact Object Headers(preview), Stream Gatherers, JEP 491 등 점진 개선.
- Java 25 LTS (2025.9) — 가상 스레드 default 권장(JEP), Module Import Declarations(preview), Pattern matching for switch 최종 안정화, JEP 470 PEM keystore, Generational ZGC default, Compact Object Headers default.
핵심 메시지는 두 가지다. (1) 2026년에 새로 짓는 Java 서비스는 Java 21 또는 Java 25 LTS가 표준이고, Java 17은 "유지 보수 모드". (2) 동시성은 더 이상 "스레드 풀 튜닝" 문제가 아니라 블로킹 코드를 자연스럽게 쓰면 된다는 모델이 보편화됐다. 리액티브 코드의 "콜백 지옥" 시대가 끝났다.
2. Java 25 LTS (2025.9) — 가상 스레드 default, Pattern matching, Module imports
Java 25 LTS의 가장 큰 변화 세 가지를 보자.
2.1 가상 스레드(Virtual Threads)가 사실상 기본값
Java 21에서 GA로 들어온 가상 스레드는 Java 25 LTS에서 "Synchronize Virtual Threads without Pinning"(JEP 491) 등이 안정화되면서 사실상 모든 새 코드의 디폴트가 됐다. 핵심 API는 다음과 같다.
// Java 25 — 가상 스레드를 그대로 쓰는 가장 간단한 예
Thread.startVirtualThread(() -> {
var response = httpClient.send(request, BodyHandlers.ofString());
log.info("got {}", response.statusCode());
});
// Executor 형태
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
IntStream.range(0, 10_000).forEach(i ->
executor.submit(() -> fetchUser(i))
);
} // 자동 join
10,000개의 동시 HTTP 호출을 만들어도 OS 스레드는 수십 개 수준이다. 가상 스레드는 JVM이 carrier 스레드(=ForkJoinPool)에서 협력적으로 마운트/언마운트한다.
2.2 Pattern Matching for switch (확정)
switch가 데이터 형태에 따라 분기하는 진짜 패턴 매칭이 된다.
sealed interface Shape permits Circle, Rect, Triangle {}
record Circle(double r) implements Shape {}
record Rect(double w, double h) implements Shape {}
record Triangle(double b, double h) implements Shape {}
double area(Shape s) {
return switch (s) {
case Circle(double r) -> Math.PI * r * r;
case Rect(double w, double h) -> w * h;
case Triangle(double b, double h) -> 0.5 * b * h;
};
}
sealed interface + record deconstruction + exhaustiveness 체크가 한 묶음으로 들어와서, Scala/Kotlin/Rust에 익숙한 사람이 보던 match와 거의 동일하다. default가 필요 없다는 점이 큰 차이.
2.3 Module Import Declarations (preview)
매 파일 상단의 import java.util.*; import java.util.concurrent.*; 더미를 한 줄로 줄인다.
import module java.base;
import module java.net.http;
void main() {
var client = HttpClient.newHttpClient();
var req = HttpRequest.newBuilder(URI.create("https://example.com")).build();
}
JEP 477(Implicit Classes / Instance Main)과 합쳐지면 작은 스크립트는 거의 Python 수준으로 짧아진다. 학습용·jbang 친화적.
3. Project Loom — 가상 스레드 + Structured Concurrency 실전
Loom의 진짜 가치는 두 가지가 한 묶음으로 들어왔다는 것이다.
3.1 가상 스레드의 동작 모델
가상 스레드는 OS 스레드가 아니라 JVM 힙에 사는 객체다. JVM이 carrier(=플랫폼 스레드) 위에 mount 했다가, I/O 같은 블로킹 지점에서 unmount 하고 다른 가상 스레드를 mount 한다. 핵심 함의는 다음과 같다.
- HTTP 호출, JDBC, 파일 I/O를 그냥 동기 코드로 쓰면 된다.
CompletableFuture체인이나Mono/Flux가 필요 없다. synchronized블록이 carrier를 pin 시키는 문제는 JEP 491(Java 24)에서 해결됐다. Java 25 LTS부터는synchronized도 일반적으로 안전.- 가상 스레드는 절대 풀링하지 마라. 풀이 곧 안티패턴. 매 요청마다 새로 만든다.
3.2 Structured Concurrency(JEP 480 / 505)
여러 동시 작업을 부모-자식 구조로 묶는다. 자식이 실패하면 형제도 같이 취소된다.
import jdk.incubator.concurrent.StructuredTaskScope;
record UserDashboard(User user, List<Order> orders, List<Notice> notices) {}
UserDashboard build(long userId) throws Exception {
try (var scope = new StructuredTaskScope.ShutdownOnFailure()) {
var userF = scope.fork(() -> userService.findById(userId));
var ordersF = scope.fork(() -> orderService.findByUser(userId));
var noticesF = scope.fork(() -> noticeService.findByUser(userId));
scope.join(); // 모두 끝날 때까지 대기
scope.throwIfFailed(); // 하나라도 실패하면 전파
return new UserDashboard(userF.get(), ordersF.get(), noticesF.get());
}
}
세 작업이 진정한 의미에서 부모와 lifecycle 을 공유한다. 부모가 인터럽트되면 자식도 같이 죽고, 스택 트레이스도 부모-자식 관계가 보존된다. 실무에서는 "한 요청 = 한 scope"가 표준이 된다.
3.3 Scoped Values(JEP 506)
ThreadLocal을 대체하는, 가상 스레드 환경에서 안전하고 효율적인 컨텍스트 전파 메커니즘.
private static final ScopedValue<String> REQUEST_ID = ScopedValue.newInstance();
void handle(HttpRequest req) {
ScopedValue.where(REQUEST_ID, req.header("x-request-id"))
.run(() -> business());
}
void logInfo() {
log.info("request-id={}", REQUEST_ID.get());
}
ThreadLocal과 달리 (1) 불변이고 (2) scope 가 끝나면 자동 해제되며 (3) 가상 스레드 간 복사 비용이 거의 없다. 가상 스레드를 본격적으로 쓴다면 ThreadLocal 은 신중하게 줄여 가는 게 좋다.
4. Spring Boot 3.5 — Native + GraalVM 통합
Spring Boot 3.5(2025.5 GA)는 Java 17 minimum, Java 21/25 권장, Jakarta EE 11 기반이다. 핵심 포인트.
4.1 가상 스레드를 한 줄로 켠다
# application.properties
spring.threads.virtual.enabled=true
이 한 줄이면 Tomcat / Jetty / Undertow 가 요청 핸들러를 가상 스레드로 실행한다. @Async 의 기본 풀도 가상 스레드 기반으로 전환할 수 있다.
@Configuration
class AsyncConfig implements AsyncConfigurer {
@Override public Executor getAsyncExecutor() {
return Executors.newVirtualThreadPerTaskExecutor();
}
}
DB 커넥션 풀(HikariCP), Reactor Netty 클라이언트, 외부 HTTP 호출은 그대로 사용 가능. 단 synchronized 가 많은 라이브러리는 Java 25 권장.
4.2 GraalVM Native Image 정식 지원
# Spring Boot + GraalVM native image
./mvnw -Pnative native:compile
# 또는 cloud-native buildpack
./mvnw spring-boot:build-image -Pnative
- 부팅 시간 50
100ms 수준(JVM은 보통 13초). - 메모리는 JVM 대비 1/3~1/5 수준.
- 단, AOT 컴파일 시간이 길고 reflection/proxy 가 많은 라이브러리는 hint 가 필요.
Spring Boot 3.5는 @RegisterReflectionForBinding 같은 hint 어노테이션이 정착해 있어서, 대부분의 Spring Data / Jackson / JPA 코드는 hint 없이도 native 컴파일된다.
4.3 Observability 1급 시민
Micrometer + Tracing(Brave/OpenTelemetry) 이 기본 의존성에 들어 있다. OTel Java agent 없이도 @Observed 어노테이션 하나로 span 이 생긴다.
@Service
class OrderService {
@Observed(name = "order.create")
public Order create(OrderRequest req) { /* ... */ }
}
OTel collector 로 보내려면 management.otlp.tracing.endpoint 한 줄 추가하면 된다.
5. Quarkus 3.20 — Supersonic Subatomic Java
Quarkus(Red Hat)는 Kubernetes-native Java를 표방한다. 핵심 차별점.
5.1 부팅 시간 / 메모리 우위
- JVM 모드: 1
2초 부팅, 100200MB RSS. - Native 모드(GraalVM): 20
30ms 부팅, 3050MB RSS.
이 숫자가 Knative / Lambda / Cloud Run 같은 serverless 환경과 잘 맞는다. scale-to-zero 가 의미 있게 작동한다.
5.2 개발 경험 — Dev Mode + Continuous Testing
./mvnw quarkus:dev
- 파일 저장하는 순간 핫 리로드.
r누르면 변경된 파일만 테스트 재실행(continuous testing).- 내장 Dev UI(http://localhost:8080/q/dev/)에서 확장 설정, DB 쿼리, REST endpoint 호출까지 가능.
5.3 코드 예시 — REST + Panache + Reactive
@Path("/users")
public class UserResource {
@GET @Path("/{id}")
public Uni<User> get(@PathParam("id") Long id) {
return User.<User>findById(id);
}
@POST
public Uni<Response> create(User user) {
return Panache.withTransaction(user::persist)
.replaceWith(Response.created(URI.create("/users/" + user.id)).build());
}
}
Uni/Multi(SmallRye Mutiny)가 기본 reactive 타입이다. 단, Quarkus 3.x부터는 RESTEasy Reactive + Hibernate Reactive를 쓰지 않고 일반 blocking 모드를 가상 스레드와 함께 쓰는 패턴이 일반화됐다.
5.4 확장 생태계
quarkus- 접두어 확장이 600개 이상. Kafka, gRPC, Redis, Vault, Keycloak, Kubernetes-config, OpenAPI, MicroProfile 전체 — 거의 모든 게 1급으로 들어와 있다.
6. Micronaut 4 — Reactor 친화
Micronaut 4 의 차별점은 컴파일 타임 DI다. 리플렉션 대신 어노테이션 프로세서로 빈 메타데이터를 생성하기 때문에, native image 가 잘 맞는다.
@Controller("/hello")
public class HelloController {
@Get(uri = "/{name}", produces = MediaType.TEXT_PLAIN)
public String hello(String name) {
return "Hello, " + name;
}
}
- Project Reactor 와 자연스럽게 어울린다. Spring WebFlux 사용자가 옮겨 오기 쉽다.
- GraalVM native image 가 기본 시나리오. 컴파일 시간이 Spring 보다 짧다.
- AWS Lambda / GCP Cloud Functions / Azure Functions 어댑터가 1급으로 들어 있다.
토스 / 카카오 같은 회사들은 Spring 이 절대 다수지만, 일부 신규 서비스에 Micronaut 를 도입해 콜드 스타트를 낮춘 사례가 보고되고 있다.
7. Helidon 4 / Vert.x 5 — 그 외 옵션
7.1 Helidon 4 (Oracle)
Oracle 이 주도하는 microservices 프레임워크. Helidon Nima 라는 새 웹 엔진은 처음부터 가상 스레드 위에서 동작하도록 설계됐다(Netty 사용 안 함).
public class Main {
public static void main(String[] args) {
WebServer.builder()
.routing(r -> r.get("/hello", (req, res) -> res.send("Hello")))
.build()
.start();
}
}
Netty 없이 가상 스레드를 직접 carrier 로 쓰기 때문에, 동시성 모델이 가장 단순하다. JVM 메모리 사용량도 매우 낮다. Oracle Cloud 환경과 잘 맞는다.
7.2 Vert.x 5
이벤트 루프 기반의 reactive toolkit. 한 노드에서 매우 높은 동시 연결을 처리해야 할 때 유리하다.
Vertx vertx = Vertx.vertx();
vertx.createHttpServer()
.requestHandler(req -> req.response().end("Hello"))
.listen(8080);
Vert.x 5 는 reactive 와 함께 가상 스레드 모드도 지원해서, 콜백 지옥 없이도 쓸 수 있다. 메시지 게이트웨이, IoT 게이트웨이, WebSocket 서버처럼 연결 수가 폭발하는 워크로드의 단골.
8. ZGC — sub-ms pause GC
Java 25 LTS 기준으로 Generational ZGC가 기본 GC가 됐다.
8.1 왜 중요한가
기존 G1 GC 가 수십수백 ms의 STW(stop-the-world) pause 를 낼 수 있는 반면, ZGC 는 GC pause 가 1ms 이하다. 힙 크기가 수십수백 GB여도 동일한 pause 특성을 보인다.
8.2 켜는 법
java -XX:+UseZGC -Xmx16g -jar app.jar
Java 21 부터는 -XX:+ZGenerational 로 generational 모드를 켰는데, Java 25 LTS 에서는 그게 디폴트가 됐다.
8.3 트레이드오프
- 처리량(throughput)은 G1 대비 약간 낮을 수 있다(보통 5~10%).
- 메모리 footprint 가 G1 보다 크다(color pointer 오버헤드).
- 결제 / 트레이딩 / 광고 입찰처럼 p99 지연이 핵심 KPI인 워크로드에서 진가를 발휘한다.
토스의 결제 게이트웨이, Mercari의 주문 처리 같이 p99 가 SLA 인 경우 ZGC가 사실상 표준이다.
9. Project Valhalla — value types
Valhalla 는 여전히 "곧 나온다"의 영역이지만, 2026년 시점에서는 value types(JEP 401 / 402) 가 preview 단계까지 와 있다.
9.1 무엇이 바뀌나
value class Point {
int x;
int y;
}
Point는 identity 가 없는 객체. 즉==비교가 값 비교.- JVM 이 flatten 해서 배열에 인라인 저장할 수 있다.
Point[]가 진짜 연속된 메모리. - 박싱 비용이 사라진다.
int처럼 동작하지만 클래스 인터페이스를 가진다.
9.2 왜 중요한가
지금까지 Java 의 객체는 무조건 힙에 포인터로 살았다. 수치 컴퓨팅, ML 텐서, 게임 엔진처럼 "수십 만개의 작은 객체"를 다루는 워크로드에서는 박싱과 캐시 미스 때문에 C++/Rust 대비 큰 손해를 봤다. Valhalla 가 GA 되면 그 격차가 상당 부분 사라진다. 2026년 기준으로 production 적용은 시기상조지만, ML 라이브러리(DJL 등)는 이미 준비 중이다.
10. Project Panama (FFI, Java 22 GA) — jextract와 함께
Panama 의 Foreign Function & Memory API(FFM)는 Java 22에서 GA 됐다. JNI 의 후계자이자 훨씬 안전한 대안.
10.1 기본 사용 — C 함수 호출
import java.lang.foreign.*;
import static java.lang.foreign.ValueLayout.*;
try (Arena arena = Arena.ofConfined()) {
Linker linker = Linker.nativeLinker();
SymbolLookup stdlib = linker.defaultLookup();
MethodHandle strlen = linker.downcallHandle(
stdlib.find("strlen").orElseThrow(),
FunctionDescriptor.of(JAVA_LONG, ADDRESS)
);
MemorySegment cString = arena.allocateUtf8String("Hello, Panama!");
long len = (long) strlen.invoke(cString);
System.out.println(len); // 14
}
JNI 와 비교한 장점.
Arena가 메모리 lifecycle 을 관리해서 누수가 거의 불가능.- 안전한 메모리 액세스(off-heap 인데 bounds-check).
- C 헤더에서 자동 생성된 바인딩(jextract)을 쓸 수 있어 boilerplate 가 거의 없다.
10.2 jextract — C 헤더에서 Java 바인딩 자동 생성
# 예: SQLite 의 C 헤더에서 Java 바인딩 생성
jextract --source --output gen \
-t org.sqlite.ffi \
/usr/include/sqlite3.h
org.sqlite.ffi.sqlite3_h 같은 클래스가 생성되고, sqlite3_open/sqlite3_exec 같은 함수가 Java MethodHandle 로 노출된다. 결과적으로 JNI 없이도 native 라이브러리를 사용할 수 있다.
10.3 적용 사례
- 고성능 압축(zstd, snappy) 라이브러리.
- 머신러닝 추론(ONNX Runtime, llama.cpp) 통합.
- HW 가속(CUDA, Apple Metal) 호출.
- 메모리 매핑 파일을 가공해야 하는 OLAP 엔진(예: Apache Arrow).
JNI 시절에는 "성능 때문에 어쩔 수 없이" 썼지만, Panama 시대에는 "기본 옵션"이 됐다.
11. Project Babylon — JVM의 GPU/AI 컴퓨트
Babylon(2024~)은 OpenJDK 의 새 프로젝트. Code Reflection 이라는 기능을 통해 Java 코드를 다른 프로그래밍 모델(GPU, SQL, 미분 가능 함수 등)로 변환할 수 있게 한다.
11.1 동기
지금까지 Java 에서 GPU 를 쓰려면 (1) JNI 로 CUDA 콜, (2) ONNX Runtime / TornadoVM 같은 외부 도구를 거쳤다. Babylon 의 목표는 순수 Java 코드를 그대로 GPU 커널로 컴파일할 수 있는 표준 API 를 제공하는 것.
11.2 그림으로
Java source Reflected method body (IR) Target backend
@CodeReflection ────► Op tree (SSA) ────► SPIR-V / PTX / SQL / ...
void matmul(...) { }
Babylon 은 라이브러리 작성자들이 자신만의 어노테이션 + IR consumer 를 만들도록 하는 인프라다. 예를 들어 TornadoVM 이나 HAT(Heterogeneous Accelerator Toolkit) 가 Babylon 위에서 동작한다.
11.3 2026년의 의미
Java 는 AI/ML 의 "서비스 계층" 언어로 자리를 굳혔지만, "학습/추론 계층"에서는 항상 Python 에 밀렸다. Babylon 이 안정화되면, Java 에서 직접 GPU 커널을 쓸 수 있게 되어 추론 서비스의 일부를 native 화하는 길이 열린다. 아직 incubating 단계지만, 방향이 옳다.
12. GraalVM 25 — native image
GraalVM 25 (2025.9)는 OpenJDK 25 와 같이 릴리스됐다. 핵심 가치는 두 가지.
12.1 Native Image
# Spring Boot / Quarkus / Micronaut 어느 쪽이든
native-image --no-fallback -jar app.jar
- 부팅: 20~100ms.
- 메모리: JVM 대비 1/3~1/5.
- 단점: 빌드 시간이 길다(수 분), reflection / proxy / resource 로딩이 명시적이어야 한다.
Spring Boot 3.5 + GraalVM 25 조합은 reachability metadata 가 자동 수집되어, 대부분의 Spring 표준 코드는 hint 없이 native 화된다.
12.2 Polyglot
GraalVM 위에서 JavaScript / Python / Ruby / Wasm / R / LLVM bitcode 가 같이 돈다. Java 함수에서 JS 함수를 그대로 호출 가능. 예시.
try (Context ctx = Context.create("js")) {
Value array = ctx.eval("js", "[1,2,3]");
System.out.println(array.getArraySize()); // 3
}
실무에서는 polyglot 보다 native image 쪽이 훨씬 자주 쓰인다.
12.3 Oracle GraalVM vs GraalVM CE
Java 21 부터 Oracle GraalVM 이 GFTC 라이선스(서비스 자유 사용 + GraalVM 의 fast-path 컴파일러 포함)로 풀렸다. CE 와 EE 의 구분이 사라지고, 사실상 무료로 production 에 쓸 수 있다.
13. Maven 4 + Gradle 9 + jbang
13.1 Maven 4
10년 만의 메이저 업그레이드. 핵심 변화.
pom.xmlconsumer/build POM 분리 — 배포되는 POM 이 깔끔해진다.- 멀티 모듈 빌드의 의존성 자동 추론.
- 빌드 캐시 / 병렬 빌드 강화.
mvn대신mvnup/mvnsh등의 새 도구 추가.
기존 pom.xml 은 거의 그대로 동작하므로, 큰 마이그레이션 부담은 없다.
13.2 Gradle 9
- Configuration Cache 가 안정화 —
gradle build가 캐시 hit 시 거의 즉시 시작. - Kotlin DSL 이 권장. Groovy DSL 도 계속 지원되지만 신규 프로젝트는 Kotlin DSL 권장.
- Build Authoring 가이드(
buildSrc→ version catalog) 가 표준화.
plugins {
id("org.springframework.boot") version "3.5.0"
id("io.spring.dependency-management") version "1.1.6"
kotlin("jvm") version "2.1.0"
}
dependencies {
implementation("org.springframework.boot:spring-boot-starter-web")
implementation("org.springframework.boot:spring-boot-starter-data-jpa")
runtimeOnly("org.postgresql:postgresql")
}
13.3 jbang — Java 스크립트화
# 단일 파일에서 Spring Boot 앱 실행
jbang hello.java
///usr/bin/env jbang "$0" "$@" ; exit $?
//DEPS info.picocli:picocli:4.7.6
import picocli.CommandLine;
import picocli.CommandLine.Command;
@Command(name = "hello")
public class hello implements Runnable {
public void run() { System.out.println("Hello from jbang!"); }
public static void main(String[] args) { new CommandLine(new hello()).execute(args); }
}
//DEPS 주석으로 의존성을 선언하고, Maven 의 dependency resolver 가 자동으로 가져온다. CLI 도구, CI 자동화 스크립트, ad-hoc 데이터 처리에 매우 유용. Java 25 의 Implicit Classes(JEP 477) 와 함께 쓰면 거의 Python 수준으로 짧다.
14. 한국 / 일본 — 토스, 카카오 페이, Mercari, LINE, NTT Data, 楽天
14.1 한국
- 토스(Toss) — 코어 결제·송금 시스템은 여전히 Java + Spring Boot가 다수. 일부 신규 서비스는 Kotlin/Spring 으로 작성. 2024년부터 가상 스레드 도입 사례 공유 시작. ZGC 도 결제 게이트웨이의 표준 GC.
- 카카오 페이 — Java + Spring Boot 가 중심. Kafka 기반의 이벤트 드리븐 아키텍처. Reactive 와 함께 가상 스레드를 점진 도입.
- 네이버 / 라인 — 다수의 서비스가 Java/Kotlin/Spring. LINE Pay 는 일본 시장 대응을 위해 한국·일본·대만 멀티 리전.
- 쿠팡 — Java + Spring + Kafka 가 중심. 최근에는 일부 신규 서비스에 Kotlin 비중 증가.
14.2 일본
- メルカリ(Mercari) — 검색·추천 등 일부 ML 인근은 Go/Python 이지만, 상품·결제·정산은 Java/Kotlin. JVM 운영 노하우(JVM GC 튜닝, ZGC) 공유로 유명.
- LINE 야후 — Java + Kotlin + Spring 의 대규모 사용 사례. Vert.x 기반의 메시지 게이트웨이도 일부 운영.
- NTT Data — 엔터프라이즈 SI 의 표준. 미션 크리티컬 시스템에 Java 17/21 LTS 가 정착. Spring Boot 와 함께 Helidon / Quarkus 도 채택.
- 楽天(Rakuten) — 글로벌 e-커머스 플랫폼은 Java + Spring 이 다수. 일본 통신(Rakuten Mobile)에서는 Reactive 와 함께 Vert.x 도 활용.
- デンソー(Denso) / Sony / Hitachi — 임베디드·IoT 게이트웨이에서 Helidon Nima 가 채택되는 사례 증가.
공통점은 "Java/Kotlin/Spring 모노리스 + Kafka 이벤트 드리븐 + 일부 신규 서비스에 가상 스레드 / Native Image"라는 패턴이다.
15. 누가 Java/Spring을 골라야 하나 — 엔터프라이즈 / 금융 / 모노리스 / 멀티-언어 팀
15.1 강력 추천
- 엔터프라이즈 / 금융 / 통신 — 규제, 감사 추적, 장기 유지보수가 핵심. Java 25 LTS 의 8년 지원, Spring 의 생태계, Quarkus 의 운영 도구는 다른 언어가 따라오기 어렵다.
- 모노리스에서 출발하는 신규 서비스 — Spring Boot 의 "convention over configuration" 이 압도적으로 빠른 출발을 보장. 모듈 분리는 나중에.
- JVM 라이브러리 자산이 큰 팀 — Kafka, Hadoop, Spark, Flink, Cassandra, Elasticsearch — 데이터 인프라의 거의 전부가 JVM. 같은 언어로 운영·통합·디버깅 가능.
15.2 조건부 추천
- 콜드 스타트가 핵심인 serverless — Quarkus + GraalVM 또는 Micronaut + GraalVM. Java/Spring 일반 조합은 콜드 스타트가 약하다.
- 연결 수 폭발(IoT, WebSocket, 게임 서버) — Vert.x 또는 Helidon Nima 가 더 적합.
- 데이터 사이언스 / ML 학습 파이프라인 — 여전히 Python 이 우세. Java 는 서비스 계층 / 추론 게이트웨이.
15.3 비추천
- CLI 단일 바이너리 도구 — Go / Rust 가 더 자연스럽다. 단, jbang + GraalVM 조합은 의외로 경쟁력 있음.
- 시스템 프로그래밍 — Rust / C++ / Zig.
15.4 Java vs Kotlin
같은 JVM 위지만 선택 기준이 다르다. Java 는 "조직 표준이 Java" 또는 "라이브러리가 Java 위주"일 때, Kotlin 은 "DSL 이 많은 도메인" 또는 "Android 와 코드를 공유"할 때. Spring 은 Kotlin 도 1급 지원하므로 신규 서비스에서 Kotlin 을 채택하는 한국·일본 회사가 빠르게 늘고 있다.
참고 / References
- OpenJDK — Java 25 LTS
- JEP Index
- JEP 444 — Virtual Threads (Java 21)
- JEP 480 / 505 — Structured Concurrency
- JEP 506 — Scoped Values
- JEP 491 — Synchronize Virtual Threads without Pinning
- JEP 441 — Pattern Matching for switch
- JEP 511 — Module Import Declarations
- JEP 454 — Foreign Function & Memory API (Java 22 GA)
- Project Loom
- Project Valhalla
- Project Panama
- Project Babylon
- Spring Boot 3.5 Release Notes
- Quarkus
- Micronaut
- Helidon
- Vert.x
- GraalVM
- Maven 4
- Gradle 9
- jbang
- jextract
- Mercari Engineering Blog
- LINE Engineering Blog