자바진영 ( 자바,스칼라,코틀린 ) 에서 모두 활용가능한 패턴으로

RestAPI와 WebSocket의 개발방식의 차이인 StateFul과 Stateless를 먼저알아보고

Reactive 웹소켓을 액터모델과 연동했을때 장점과 확장가능한 샘플코드를 살펴보겠습니다.

Let't go

Stateful VS Stateless

REST API (Stateless 방식)

✔ 개념

✔ 장점

확장성(Scalability) 높음

단순하고 유지보수 용이

캐싱 활용 가능

❌ 단점

실시간성이 부족함

매 요청마다 인증이 필요


🔹 WebSocket (Stateful 방식)

✔ 개념

✔ 장점

실시간 데이터 전송 최적화

네트워크 오버헤드 감소

양방향 통신 가능

❌ 단점

확장성이 낮음

복잡한 상태 관리 필요

브라우저 및 네트워크 제한 사항 존재

🔹 어떤 방식을 선택해야 할까?

REST API가 적합한 경우

WebSocket이 적합한 경우


Spring WebFlux의 org.springframework.web.reactive.socket 기반의 웹소켓과 전통적인 Spring MVC 기반 웹소켓을 비교해보겠습니다.


1. 아키텍처적 차이

비교 항목Spring WebFlux (org.springframework.web.reactive.socket)Spring MVC (전통적인 웹소켓)
스레드 모델Non-blocking, 이벤트 기반 (Netty, Undertow 등 지원)Blocking, Thread-per-connection (Tomcat, Jetty, Undertow)
리액티브 스트림 지원Flux<Message>, Mono<Message> 기반@MessageMapping 기반
동시성 처리요청 처리에 많은 스레드를 사용하지 않음 (적은 리소스로 높은 성능)많은 동시 접속 시 스레드가 증가, 성능 저하 가능
서버 요구 사항Netty, Undertow, Jetty 등 리액티브 지원 서버 필요Tomcat, Jetty, Undertow 지원
부하 분산가볍고 빠르며 부하를 효과적으로 처리 가능높은 동접자 수 처리 시 성능 저하 가능

2. 성능 및 확장성

비교 항목Spring WebFlux (org.springframework.web.reactive.socket)Spring MVC (전통적인 웹소켓)
성능대량의 동시 요청 처리에 유리동시 연결이 많아지면 성능 저하
부하 분산비동기 이벤트 기반 처리로 효율적스레드 증가로 인한 오버헤드 발생
리소스 관리적은 스레드로 많은 요청 처리 가능많은 동시 요청 시 스레드 리소스 소모 증가
지연 처리이벤트 기반으로 낮은 지연 시간스레드가 많아지면 응답 지연 증가

3. 프로그래밍 모델 차이

Spring WebFlux 웹소켓 (비동기, 리액티브)

@Component
class ReactiveWebSocketHandler : WebSocketHandler {
    override fun handle(session: WebSocketSession): Mono<Void> {
        val input = session.receive()
            .map { it.payloadAsText }
            .doOnNext { println("Received: $it") }

        val output = Flux.interval(Duration.ofSeconds(1))
            .map { "Server response $it" }
            .map(session::textMessage)

        return session.send(output)
    }
}




Spring MVC 웹소켓 (동기, Blocking)

@Controller
class TraditionalWebSocketHandler {

    @MessageMapping("/message")
    @SendTo("/topic/response")
    fun handleMessage(message: String): String {
        println("Received: $message")
        return "Server response: $message"
    }
}

4. 사용 시 고려 사항

WebFlux 웹소켓이 유리한 경우

Spring MVC 웹소켓이 유리한 경우


5. 정리

비교 항목Spring WebFlux (org.springframework.web.reactive.socket)Spring MVC (전통적인 웹소켓)
비동기 지원✅ 완전한 비동기 리액티브 모델🚫 동기적 처리
성능✅ 높은 동시성 처리 가능🚫 동접자가 많으면 성능 저하
사용하기 쉬운가?🚫 다소 복잡한 코드 구조✅ 전통적인 MVC 패턴과 유사
서버 호환성🚫 Netty, Undertow 등 필요✅ Tomcat, Jetty 지원
적용 사례✅ 실시간 데이터 스트리밍, 채팅, 알림✅ 단순한 웹소켓 기능

🔥 결론

🚀 즉, 성능과 확장성이 중요한 경우 WebFlux, 익숙한 개발 방식과 기존 시스템 통합이 중요한 경우 MVC 웹소켓을 선택하는 것이 좋습니다.


액터모델이 국내에 개발패턴으로 잘 안알려져 있기도하고 레퍼런스가 부족하지만 이미 성공한 메시징/메신저/통신 테크기업들이 액터모델을 직접 채택하거나 액터모델이 내재화된 프레임워크를 사용하고 있는 것으로 추정합니다.

이 기술을 단지 학습곡선때문에 제외할것이냐? 학습곡선이 높을수 있지만 우리가 필요로하는 스팩이여서 연마가 필요한것인가? 그것을 책임지는 기술팀이 판단해야하는 영역입니다.

학습도에따라 액터모델이 우리에게 고통을 줄수도 있습니다. 액터모델 프로그래밍을 할필요없는 Reactive진영의 우수한 클라우드형 MQ PasS를 채택할수도 있겠지만 ( 트래픽당 클라우드 비용을 잘 계산해야함 )

직접구현 개발모델을 선택한다고 하면  스레드 모델과 비교할수 있습니다.

액터 모델 vs 스레드 모델 비교 요약

