Java 파일들(Verticle, Router, Handler, Service, Repository 등)과 Vert.x 공식 문서를 바탕으로 Vert.x 개발 패턴의 핵심 원칙 및 모범 사례를 종합적으로 분석하여 학습 내용을 정리했습니다.
Vert.x는 JVM 기반의 비동기, 리액티브 애플리케이션 구축을 위한 툴킷이며, 기존의 블로킹(Blocking) 방식 대신 논블로킹(Non-blocking) 및 이벤트 중심(Event-driven) 아키텍처를 채택합니다.
——————————————————————————–
1. Vert.x 개발 패턴의 핵심 원칙
A. 논블로킹 및 멀티 리액터 패턴 (Non-blocking & Multi-Reactor)
• 이벤트 루프(Event Loop)의 황금률: Vert.x에서 가장 중요한 원칙은 **이벤트 루프를 막지 않는 것(Don’t Block the Event Loop)**입니다. Vert.x API는 기본적으로 호출 스레드를 차단하지 않으며, 결과가 즉시 제공되지 않으면 나중에 이벤트를 수신할 **핸들러(Handler)**를 제공해야 합니다.
• 멀티 리액터 패턴: Vert.x는 Node.js와 같은 단일 스레드 리액터 패턴과 달리, Vert.x 인스턴스당 여러 개의 이벤트 루프를 유지하는 **멀티 리액터 패턴(Multi-Reactor Pattern)**을 사용합니다. 이를 통해 단일 Vert.x 프로세스가 서버의 멀티 코어에 걸쳐 확장할 수 있습니다.
• 비동기 결과 처리 (Future): Vert.x 4부터는 비동기 결과를 나타내기 위해 Future 객체를 사용합니다. 비동기 메서드는
Future를 반환하며, .onSuccess(), .onFailure(), .compose() 등을 사용하여 비동기 논리를 연결하고 결과를 처리합니다.B. 배포 및 동시성 관리: Verticle
Vert.x 애플리케이션의 기본 배포 단위(deployment unit)는 **버티클(Verticle)**입니다.
|
Verticle 유형
|
용도
|
특징
|
코드 예시
|
|
Standard Verticles
|
네트워크 I/O 및 논블로킹 작업 (API 처리).
|
이벤트 루프 스레드에 할당되며, 모든 코드가 동일한 이벤트 루프에서 실행되므로 별도의 동기화(synchronization) 없이 단일 스레드로 코드를 작성할 수 있습니다.
|
ApiVerticle, MainVerticle |
|
Worker Verticles
|
블로킹(Blocking) 코드 실행 (예: JDBC, 장기 실행 CPU 작업).
|
이벤트 루프를 막지 않기 위해 **워커 스레드 풀(Worker Thread Pool)**을 사용합니다.
DeploymentOptions에서 .setWorker(true)로 설정하여 배포해야 합니다. |
MigrationVerticle (Flyway DB 마이그레이션 처리) |
|
가상 스레드 Verticles
|
Java 21+에서
await 패턴을 사용하여 동기적인 것처럼 보이는 비동기 코드를 작성할 때 사용됩니다. |
DeploymentOptions에서 ThreadingModel.VIRTUAL_THREAD를 설정합니다. |
N/A (제공된 소스에는 명시적 사용 없음)
|
제공된 소스에서는
MainVerticle이 MigrationVerticle (워커 버티클)을 배포한 후 비동기 체인(.flatMap)을 사용하여 ApiVerticle (표준 버티클)을 배포하는 방식으로 초기화 순서를 제어합니다.2. 모듈식 애플리케이션 구조 및 책임 분리 (N-Tier Architecture)
제공된 Java 파일들은 Vert.x를 사용하여 확장 가능한 RESTful 웹 서비스를 구축할 때 권장되는 N-Tier 아키텍처를 보여줍니다.
A. 웹/라우팅 계층 (Handler/Router Layer)
요청 처리의 시작점이며, Vert.x Web 모듈을 사용합니다.
1. Router (Router): HTTP 요청을 특정 핸들러로 라우팅하는 데 사용됩니다.
2. Handler Chain (핸들러 체인): 요청을 처리하기 위해 여러 핸들러를 순차적으로 연결합니다.
◦ Body Handling:
BodyHandler.create()를 사용하여 요청 본문(request body)을 처리합니다. ◦ Logging:
LoggerHandler.create()를 사용하여 요청 정보를 기록합니다. ◦ Validation (BookValidationHandler):
Vert.x Web Validation 모듈을 사용하여 요청이 비즈니스 로직으로 전달되기 전에 입력 유효성(경로/쿼리 파라미터 및 본문)을 검증합니다. ◦ Error Handling (ErrorHandler):
BadRequestException 등 유효성 검사 오류(400 Bad Request)를 캡처하여 적절한 응답을 구성합니다. ◦ Business Logic (BookHandler):
RoutingContext에서 필요한 정보를 추출하고, 비즈니스 로직을 처리하는 서비스 계층을 호출한 다음, Future.onSuccess() 및 onFailure()를 사용하여 HTTP 응답(200 OK, 201 Created, 204 No Content, 또는 에러)을 구축합니다.B. 서비스 계층 (Service Layer)
BookService는 순수한 비즈니스 로직을 구현하고 트랜잭션을 조정하는 미들웨어 역할을 합니다.• 비동기 트랜잭션 관리:
dbClient.withTransaction(connection -> { ... })을 사용하여 논블로킹 방식으로 데이터베이스 트랜잭션을 관리합니다. 이 패턴은 연결을 얻고, 작업을 수행하고, 성공 시 커밋하거나 실패 시 롤백하는 모든 과정을 비동기적으로 처리합니다.• Future 체이닝:
bookRepository.count(connection).flatMap(...)과 같이 Future를 사용하여 여러 데이터베이스 작업을 비동기적으로 순차 연결합니다.C. 데이터 접근 계층 (Repository Layer)
BookRepository는 데이터 소스 접근 로직(SQL)을 캡슐화하고 도메인 모델(Book POJO)을 데이터베이스와 연결합니다.• Reactive SQL Client:
io.vertx.sqlclient.Pool을 사용하여 데이터베이스에 접근하며, 이는 논블로킹 방식으로 설계되었습니다.• SQL Templating:
SqlTemplate을 사용하여 쿼리 문자열에 변수(#{id}, #{limit})를 매핑하고 결과를 RowMapper나 클래스(Book.class)로 매핑합니다.3. Vert.x 핵심 모듈 활용

제공된 소스 코드는 Vert.x 생태계의 다양한 모듈을 통합하여 프로덕션 환경에 적합한 애플리케이션을 구축하는 방법을 보여줍니다.
|
모듈/기능
|
사용 목적 및 패턴
|
소스 근거
|
|
Vert.x Core
|
Vert.x 인스턴스, Verticle, Event Bus, Future의 기본 기능 제공
|
AbstractVerticle |
|
Vert.x Web
|
HTTP 서버 생성, 라우팅 (
Router), 핸들러 관리 |
ApiVerticle.start(), BookRouter.buildBookRouter() |
|
Web Validation
|
요청 유효성 검사 (JSON Schema DSL, 쿼리/경로 파라미터)
|
BookValidationHandler |
|
Reactive SQL Clients
|
비동기 데이터베이스 접속 및 트랜잭션 관리
|
ApiVerticle에서 Pool 생성, BookService에서 withTransaction 사용 |
|
Monitoring (Micrometer/Prometheus)
|
애플리케이션 성능 및 상태 측정
|
IISLinkDaemonApplication에서 MicrometerMetricsOptions, VertxPrometheusOptions 설정 및 PrometheusScrapingHandler를 통해 /metrics 엔드포인트 노출 |
|
Health Check
|
서비스 가용성(Database 연결 상태) 확인
|
HealthCheckRouter를 통해 /health 엔드포인트 노출 및 DB 연결 체크 로직 등록 |
|
Blocking Code Management
|
Flyway DB 마이그레이션 처리
|
MigrationVerticle을 Worker Verticle로 배포하여 이벤트 루프 차단 방지 |
——————————————————————————–
학습 요약: Vert.x 개발의 비동기적 사고방식
Vert.x 개발의 핵심은 블로킹이 아닌 이벤트 처리 흐름을 설계하는 것입니다. Spring Controller가 요청을 받으면 서비스 메서드를 동기적으로 호출하는 것과 달리, Vert.x의 핸들러는 비즈니스 로직을 서비스 메서드의
Future로 위임하고, 이 Future가 성공하거나 실패할 때까지 기다리지 않고 응답 처리를 위한 onSuccess 콜백을 등록합니다.이는 마치 식당에서 주문(Request)을 받고, 요리(Service/Repository)를 주방(Event Loop)에 비동기적으로 전달한 뒤, 요리가 완성되면(Future 완료) 알림을 받아 손님에게 제공(Response)하는 것과 같습니다. 주방(Event Loop)은 단일 스레드이지만, 주문이 처리되기를 기다리며 놀고 있지 않고, 다른 주문(이벤트)을 계속 처리하여 성능과 확장성을 극대화합니다.