정의

Reactor 패턴은 이벤트가 발생했을 때 이벤트를 분리하고 적절한 핸들러에 전달하는 이벤트 처리 방식이다.

Reactor 패턴은 하나의 스레드 또는 적은 수의 스레드가 여러 I/O 이벤트를 감시하고, 이벤트가 발생하면 적절한 핸들러를 호출하는 구조다.
비동기 I/O와 이벤트 기반 서버에서 자주 사용된다.

🧱 핵심 구성요소

  • Reactor
  • EventHandler
  • Selector

image

🔄 동작 방식

  1. Reactor가 이벤트를 감시한다.
  2. 이벤트가 발생하면 Selector가 해당 이벤트를 감지한다.
  3. Reactor가 적절한 EventHandler를 호출한다.
  4. EventHandler가 실제 비즈니스 로직을 처리한다.

🧩 Reactor

Reactor는 이벤트를 받아서 처리할 대상을 결정하는 중심 객체다.

public class Reactor {
    private final Selector selector;
    private final ServerSocketChannel serverSocketChannel;
    private final EventHandler eventHandler;

    public Reactor(EventHandler eventHandler) throws IOException {
        this.selector = Selector.open();
        this.serverSocketChannel = ServerSocketChannel.open();
        this.serverSocketChannel.socket().bind(new InetSocketAddress(80));
        this.serverSocketChannel.configureBlocking(false);
        this.serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
        this.eventHandler = eventHandler;
    }

    public void run() throws IOException {
        while (true) {
            selector.select();

            Set<SelectionKey> selectedKeys = selector.selectedKeys();
            Iterator<SelectionKey> keyIterator = selectedKeys.iterator();

            while (keyIterator.hasNext()) {
                SelectionKey key = keyIterator.next();
                keyIterator.remove();

                if (key.isAcceptable()) {
                    handleAccept();
                } else if (key.isReadable()) {
                    handleRead(key);
                }
            }
        }
    }

    private void handleAccept() throws IOException {
        SocketChannel socketChannel = serverSocketChannel.accept();
        socketChannel.configureBlocking(false);
        socketChannel.register(selector, SelectionKey.OP_READ);
        eventHandler.handleEvent(new Event(socketChannel));
    }

    private void handleRead(SelectionKey key) throws IOException {
        SocketChannel socketChannel = (SocketChannel) key.channel();
        eventHandler.handleEvent(new Event(socketChannel));
    }
}

🧩 Selector

Selector는 여러 채널의 I/O 이벤트를 감시하는 객체다.

public abstract class Selector implements Closeable {
    protected Selector() { }

    public static Selector open() throws IOException {
        return SelectorProvider.provider().openSelector();
    }

    public abstract Set<SelectionKey> selectedKeys();
    public abstract int select() throws IOException;
}

🧩 EventHandler

EventHandler는 실제 처리 로직을 담당한다.
I/O 대기와 실제 비즈니스 로직을 분리하기 위해 사용한다.

public class EventHandler {
    public void handleEvent(Event event) {
        // 비즈니스 로직
    }
}

⚖️ 장점과 고려사항

  • I/O 이벤트 처리를 효율적으로 할 수 있다.
  • 적은 수의 스레드로 다수의 연결을 관리할 수 있다.
  • 이벤트 분리 구조가 명확하다.
  • 반대로 복잡한 동시성 로직은 별도 설계가 필요하다.

연결문서

댓글남기기