작성해놓고보니 이전에도 비슷한 포스팅을 했었다.
리액터
프로젝트 리액터는 JVM 환경에서 리액티브 애플리케이션을 개발할 수 있도록 지원하는 오픈 소스 프레임워크이다.
coroutine
코루틴은 실행을 일시 중지(suspend)하고 재개할 수 있는 컴퓨터 프로그램 구성 요소로, 협동적 멀티태스킹을 위한 서브루틴입니다.
둘의 공통점이 있다.
- 스레드를 오래 붙잡지 않는다
- 작업이 끝날 때까지 기다리지 않는다
- 높은 동시성을 목표로 한다
이런 공통점 때문에 두 개가 같은 개념인 줄 착각했는데...
spring boot에서 리액터와 coroutine은 둘 다 동작하지만 동작 방식이 약간 다르다.
리액터를 먼저 살펴보자
- Lazy 방식으로 동작해서, subscribe()가 호출되기 전까지는 연산자가 실행되지 않는다.
이 말을 이해하기 위해서 아래 예제 코드를 보자.
fun main() {
service() // A가 출력된다 // B는 출력되지 않는다 (subscribe이 되지 않았기 때문에)
println("C") // C가 출력된다
}
fun service(): Mono<Int> { // 리액터는 Mono와 Flux 타입을 사용한다.
println("A") // A가 출력된다
return Mono.just(1)
.map {
println("B") // subscribe가 되지 않았기 때문에, B는 출력되지 않는다.
it + 1
}
}
main()함수가 실행되면 이 코드는
A
C
를 출력한다.
B는 출력하지 않는다. subscribe()가 되지 않았기 때문이다.
fun main() {
service().subscribe() // A가 출력된다 // subscribe()를 붙여주었기 때문에, B가 출력된다!
println("C") // C가 출력된다.
}
main함수를 위처럼 고치면 A B C가 순서대로 출력된다.
그러면 코루틴은 어떨까?
suspend fun main(args: Array<String>) {
serviceB() // A가 출력된다 // B가 출력된다
println("C") // C가 출력된다
}
suspend fun serviceB(): Int {
println("A")
val x = 1
println("B")
return x + 1
}
main을 실행하면 A B C 가 차례대로 출력된다.
subscribe()같은게 없어도 말이다~~
그럼 spring boot에는 왜 이 둘이 섞여있는거임?
spring webFlux는 Reactor 기반 프레임워크다.
코루틴은 추가레이어 정도의 개념이다.
[Netty Event Loop]
↓
Reactor
↓
(옵션) Coroutine Adapter
suspend라는 키워드가 있을 경우 스프링은 실행 모델을 명확히 할 수 있다.
코루틴 실행 모델을 쓰라고 할 수 있는 것.
그걸 CoroutineHandlerAdapter 라고 하는데...
CoroutineHandlerAdapter
Spring WebFlux 에서는 어떻게 Kotlin Coroutine 을 지원하고 있을까? ( feat. Context )
(아래 내용은 위 블로그의 내용을 내가 지금 이해하기 위해서 간략히 편집한 것으로 원 포스팅을 읽어봅시다)
WebFlux 에서 HTTP 요청의 흐름은 아래 순서대로 흘러간다.
1. org.springframework.web.server.WebFilter
2. org.springframework.web.reactive.DisptacherHandler
3. org.springframework.web.reactive.HandlerAdapter
HandlerAdpator 의 구현체인 RequestMappingHandlerAdapter의 invoke 함수를 따라가보면
invoke target method 가 suspend 함수인지 여부를 체크하여 suspend 함수라면 별도의 invoke 메서드를 호출
여기에서 핵심은 Mono 에서 Coroutine 으로 변환된다.
심지어 Reactor 에서 관리되는 Context 들을 CoroutineContext 로 변환하여 저장할 수 있도록 하고 있다.
즉, Reactor 진영에서 관리하는 객체들을 Coroutine 진영의 객체로 변환하여 가져올 수 있다는 것을 의미한다.
'【 개발 이야기 】' 카테고리의 다른 글
| timeout의 종류와 발생원인에 대해서 알아보자 (0) | 2026.04.13 |
|---|---|
| github oshai (0) | 2026.01.22 |
| 리눅스 읽기쓰기 권한 읽는 법 (0) | 2026.01.06 |
| spyk는 뭔 일을 하나요 (0) | 2025.12.26 |
| 패스파라미터와 쿼리파라미터 (0) | 2025.12.04 |