본문 바로가기
Database , Middleware/Redis

Redis와 Event Loop 그리고 Netty, Virtual Thread

by 방배킹 2025. 11. 17.

Redis가 빠른 이유는 인메모리 기반으로 동작하기 때문이며, 여기에 더해 단일 스레드 + Event Loop 구조를 사용하기 때문이다.
그렇다면 단일 스레드 기반의 Event Loop 구조는 왜 빠른 걸까?
이번 글에서는 Redis의 Event Loop 구조를 중심으로, Netty의 Event Loop, Event Loop의 핵심 특징인 Non-blocking I/O, 그리고 논블로킹처럼 보이지만 다른 개념인 Java Virtual Thread까지 함께 정리해보려고 한다.

Redis가 단일 스레드를 선택한 이유

Redis는 설계 단계부터 초고속, 저지연 처리를 목표로 삼았고, 이를 위해 단일 스레드라는 매우 단순하지만 강력한 전략을 선택했다.

1. 락(lock)이 필요 없다 (경쟁 비용 제거)

멀티스레드 환경에서는 공유 자원에 접근할 때 반드시 락이 필요하다. 하지만 락에는 다음과 같은 비용이 따른다.

  • 락 획득 대기 시간
  • Race Condition 방지 비용
  • 데드락 위험
  • 락 경합(lock contention)으로 인한 성능 저하

특히 Redis는 인메모리 기반이기 때문에, 락에서 발생하는 오버헤드는 디스크 기반 DB보다 훨씬 크게 작용한다.
이 때문에 Redis는 모든 명령을 단일 스레드에서 순차적으로 처리하여 락 비용을 완전히 제거했다.

2. 컨텍스트 스위칭 비용 제거 (CPU 효율 극대화)

멀티스레드 시스템에서는 CPU가 스레드를 교체하는 과정에서 컨텍스트 스위칭(Context Switching)이 발생하며, 이는 자체적으로 비용을 갖는다.
Redis는 단일 스레드 구조이기 때문에 컨텍스트 스위칭 비용이 사실상 0에 가깝다.
이러한 락 제거와 컨텍스트 스위칭 제거를 통해 Redis는 매우 효율적인 성능을 얻을 수 있었다.

Event Loop란?

Event Loop는 이벤트를 큐에 넣고, 단일 스레드가 이를 반복적으로 처리하는구조를 가진다.
대표적인 Event Loop 기반 시스템은 다음과 같다. (Redis, Netty, Node.js, Nginx)

Event Loop 핵심 구성

1. 단일 스레드 + 작업 큐(Queue)

Event Loop는 내부에 하나의 이벤트 큐를 가지고 있으며, 단일 스레드는 큐에 쌓인 이벤트를 하나씩 꺼내 처리한다.

2. Non-blocking I/O 기반

Event Loop가 빠른 이유는 Non-blocking I/O 기반이기 때문이다.
Blocking I/O라면 I/O 작업이 발생하는 순간 스레드가 멈추게 되고, 싱글 스레드 구조에서는 이로 인해 전체 시스템이 정지하는 문제가 발생한다.
반면 Non-blocking I/O는 I/O 작업이 발생하더라도 스레드가 대기하지 않고 다른 작업을 이어서 처리하기 때문에 성능상 큰 이점을 제공한다.

3. 콜백 기반, 이벤트 기반으로 동작

Event Loop가 Non-blocking I/O만으로 완성되는 것은 아니다.
Non-blocking I/O는 “스레드가 멈추지 않는다”는 특징만 제공할 뿐이고, 실제 처리 흐름을 만들어주는 핵심 요소는 콜백(callback) 또는 이벤트 기반(event-driven) 구조이다.
결론적으로 Event Loop는 "이벤트가 발생할 때까지 스레드를 놀리지 않고, 이벤트가 발생하면 즉시 처리하는 구조" 로 동작하며, 이 비동기 이벤트 기반 구조가 Non-blocking I/O와 결합하여 고성능을 만들어낸다.

Netty의 Event Loop

Netty 역시 고성능 네트워크 애플리케이션을 위해 개발된 프레임워크이며, Spring WebFlux가 Netty 기반으로 높은 처리량을 구현한 것이 대표적인 사례이다.
Redis와 달리 Netty는 다음과 같은 방식으로 Event Loop를 구성한다.

  • 각각의 EventLoop는 하나의 스레드로 동작하며
  • 여러 EventLoop가 모여 EventLoopGroup을 구성한다

즉, 구조적으로는 멀티스레드 기반의 Event Loop 모델이다.
각 EventLoop는 고정된 스레드이며, 자신이 담당하는 Channel(Socket 연결)을 지속적으로 처리하는 방식이다.
정리하면, Redis는 “스레드 하나 + Event Loop 1개”, Netty는 “여러 EventLoop → EventLoopGroup”이다.
둘 다 Event Loop 기반이지만 스레드 전략이 다르다.

그렇다면 Virtual Thread는??

https://bangbaeking.tistory.com/141

[JAVA] Virtual Thread (JDK 21)

Virtual Thread프로세스실행중인 프로그램스레드프로세스 내에서 실행되는 실행 흐름 (작업 단위)Virtual Thread2023년 JDK21에 추가된 경량 스레드이다. OS 스레드를 그대로 사용하지 않고 JVM 내부 스케줄

bangbaeking.tistory.com

Virtual Thread를 처음 학습했을 때도 비슷한 개념처럼 느껴졌었다.
Java의 기존 스레드는 I/O 작업이 발생하면 반드시 대기해야 했고, 이 구조에서는 제한된 수의 스레드만으로는 처리량에 한계가 있었다.
이를 개선하기 위해 도입된 Virtual Thread는 Blocking 작업이 발생하면 해당 Virtual Thread를 OS 스레드에서 언마운트(분리)하여 OS 스레드를 점유하지 않도록 한다.
이후 작업을 다시 이어서 실행해야 할 시점이 되면, 필요할 때 새로운 OS 스레드를 재할당받아 실행을 이어간다. 이런 동작 방식 때문에 겉으로 보기에는 Non-blocking처럼 처리되는 것처럼 느껴질 수 있지만,
실제로는 Blocking I/O를 더 효율적으로 처리하는 기술에 가깝다.
 

마무리

Redis, Netty, 그리고 Virtual Thread는 모두 높은 처리량을 목표로 한다는 공통점을 가지고 있지만, 그 접근 방식은 각기 다르다.
Redis와 Netty는 Event Loop + Non-blocking I/O 기반으로 스레드 대기 시간을 최소화하며 고성능을 구현하고,
Java의 Virtual Thread는 Blocking I/O를 효율적으로 처리하는 방식으로 기존 스레드 모델의 한계를 극복한다.
 
이전에 Netty를 공부하면서 Event Loop를 처음 접했었는데, 이번에 Redis의 Event Loop 구조를 다시 살펴보며 두 기술을 자연스럽게 비교해볼 수 있었다.
또한 Event Loop와 Non-blocking I/O를 정리하다 보니 Virtual Thread와 닮아 보인다는 생각이 들어 함께 비교해봤는데, 직접 비교하며 정리해볼 수 있어 좋았다.

댓글