비교 항목액터 모델 (Actor Model)스레드 모델 (Thread Model)
동시성 처리경량 액터 기반으로 수천만 개 병렬 처리 가능OS 스레드 기반, 스레드 개수 제한
상태 관리각 액터가 자체적으로 상태 유지 (Stateful)공유 메모리로 상태 관리 (Mutex, Lock 필요)
메시지 전달비동기 메시지 패싱 (No Lock)동기 방식 (Lock, Context Switching 부담)
리소스 효율가벼운 액터 (스레드보다 적은 메모리)스레드마다 메모리(Stack) 사용량 높음
확장성액터 개수와 관계없이 수평 확장 가능 (Cluster 지원)스레드 개수 제한으로 확장성 제한적
안정성액터 단위 장애 격리 가능 (Supervisor Strategy)하나의 스레드 장애 시 전체 영향 가능
데드락 발생메시지 기반 → 데드락 없음공유 메모리 접근 시 데드락 발생 가능
구현 난이도비동기 메시지 기반, 설계 패턴 필요전통적인 동기 방식으로 직관적

🚀 액터 모델의 주요 장점

👉 멀티스레드 환경의 동시성 이슈(Lock, 데드락, 컨텍스트 스위칭)를 해결하고, 확장성과 안정성을 극대화한 모델! 🚀

🔹 액터 모델을 채택한 메시징/메신저 시스템

1. WhatsApp


2. Telegram


3. Microsoft Orleans


4. Akka 기반 메시징 시스템


5. RabbitMQ (Erlang 기반)

6. Apache Flink

7. Ray


🚀 분석: 액터 모델과 웹소켓 연동의 장점

이 코드는 Akka (현재 Apache Pekko) 기반 액터 모델을 활용하여 **웹소켓을 관리하는 세션 관리자(SessionManagerActor)**를 구현한 것입니다.
액터 모델이 웹소켓과 연동될 때 가지는 장점은 다음과 같습니다.


🔹 1. 높은 동시성 및 확장성 (Scalability & Concurrency)

💡 예제 코드 적용:


🔹 2. 상태(State) 유지 및 장애 복구 (Fault Tolerance)

💡 예제 코드 적용:


🔹 3. 비동기 이벤트 기반 처리 (Reactive & Event-driven)

💡 예제 코드 적용:


🔹 4. 트래픽 부하 감소 (Efficient Resource Utilization)

💡 예제 코드 적용:


🔹 5. 확장성 있는 토픽 기반 메시징 시스템 (Scalable Pub/Sub Architecture)

💡 예제 코드 적용:


고성능 IO

AKKA를 소개할때 그것을 프로덕에 적용을 해보았나요? 성능에 문제없나요? 단지 이론에 거치는것을 소개하나요? 라는 질문을 가끔 받기도합니다.

글로벌 기업에 근무할 자바 7인시절 C++ IOCP로작동되는 고성능으로 이루어진 특정 카테고리 글로벌 TOP랭크의 멀티플레이어 서버를  모바일웹에 대응하기위해 C++ 네이티브 분산처리 개발 난이도를 낮추려고 Akka를 성공 적으로 도입하였으며

웹진영에서 AKKA를 사용하면 학습곡선이 높은것에 해당할수 있지만, 분산처리 시스템을 모두 메이드업한 C++시절에서 AKKA는 오히려 분산처리를 단순화하는 툴킷이였습니다.

그래서 고성능 IO관점에서 자바의 네티IO를 리모트장치로 채택할수 있지만 더 성능좋은 IO를 채택할수 있습니다.   단일지점 Remote IO능력으로 본다면 네이테브의 장점으로 IOCPSOCK(C++ WinServer)을 여전히 능가할수 없으며 자바7일시절에도 C++의 단일지점 능력치를 50%만 뽑아내도 성공적인 변환이였습니다. 하지만 단일지점 처리능력보다, 오히려 단일장비 10만이나 처리하는  리소스처리량을 낮추고 더 적고 많은 장치로 트래픽을 분산하는 분산처리 유연함이 더 중요했기때문에 AKKA를 과거 시절 채택을 하였습니다.

C++이 안된다라기보다 이 진영은 액터모델에 준하거나 능가하는 액티브오브젝트 패턴을 직접구현하고 네트워크프로그래밍까지화해 최적화 까지 할수 있는 팀역량을 보유해야 했기때문에 어나더 레벨의 개발구성이 필요한것도 AKKA로 전환한 이유중에 하나였습니다.

도입시 로드테스트 사례및 글로벌 기업


소개가 길었지만~ 본방인 Reactive Websocket과 액터모델을 연동하는 샘플코드를 살펴보겠습니다.

Reactive Websocket with ActorModel 구현체



구현샘플 코드


위 버전은 로컬로 작동되며 , 액터모델을 최초한번 연동하고 나면 액터모델 자체만으로 리모트/클러스터 등으로 확장할수 있습니다.

약간의 액터를 배치하고 Discovery요소및 영속성장치를 활용하게 되지만 핵심은 외부장치의 변화로 도메인을 처리하는 액터로직의 코드 수정이 없다는것이 가장 큰장점이며 이러한 장점으로 액터모델의 학습곡선과 장치를 이해한다고 가정하면

외부장치의 도움없이 로컬 Only 모놀리식으로 시작해 기능구현을 모두 해도 나중에 MSA로 확장시 기존 구현된 코드를 변경할 필요 없는것이 액터모델의 큰장점입니다.

로컬액터가 구현되었을때 확장하는 샘플코드는 별도로 구분하였으며 모든 구현코드는 유닛테스트로 코드를 설명하며 활용방법을 알수 있습니다.

확장하기

확장 장치및 설명


다음장에서는 웹소켓과 여기에 연결된 액터모델을 비동기 수신검사하는 유닛테스트를 알아보겠습니다.

Next : UnitTest Reactive Websocket&Actor