3. 리액티브 라이브러리 비교
생태계별 타입
라이브러리 | 단일 값 | 여러 값 | 주 사용처 |
Project Reactor | Mono<T> | Flux<T> | Spring WebFlux |
Mutiny | Uni<T> | Multi<T> | Quarkus/Vert.x |
RxJava | Single<T> | Observable<T> | Android |
Kotlin Coroutine | Deferred<T> | Flow<T> | Kotlin 전반 |
Java 표준 | CompletableFuture<T> | Stream<T> | Java 전반 |
Mutiny란?
Quarkus/Vert.x 생태계의 리액티브 프로그래밍 라이브러리
// Uni - 단일 값 비동기 처리 (Mono와 동일한 역할)
Uni<User> user = userRepository.findById(1L);
// Multi - 여러 값 스트리밍 (Flux와 동일한 역할)
Multi<User> users = userRepository.findAll();
Java
복사
Mono vs Uni
거의 동일한 개념. 다른 라이브러리의 같은 역할을 하는 타입.
특성 | Mono (Reactor) | Uni (Mutiny) |
생태계 | Spring WebFlux | Quarkus/Vert.x |
API 스타일 | 풍부하고 복잡 | 단순하고 직관적 |
연산자 수 | 많음 (100+) | 적음 (핵심만) |
4. Kotlin Coroutine
Coroutine이란?
경량 스레드. 비동기 코드를 동기 코드처럼 작성할 수 있게 해줌.
// 콜백 지옥 (기존)
fetchUser { user ->
fetchOrders(user.id) { orders ->
fetchItems(orders) { items ->
// 중첩...
}
}
}
// 코루틴 (깔끔)
suspend fun process() {
val user = fetchUser()
val orders = fetchOrders(user.id)
val items = fetchItems(orders)
}
Kotlin
복사
Deferred<T>란?
코루틴의 비동기 결과를 담는 컨테이너. async로 생성.
val deferred: Deferred<Int> = async {
delay(1000)
42
}
val result: Int = deferred.await() // 42
Kotlin
복사
asUni()란?
Kotlin Deferred<T>를 Mutiny Uni<T>로 변환하는 확장 함수.
// 변환 흐름
CoroutineScope(...).async {
block(queryHelper) // Kotlin Coroutine
}.asUni() // Deferred → Uni 변환
.awaitSuspending() // Uni → suspend로 복귀
Kotlin
복사
왜 필요한가?
•
Hibernate Reactive는 Mutiny 기반
•
비즈니스 코드는 Kotlin Coroutine 기반
•
두 세계를 연결하기 위해 변환 필요
5. suspend 키워드
정의
•
*"일시 중단 가능한 함수"**를 표시하는 Kotlin 키워드.
// 일반 함수 - 스레드 블로킹
fun fetchUser(): User {
Thread.sleep(1000) // 스레드가 1초간 멈춤 (낭비)
return user
}
// suspend 함수 - 스레드 양보
suspend fun fetchUser(): User {
delay(1000) // 스레드 반납하고 기다림 (효율적)
return user
}
Kotlin
복사
suspend가 효과 있는 경우
상황 | 예시 |
네트워크 I/O | HTTP 호출, API 요청 |
DB I/O | 쿼리 실행, 데이터 조회 |
파일 I/O | 파일 읽기/쓰기 |
지연 | delay(), 타이머 |
suspend가 의미 없는 경우
// ❌ 순수 CPU 연산 - 중단할 타이밍 없음
suspend fun calculateSum(): Long {
var sum = 0L
for (i in 1..1_000_000_000) sum += i
return sum
}
// ❌ 블로킹 라이브러리 감싸기만 한 경우
suspend fun badExample(): String {
return blockingHttpClient.get("/api")
}
Kotlin
복사
핵심 정리
suspend는 "기다리는 시간"이 있을 때만 효과가 있다.
CPU가 계속 일하는 연산에는 의미 없음.
6. 현재 프로젝트 아키텍처
┌─────────────────────────────────────────────────┐
│ api server
├─────────────────────────────────────────────────┤
│ Controller │ Spring WebFlux (Mono/Flux) │
│ Service │ Kotlin Coroutine (suspend) │
│ Repository │ Hibernate Reactive (Mutiny) │
└─────────────────────────────────────────────────┘
변환 흐름:
Mono ←→ Coroutine (suspend) ←→ Uni
Plain Text
복사