Java NIO(New I/O)는 자바의 표준 입출력 API인 java.io 패키지를 대체하거나 보완하는 기능을 제공하는 패키지입니다. 주로 대용량 데이터를 처리하거나 성능을 최적화할 필요가 있는 경우 사용됩니다. 자바 NIO는 비동기적이고, 블로킹이 아닌(non-blocking) 입출력 작업을 지원하는 것이 특징입니다.
1. blocking IO
블로킹 I/O는 입출력 작업이 완료될 때까지 현재 실행 흐름이 차단(block)되는 방식입니다. 입출력 작업이 시작되면 해당 작업이 완료될 때까지 다른 작업을 수행할 수 없습니다. 이러한 차단은 입출력 작업이 완료되기 전까지 스레드가 대기하며, 작업이 완료되면 스레드는 결과를 반환하고 다음 작업을 수행합니다.
스레드가 입출력 작업을 기다리는 동안 블로킹되기 때문에 동시에 여러 클라이언트의 요청을 처리하기에는 비효율적입니다.
ex) InputStream의 read() 메서드는 데이터를 읽을 때까지 현재 스레드를 차단합니다.
데이터가 도착할 때까지 스레드는 아무 작업도 수행하지 않고 대기합니다.
2. New IO
자바 4부터 새로운 입출력(NIO: New Input/Output)이라는 뜻에서 java.nio 패키지가 포함되고
자바 7로 버전업하면서 자바 IO와 NIO 사이의 일관성 없는 클래스 설계를 바로 잡고, 비동기 채널 등의 네트워크 지원을 강화한 NIO.2 API가 추가되었습니다.
1. 버퍼(Buffer)
- 데이터를 일시적으로 저장하는 메모리 공간입니다.
- 버퍼는 Buffer 클래스(예: ByteBuffer, CharBuffer 등)로 구현되며, 읽기/쓰기 작업에서 중요한 역할을 합니다.
- NIO에서는 데이터를 직접 읽고 쓸 수 있는 스트림 대신 버퍼를 통해 작업합니다.
2. 채널(Channel)
- 입출력 데이터의 연결점 역할을 합니다.
- 전통적인 InputStream, OutputStream과는 달리, Channel은 양방향 입출력을 지원합니다.
- 주요 채널 클래스에는 FileChannel, SocketChannel, ServerSocketChannel, DatagramChannel 등이 있습니다.
- 채널은 버퍼와 결합되어 비동기적으로 데이터를 읽고 씁니다.
3. 비동기식 및 논블로킹 I/O (Asynchronous & Non-blocking I/O)
- 전통적인 I/O는 블로킹 방식입니다. 즉, 입출력 작업이 완료될 때까지 쓰레드가 작업을 멈추고 대기합니다.
- 반면, NIO는 논블로킹 모드를 지원하여 입출력 작업이 완료될 때까지 기다리지 않고, 즉시 다른 작업을 수행할 수 있게 합니다. 입출력 작업이 완료되면 해당 작업을 처리할 수 있습니다.
- 비동기 I/O를 위한 AsynchronousSocketChannel, AsynchronousServerSocketChannel 같은 클래스들이 있습니다.
4. 셀렉터(Selector)
- 논블로킹 I/O에서 여러 채널을 동시에 모니터링할 수 있게 해주는 객체입니다.
- Selector는 여러 채널의 이벤트(읽기, 쓰기 가능 상태)를 감지하고 해당 이벤트가 발생한 채널만 선택적으로 처리할 수 있게 합니다.
- 이를 통해 하나의 쓰레드가 여러 채널을 효율적으로 처리할 수 있습니다.
5. 파일 I/O (File I/O)
- NIO는 파일 시스템의 작업을 위한 강력한 기능을 제공합니다. FileChannel을 사용하여 파일의 데이터를 읽고 쓸 수 있습니다.
- 이 외에도 Paths, Files와 같은 유틸리티 클래스들을 통해 파일 복사, 이동, 삭제, 파일 속성 읽기 등의 작업을 효율적으로 처리할 수 있습니다.
Java NIO와 기존 I/O의 차이점
- Stream vs. Buffer: 기존 I/O는 스트림 기반이었으나, NIO는 버퍼 기반입니다.
- Blocking vs. Non-blocking: 기존 I/O는 블로킹 방식이지만, NIO는 논블로킹 방식도 지원합니다.
- 비동기 I/O: NIO는 비동기 I/O 작업을 위한 클래스를 제공합니다.
| 구분 | IO | NIO |
| 입출력 방식 | 스트림 방식 (단방향) | 채널 방식 (양방향) |
| 버퍼 방식 | 논버퍼 | 버퍼 |
| 비동기 방식 | 지원 안함 | 지원 |
| 블록킹/넌블로킹 방식 | 블로킹 방식만 지원 | 블로킹 / 넌블로킹 방식 모두 지원 |
논블로킹 I/O는 입출력 작업이 완료되지 않더라도 현재 실행 흐름이 차단되지 않는 방식입니다. 입출력 작업을 시작한 후에 다른 작업을 수행할 수 있으며, 입출력 작업이 완료되면 그 결과를 확인할 수 있습니다.이를 위해 자바에서는 NIO(Non-blocking I/O) 패키지를 제공하며, Selector, Channel, ByteBuffer 등의 요소를 사용하여 구현합니다.논블로킹 I/O는 단일 스레드에서 여러 개의 연결을 처리하는 데 유용합니다. 단일 스레드가 여러 개의 채널을 관리하고, 입출력 작업이 완료되지 않더라도 다른 작업을 수행할 수 있습니다. 이는 입출력 작업을 기다리는 동안 다른 클라이언트의 요청을 처리하는 데 유용하며, 동시 접속이 많은 서버 애플리케이션에 적합합니다.
1. Blocking I/O (BIO) 설정
설정 예시: 톰캣의 기본 설정은 BIO입니다. 이 경우, 요청을 처리하기 위해 각 클라이언트에 대해 별도의 스레드를 생성합니다.
- 동작 방식:
- 클라이언트가 요청을 보내면, 톰캣 서버는 새로운 스레드를 생성하여 해당 요청을 처리합니다.
- 스레드는 요청을 처리하는 동안 블로킹 상태가 되어, 다른 요청이 들어오더라도 대기해야 합니다.
- 이로 인해 많은 동시 클라이언트 요청이 들어오면, 스레드 수가 급격히 증가하고 서버의 자원이 소모됩니다.
- 장점:
- 구현이 간단하고 이해하기 쉽습니다.
- 스레드가 독립적으로 동작하여, 요청 처리 로직을 단순하게 구성할 수 있습니다.
- 단점:
- 스레드 생성과 관리로 인한 오버헤드가 발생합니다.
- 대량의 동시 요청을 처리하기 어려워 성능이 저하될 수 있습니다.
2. Non-blocking I/O (NIO) 설정
설정 예시: 톰캣에서 NIO를 사용하려면, server.xml 파일에서 connector의 protocol 속성을 org.apache.coyote.http11.Http11NioProtocol로 설정해야 합니다.
<Connector port="8080" protocol="org.apache.coyote.http11.Http11NioProtocol" maxThreads="200" connectionTimeout="20000" />
- 동작 방식:
- 클라이언트가 요청을 보내면, 톰캣 서버는 요청을 처리하기 위해 스레드를 블로킹하지 않고 요청을 큐에 추가합니다.
- 선택자(Selector)를 사용하여 여러 클라이언트의 요청을 동시에 모니터링하고, 요청이 처리 가능한 상태가 되면 해당 스레드가 작업을 수행합니다.
- 이를 통해 여러 클라이언트 요청을 동시에 처리할 수 있으며, 필요할 때만 스레드를 사용합니다.
- 장점:
- 적은 수의 스레드로도 많은 동시 클라이언트 요청을 처리할 수 있습니다.
- 자원 사용이 효율적이며, 성능이 향상됩니다.
- 단점:
- 구현이 다소 복잡할 수 있으며, 비동기 프로그래밍 모델에 대한 이해가 필요합니다.
BIO 방식은 각 요청에 대해 별도의 스레드를 생성하여 요청을 처리하고, 블로킹되어 다른 요청을 대기하게 하므로 동시 처리 능력이 제한됩니다.
NIO방식은 비동기적으로 요청을 처리하여, 여러 클라이언트의 요청을 효율적으로 관리할 수 있어 성능이 향상됩니다.
'WEB개발 > JAVA' 카테고리의 다른 글
| java Stream API (0) | 2026.01.12 |
|---|---|
| Checked Exception, Unchecked Exception (Runtime Exception) (0) | 2025.12.08 |
| Daemon Thread vs User Thread (0) | 2025.02.21 |
| CyclicBarrier, CountDownLatch (0) | 2025.02.21 |
| 제너릭 Generic (0) | 2024.12.18 |