Netty

Netty는 비동기 이벤트 기반 네트워크 애플리케이션 프레임워크로 비동기 이벤트를 활용해 최소한의 리소스로 많은 연결을 처리할 수 있습니다.

Spring 5.0에서 도입된 리액티브 프로그래밍 모델을 기반으로 동작하는 Spring WebFlux도 서버 구현을 위한 다양한 옵션을 제공하지만, Netty를 기본적으로 사용하는 서버 엔진이다.

<aside> 💡

비동기 이벤트 기반란?

비동기 이벤트 기반이란, 이벤트가 발생했을 때 이를 비동기로 처리하는 방식의 프로그래밍 모델을 말함.

즉, “어떤 일이 생기면(이벤트가 발생하면), 그때 처리해라(핸들러를 비동기로 실행)”는 구조입니다.

</aside>

블라킹 I/O 와 논블라킹 I/O

Netty는 Java NIO 기반의 고성능 네트워크 애플리케이션 프레임워크입니다. Netty에 대해 알아보기 전 Java의 블라킹 I/O와 논블라킹 I/O에 대해 알아보겠습니다.

Java 블라킹 I/O

Java 1.0에 처음 도입된 Java I/O는 바이트 단위로 읽고 쓸 수 있는 Stream에 대한 API를 제공했습니다. 이러한 자바 I/O는 블로킹 함수만 지원했습니다.

public static void main(String[] args) {
    log.info("start main");
    try (ServerSocket serverSocket = new ServerSocket()) {
        serverSocket.bind(new InetSocketAddress("localhost", 7777));

        while (true) {
            Socket clientSocket = serverSocket.accept();
            byte[] requestBytes = new byte[1024];
            InputStream in = clientSocket.getInputStream();
            in.read(requestBytes);
            log.info("request: {}", new String(requestBytes).trim());

            OutputStream out = clientSocket.getOutputStream();
            String response = "This is server";
            out.write(response.getBytes());
            out.flush();
            
            clientSocket.close();
        }
    }
}

위 코드는 다음과 같은 특징이 있습니다:

image.png

위 그림처럼 read( ) 함수로 발생하는 시스템콜 호출에 커널이 응답을 돌려줄 때까지 Application은 실행을 블락합니다. 따라서, 다수의 클라이언트 요청을 동시에 처리하기 위해서는 각각의 클라이언트마다 새로운 스레드를 할당해야 합니다. 하지만 네트워크 요청이 발생할 때마다 새로운 스레드를 할당하면 스레드 생성 및 관리 비용과 컨텍스트 스위칭로 인해 메모리와 CPU 자원이 과부화될 수 있습니다.

Java NIO와 논블라킹 I/O

자바의 초기 I/O는 블라킹으로 동작하였고 이 때문에 발생하는 단점을 해결하기 위한 방식이 논블라킹 I/O입니다.

Java 1.4에 도입된 Java NIO는 논블라킹을 지원하고 Selector, Channel 도입으로 높은 성능을 보장합니다. 또한 Java I/O에서 InputStream, OutpusStream으로 데이터를 단방향으로 처리하던 것을 Java NIO는 Channel 하나로 데이터를 Input/Output 양방향으로 처리할 수 있습니다.