이벤트 디멀티플렉싱
1. 개요
1. 개요
이벤트 디멀티플렉싱은 네트워크 프로그래밍과 시스템 프로그래밍에서 널리 사용되는 기술로, 하나의 입출력 채널을 통해 여러 소켓의 이벤트를 동시에 처리하는 것을 핵심으로 한다. 이 기술은 고성능 네트워크 서버를 구현할 때, 특히 동시에 수많은 클라이언트 연결을 효율적으로 관리해야 하는 상황에서 필수적이다.
기본적인 블로킹 입출력 방식은 하나의 연결을 처리하는 동안 다른 연결의 요청을 기다리게 하여 자원 낭비와 성능 저하를 초래한다. 이벤트 디멀티플렉싱은 이러한 문제를 해결하기 위해, 단일 스레드 또는 프로세스가 다수의 소켓 연결을 모니터링하고, 실제 입출력 작업이 준비된 소켓만을 효율적으로 선택하여 처리할 수 있게 한다. 이는 입출력 다중화의 대표적인 구현 방식이다.
주요 운영체제는 각각의 시스템 호출이나 API를 제공하여 이 기능을 지원한다. 유닉스 계열 시스템에서는 전통적으로 select와 poll이 사용되었으며, 리눅스에서는 고성능을 위한 epoll이, BSD 계열(맥OS 포함)에서는 kqueue가 개발되었다. 마이크로소프트 윈도우 환경에서는 IOCP가 비동기 입출력 모델을 제공한다.
이 기술의 적용은 웹 서버, 게임 서버, 실시간 메시징 시스템 등 대규모 동시 접속을 처리해야 하는 모든 네트워크 애플리케이션의 성능을 결정하는 근간이 된다.
2. 동기와 필요성
2. 동기와 필요성
전통적인 네트워크 프로그래밍에서 서버는 각 클라이언트 연결마다 별도의 스레드나 프로세스를 생성하여 처리하는 방식이 일반적이었다. 그러나 이 방식은 동시에 수천, 수만 개의 연결을 처리해야 하는 현대의 고성능 서버 환경에서는 심각한 한계를 드러낸다. 각 연결마다 스레드를 생성하면 컨텍스트 스위칭에 따른 오버헤드가 커지고, 메모리 사용량이 급증하여 시스템 자원을 빠르게 소모하게 된다. 특히 대부분의 연결이 실제 데이터 교환보다는 대기 상태에 머무르는 경우, 이러한 자원 낭비는 더욱 두드러진다.
이러한 문제를 해결하기 위해 등장한 개념이 이벤트 디멀티플렉싱이다. 이 기술의 핵심은 단일 프로세스 또는 스레드가 여러 개의 네트워크 소켓을 동시에 관리할 수 있도록 하는 것이다. 서버는 모든 활성 소켓을 모니터링하며, 실제로 읽기 또는 쓰기 작업이 가능한 소켓(즉, 이벤트가 발생한 소켓)만을 골라내어 효율적으로 처리한다. 이를 통해 수많은 대기 중인 연결을 적은 수의 스레드로 관리하는 것이 가능해지며, 시스템 콜 호출 횟수와 자원 사용량을 획기적으로 줄일 수 있다.
따라서 이벤트 디멀티플렉싱은 C10K 문제와 같은 대규모 동시 연결을 처리해야 하는 서버를 구현하는 데 필수적인 기반 기술이 되었다. 웹 서버, 실시간 통신 서버, 게임 서버, 메시지 브로커 등 높은 처리량과 낮은 지연 시간을 요구하는 모든 네트워크 서버 구현의 핵심이 된다. 이는 단순한 성능 최적화를 넘어, 현대 분산 시스템과 클라우드 컴퓨팅 인프라의 효율성을 보장하는 중요한 요소이다.
3. 구현 방식
3. 구현 방식
3.1. select
3.1. select
select는 이벤트 디멀티플렉싱을 구현하는 가장 기본적이고 전통적인 시스템 호출이다. 이 방식은 운영체제에 감시할 파일 디스크립터들의 집합을 전달하면, 운영체제가 이 집합 중 입출력 준비가 완료된 디스크립터를 골라 반환하는 방식으로 동작한다. 주로 소켓 프로그래밍에서 단일 프로세스나 스레드가 여러 클라이언트 연결을 동시에 관리할 때 사용된다.
select의 구현 방식은 비교적 단순하다. 프로그램은 읽기, 쓰기, 예외 상태를 감시할 세 개의 파일 디스크립터 집합을 준비하여 select 호출에 인자로 전달한다. 호출은 블로킹 또는 타임아웃을 설정한 논블로킹 모드로 동작할 수 있다. 커널은 호출이 반환될 때, 실제로 이벤트가 발생한 디스크립터만 남기고 나머지는 집합에서 제거한다. 따라서 프로그램은 반환된 집합을 순회하며 어떤 소켓에서 이벤트가 발생했는지 확인한 후, 해당 입출력 작업을 수행한다.
그러나 select에는 몇 가지 명확한 한계가 존재한다. 감시할 수 있는 파일 디스크립터의 최대 개수가 운영체제별로 제한되어 있으며, 호출이 반환될 때마다 관심 목록 전체를 커널에 다시 전달해야 하므로 성능 오버헤드가 발생한다. 또한, 이벤트가 발생한 디스크립터를 찾기 위해 매번 전체 집합을 선형적으로 검색해야 하므로, 관리하는 연결 수가 많아질수록 효율성이 급격히 떨어진다.
이러한 단점들로 인해 대규모 네트워크 서버를 구현하는 데는 select가 적합하지 않으며, 더 발전된 epoll이나 kqueue 같은 메커니즘이 선호된다. 하지만 그 간단함과 이식성 덕분에 소규모 연결을 처리하거나 다양한 플랫폼에서 동작해야 하는 프로그램에서는 여전히 유용하게 사용된다.
3.2. poll
3.2. poll
poll은 select의 한계를 개선하기 위해 도입된 입출력 다중화 시스템 호출이다. select와 마찬가지로 단일 프로세스나 스레드가 여러 파일 디스크립터(주로 소켓)의 입출력 준비 상태를 동시에 모니터링할 수 있게 해준다. 그러나 select는 감시할 파일 디스크립터의 최대 개수에 제한이 있고, 매번 호출 시 관심 있는 모든 디스크립터 집합을 재전달해야 하는 비효율성이 있었다.
poll은 이러한 문제를 해결하기 위해 설계되었다. poll은 감시할 파일 디스크립터의 개수에 제한을 두지 않으며, 관심 있는 이벤트와 발생한 이벤트를 구분하는 구조체 배열을 사용한다. 이로 인해 애플리케이션은 호출할 때마다 전체 디스크립터 목록을 전달해야 하지만, 내부적으로 커널이 관리하는 데이터 구조가 더 효율적일 수 있다. poll은 리눅스, 유닉스 계열 운영체제에서 널리 사용 가능한 표준 POSIX API이다.
그러나 poll 역시 근본적인 성능 문제를 완전히 해결하지는 못한다. 감시하는 파일 디스크립터의 수가 매우 많아지면, 준비 상태를 확인하기 위해 커널이 전체 목록을 순차적으로 검사해야 하므로 성능이 선형적으로 저하된다. 이는 C10K 문제와 같은 대규모 연결을 처리하는 서버 구현에 있어서는 여전히 병목이 될 수 있다. 이러한 한계로 인해 더 확장성 있는 메커니즘인 epoll이나 kqueue가 개발되게 된 동기가 되었다.
3.3. epoll
3.3. epoll
epoll은 리눅스 커널 2.5.44 버전부터 도입된 이벤트 디멀티플렉싱 메커니즘이다. 기존의 select나 poll 시스템 호출이 매번 감시할 파일 디스크립터 목록 전체를 커널에 전달해야 하는 오버헤드가 있었던 반면, epoll은 커널 내부에 감시 대상 목록을 유지하고, 애플리케이션은 변경 사항이 있는 이벤트만 확인하는 방식을 사용한다. 이로 인해 연결된 소켓의 수가 많아질수록 성능상의 이점이 두드러진다.
epoll은 크게 세 가지 시스템 호출로 구성된다. 첫째, epoll_create를 통해 epoll 인스턴스를 생성한다. 둘째, epoll_ctl을 사용하여 해당 인스턴스에 관심 있는 파일 디스크립터(예: 소켓)를 등록, 수정 또는 삭제한다. 마지막으로 epoll_wait를 호출하여 등록된 파일 디스크립터들 중 입출력 이벤트가 발생한 것들만의 리스트를 블로킹 또는 논블로킹 방식으로 받아온다. 이 구조는 이벤트가 발생할 때마다 전체 목록을 스캔할 필요가 없게 만든다.
epoll은 주로 Edge-Triggered와 Level-Triggered라는 두 가지 이벤트 통지 방식을 지원한다. Level-Triggered는 파일 디스크립터가 준비 상태인 동안 계속해서 이벤트를 알려주는 반면, Edge-Triggered는 상태가 변화하는 순간(예: 버퍼에 새로운 데이터가 도착한 순간)에만 한 번 알려준다. Edge-Triggered 방식을 사용하면 애플리케이션이 가능한 한 많은 데이터를 읽거나 써야 하는 책임이 있지만, 불필요한 시스템 호출을 줄여 더 효율적인 제어가 가능하다.
이러한 설계 덕분에 epoll은 수만 개의 동시 연결을 효율적으로 처리해야 하는 고성능 웹 서버, 채팅 서버, 게임 서버 등의 구현에 널리 사용된다. Nginx나 Node.js의 libuv 라이브러리와 같은 많은 유명 소프트웨어들이 리눅스 플랫폼에서의 높은 확장성을 위해 epoll을 기본 이벤트 디멀티플렉서로 채택하고 있다.
3.4. kqueue
3.4. kqueue
kqueue는 BSD 계열 운영 체제(FreeBSD, NetBSD, OpenBSD, macOS 등)에서 제공하는 고성능 이벤트 디멀티플렉싱 메커니즘이다. 이는 select나 poll과 같은 전통적인 인터페이스의 확장성 문제를 해결하기 위해 설계되었으며, 커널 수준에서 이벤트를 효율적으로 관리한다. kqueue는 파일 디스크립터의 상태 변화뿐만 아니라 프로세스 상태, 시그널, 타이머 등 다양한 이벤트 소스를 모니터링할 수 있는 범용적인 이벤트 알림 시스템으로도 기능한다.
kqueue의 핵심은 kqueue() 시스템 호출을 통해 생성된 커널 이벤트 큐와 kevent() 시스템 호출을 통해 이벤트를 등록하고 검색하는 데 있다. 애플리케이션은 관심 있는 이벤트(예: 소켓 읽기 준비, 쓰기 가능, 연결 요청 등)를 kevent()로 커널 큐에 등록하고, 이후 다시 kevent()를 호출하여 준비된 이벤트만 효율적으로 가져온다. 이 방식은 select나 poll이 매번 전체 관찰 대상 목록을 커널에 전달하고 스캔해야 하는 오버헤드를 제거한다.
주요 장점은 확장성과 효율성이다. 이벤트 등록은 한 번만 이루어지며, 커널은 상태 변화가 발생한 이벤트만 애플리케이션에 보고하므로 연결된 소켓 수가 많아질수록 성능 저하가 적다. 또한 파일 디스크립터의 생성과 삭제에 따른 관리 오버헤드가 낮다. 단점은 주로 BSD 계열 운영 체제에 국한되어 있어 이식성이 떨어진다는 점이다. 이로 인해 리눅스의 epoll이나 윈도우의 IOCP와 함께 플랫폼별 고성능 I/O 솔루션 중 하나로 자리 잡았다.
kqueue는 웹 서버, 캐시 서버, 메시지 브로커와 같이 수만 개의 동시 네트워크 연결을 처리해야 하는 고성능 서버 소프트웨어 구현에 널리 사용된다. Nginx와 같은 인기 웹 서버는 사용 중인 운영 체제에 따라 kqueue, epoll, IOCP 중 가장 적합한 이벤트 디멀티플렉싱 메커니즘을 자동으로 선택하여 사용한다.
3.5. IOCP
3.5. IOCP
IOCP는 마이크로소프트 윈도우 운영 체제에서 제공하는 고성능 입출력 다중화 기술이다. 정식 명칭은 입출력 완료 포트(I/O Completion Port)이며, 비동기 입출력 모델을 기반으로 한다. 다른 이벤트 디멀티플렉싱 기술들이 파일 디스크립터의 준비 상태를 감시하는 반면, IOCP는 입출력 작업 자체가 완료된 사건을 비동기적으로 통지받는 방식으로 동작한다. 이는 윈도우 환경에서 고성능 네트워크 서버를 구현하는 데 핵심적인 역할을 한다.
IOCP의 작동 원리는 애플리케이션이 비동기 입출력 작업을 운영 체제에 요청하면, 해당 작업이 완료되었을 때 운영 체제가 미리 생성해 둔 완료 포트를 통해 결과를 알려주는 것이다. 개발자는 스레드 풀을 생성하여 이 완료 포트에 연결하고, 완료된 입출력 작업에 대한 통지를 받아 후속 처리를 수행한다. 이 방식은 논블로킹 I/O와 결합되어, 소수의 스레드로도 수천 개의 동시 네트워크 연결을 효율적으로 관리할 수 있게 해준다.
주요 장점으로는 운영 체제 커널 수준에서의 효율적인 스케줄링과 확장성을 꼽을 수 있다. 커널이 입출력 완료 통지를 관리하고, 이를 대기 중인 스레드에 분배하므로 컨텍스트 스위칭 오버헤드가 줄어든다. 또한, 선점형 멀티태스킹 시스템에서 최적의 성능을 내도록 설계되었다. 반면, 주된 단점은 윈도우 플랫폼에 종속적이라는 점이다. 이로 인해 리눅스의 epoll이나 BSD 계열의 kqueue와 같은 크로스 플랫폼 솔루션과의 호환성 문제가 발생할 수 있다.
IOCP는 윈도우 서버 기반의 대용량 웹 서버, 게임 서버, 데이터베이스 서버 등에서 널리 사용된다. 특히, 마이크로소프트의 인터넷 정보 서비스와 같은 서버 소프트웨어의 내부 구조에 깊이 통합되어 있다. 소켓 프로그래밍을 할 때, 윈속2 라이브러리와 함께 사용되어 네트워크 처리 성능을 극대화하는 데 기여한다.
4. 작동 원리
4. 작동 원리
이벤트 디멀티플렉싱의 작동 원리는 단일 스레드 또는 프로세스가 여러 개의 네트워크 소켓이나 파일 디스크립터의 상태 변화를 효율적으로 감시하고, 준비된 입출력 작업만을 순차적으로 처리하는 데 있다. 이는 블로킹 입출력 방식에서 각 연결마다 별도의 스레드를 생성하거나, 폴링을 통해 모든 소켓을 지속적으로 확인하는 비효율성을 해결한다. 핵심은 운영체제 커널이 제공하는 특별한 시스템 호출(select, poll, epoll, kqueue, IOCP 등)을 이용해, 관심 있는 파일 디스크립터 집합과 감시할 이벤트(읽기 가능, 쓰기 가능, 오류 발생 등)를 등록하는 것이다. 이후 애플리케이션은 이 시스템 호출을 통해 대기하며, 커널은 등록된 디스크립터 중 하나라도 지정된 이벤트가 발생하면 대기를 해제하고 애플리케이션에 알린다.
구체적인 작동 흐름은 먼저 애플리케이션이 감시할 소켓들의 파일 디스크립터를 해당 운영체제의 이벤트 디멀티플렉싱 API에 등록하는 것으로 시작한다. 이후 애플리케이션은 이 API를 호출하여 이벤트 발생을 기다리는 블로킹 상태에 들어간다. 커널은 내부적으로 등록된 모든 디스크립터의 상태를 모니터링하다가, 예를 들어 새로운 클라이언트 연결 요청이 도착하거나(accept), 기존 연결에서 데이터가 도착하여 읽을 수 있는 상태가 되면, 대기 중인 시스템 호출을 깨운다. 깨어난 애플리케이션은 API의 반환값을 통해 실제로 어떤 이벤트가 어느 디스크립터에서 발생했는지 확인하고, 해당 소켓에 대해 필요한 논블로킹 입출력 작업을 즉시 수행한다.
이러한 원리는 이벤트 루프 구조와 결합되어 고성능 서버의 백본을 이룬다. 서버는 무한 루프를 돌며 지속적으로 이벤트 디멀티플렉싱 호출을 수행하고, 이벤트가 발생할 때마다 빠르게 처리한 후 다시 대기 상태로 돌아간다. 이로 인해 수천, 수만 개의 동시 연결을 처리하더라도 컨텍스트 스위칭 오버헤드가 적고, 시스템 자원을 매우 효율적으로 사용할 수 있다. 특히 epoll이나 kqueue 같은 최신 메커니즘은 커널이 감시 대상 목록을 유지하고, 준비된 이벤트만을 애플리케이션에 알려주는 엣지 트리거 또는 레벨 트리거 방식을 지원하여 성능을 더욱 극대화한다.
5. 장단점
5. 장단점
이벤트 디멀티플렉싱 기술의 가장 큰 장점은 리소스 사용 효율성이다. 기존의 멀티스레딩이나 멀티프로세싱 방식은 각 클라이언트 연결마다 별도의 스레드나 프로세스를 생성해야 하므로, 동시 연결 수가 많아질수록 컨텍스트 스위칭과 메모리 오버헤드가 급격히 증가한다. 반면 이벤트 디멀티플렉싱은 단일 또는 소수의 스레드에서 수천, 수만 개의 연결을 관리할 수 있어, C10K 문제와 같은 대규모 동시 접속 상황에서 확장성이 뛰어나다. 또한 블로킹 I/O 방식에서 발생하는 스레드의 대기 시간을 제거하여 CPU 활용도를 극대화한다.
이 기술의 단점은 구현의 복잡성에 있다. 논블로킹 I/O와 콜백 기반의 비동기 프로그래밍 모델을 사용하기 때문에, 코드의 흐름이 직관적이지 않고 디버깅이 어려울 수 있다. 또한 이벤트 루프가 하나의 긴 작업(CPU 바운드 작업)에 점유되면 전체 시스템의 응답성이 떨어지는 문제가 발생할 수 있어, 작업을 적절히 분할하거나 별도의 워커 스레드 풀을 활용해야 한다. 대표적인 구현체인 select와 poll은 감시할 파일 디스크립터의 수가 증가할수록 성능이 선형적으로 저하되는 반면, epoll이나 kqueue는 이 문제를 해결했지만 특정 운영체제(리눅스, BSD)에 종속적이라는 한계가 있다.
따라서 이벤트 디멀티플렉싱은 낮은 지연 시간과 높은 처리량이 요구되는 웹 서버, 실시간 통신 서버, 게임 서버 등에 적합하다. 그러나 복잡한 비즈니스 로직을 처리하는 일반적인 애플리케이션 서버에서는 오히려 스레드 풀과 블로킹 I/O를 조합한 방식이 개발 생산성 측면에서 더 유리할 수 있다. 기술 선택은 처리해야 할 연결의 규모, 요구되는 응답 시간, 그리고 개발 및 유지보수 비용을 종합적으로 고려해야 한다.
6. 사용 사례
6. 사용 사례
이벤트 디멀티플렉싱은 고성능 네트워크 서버를 구현하는 데 필수적인 기술로, 특히 동시에 수천, 수만 개의 클라이언트 연결을 효율적으로 관리해야 하는 상황에서 널리 사용된다. 대표적인 사용 사례로는 웹 서버, 채팅 서버, 게임 서버, 메시지 브로커 및 리버스 프록시 소프트웨어 등이 있다. 이러한 서버들은 단일 프로세스나 적은 수의 스레드로도 대규모 연결을 처리할 수 있어야 하며, 이벤트 디멀티플렉싱은 이를 가능하게 하는 핵심 메커니즘이다.
구체적으로, Node.js나 Nginx와 같은 소프트웨어는 내부적으로 이벤트 루프와 함께 이벤트 디멀티플렉싱 시스템 호출(예: epoll, kqueue)을 활용한다. 이를 통해 HTTP 요청이나 WebSocket 연결과 같은 수많은 네트워크 이벤트를 블로킹 없이 처리한다. 데이터베이스 서버나 분산 시스템의 노드 간 통신을 담당하는 미들웨어에서도 높은 처리량과 낮은 지연 시간을 달성하기 위해 이 기술을 채택한다.
사용되는 특정 API는 운영체제에 따라 다르다. 리눅스 기반 시스템에서는 epoll이, BSD 계열(macOS 포함)에서는 kqueue가, 윈도우 환경에서는 IOCP가 각각 고성능 이벤트 디멀티플렉싱을 제공한다. 이는 소켓 프로그래밍과 시스템 프로그래밍의 중요한 부분으로, 개발자는 이러한 인터페이스를 직접 사용하거나 libuv와 같은 추상화 라이브러리를 통해 간접적으로 활용하여 확장성 있는 네트워크 애플리케이션을 구축한다.
7. 관련 개념
7. 관련 개념
7.1. 이벤트 루프
7.1. 이벤트 루프
7.2. 논블로킹 I/O
7.2. 논블로킹 I/O
논블로킹 I/O는 입출력 작업이 완료될 때까지 프로세스나 스레드의 실행을 멈추지 않고, 즉시 제어권을 반환하는 입출력 방식을 의미한다. 이 방식은 이벤트 디멀티플렉싱과 함께 사용되어 고성능 네트워크 프로그래밍의 핵심을 이룬다. 전통적인 블로킹 I/O에서는 소켓에서 데이터를 읽거나 쓸 때, 데이터가 준비되거나 전송이 완료될 때까지 해당 스레드가 대기 상태에 머무르게 된다. 반면 논블로킹 모드에서는 입출력 작업을 시도했을 때 데이터가 즉시 사용 가능하지 않더라도, 시스템 콜은 즉시 에러 코드와 함께 반환되어 프로그램이 다른 작업을 계속할 수 있게 한다.
이러한 특성 덕분에 단일 스레드가 여러 개의 소켓 연결을 효율적으로 관리할 수 있다. 프로그램은 논블로킹 소켓들을 순회하며 read나 write 작업을 시도하고, 실제 데이터 전송이 가능한 소켓만 처리하면 된다. 이 과정에서 이벤트 디멀티플렉싱 시스템 호출인 select, poll, epoll 등은 어떤 소켓이 실제로 읽기 또는 쓰기 가능 상태인지를 한 번에 감지하여 알려주는 역할을 한다. 이를 통해 프로그램은 불필요한 시스템 콜 호출을 줄이고, 준비된 소켓에 대해서만 효율적으로 입출력 작업을 수행할 수 있다.
논블로킹 I/O는 C10K 문제와 같은 대량의 동시 연결을 처리해야 하는 서버 구현에 필수적이다. 블로킹 I/O 모델에서는 각 연결마다 전용 스레드를 생성해야 하여 컨텍스트 스위칭 오버헤드와 메모리 소비가 크게 증가하는 반면, 논블로킹 I/O와 이벤트 디멀티플렉싱을 결합하면 적은 수의 스레드로 수천, 수만 개의 연결을 관리하는 것이 가능해진다. 이는 Node.js나 Nginx와 같은 고성능 서버 소프트웨어의 기본 동작 원리가 된다.
그러나 논블로킹 I/O만으로는 완전한 비동기 입출력을 구현하기 어려운 경우가 있다. 예를 들어, 디스크 I/O와 같은 일부 작업은 여전히 블로킹될 수 있으며, 준비 상태를 폴링(polling)하는 방식은 CPU 자원을 소모할 수 있다. 이러한 한계를 극복하기 위해 리액터 패턴이나 프로액터 패턴과 같은 고급 디자인 패턴이 사용되며, 리눅스의 epoll이나 윈도우의 IOCP와 같은 운영체제별 고성능 이벤트 통지 메커니즘과 결합되어 활용된다.
7.3. 리액터 패턴
7.3. 리액터 패턴
리액터 패턴은 이벤트 디멀티플렉싱을 구현하기 위한 핵심적인 소프트웨어 설계 패턴이다. 이 패턴은 네트워크 프로그래밍에서 고성능 서버를 구축할 때 널리 사용되며, 하나의 이벤트 루프가 여러 클라이언트 연결로부터 발생하는 이벤트를 감지하고 적절한 핸들러로 전달하는 구조를 가진다. 이를 통해 단일 또는 소수의 스레드로도 수많은 동시 연결을 효율적으로 처리할 수 있다.
패턴의 핵심 구성 요소는 이벤트 디멀터, 이벤트 디스패처, 그리고 요청 핸들러이다. 이벤트 디멀터는 select나 epoll 같은 시스템 호출을 사용해 다중 소켓에서 발생하는 읽기, 쓰기 등의 이벤트를 감시한다. 이벤트 디스패처는 감지된 이벤트를 해당 소켓에 등록된 콜백 함수나 핸들러 객체로 연결한다. 요청 핸들러는 실제 입출력 작업이나 비즈니스 로직을 처리하는 최종 실행 단위이다.
이 패턴의 주요 장점은 확장성과 자원 효율성이다. 블로킹 I/O 방식과 달리 각 연결마다 전용 스레드를 생성할 필요가 없어 컨텍스트 스위칭 오버헤드와 메모리 사용량을 크게 줄일 수 있다. 대신, 모든 처리가 논블로킹 I/O와 비동기 이벤트 콜백 기반으로 이루어지기 때문에 애플리케이션 설계가 복잡해질 수 있다는 단점이 있다.
리액터 패턴은 Node.js의 런타임, Nginx 웹 서버, Netty 프레임워크 등 많은 고성능 서버 소프트웨어의 기반이 된다. 이 패턴과 프로액터 패턴을 결합해 계산 작업까지 분산하는 하이브리드 아키텍처도 현대 시스템에서 자주 활용된다.
