200 lines
7.5 KiB
Markdown
200 lines
7.5 KiB
Markdown
## 자바 NIO (New Input/Output) 관련 클래스 및 주요 메서드 정리
|
|
|
|
자바 NIO는 기존의 `java.io`보다 **더 빠르고 효율적인 비동기식 입출력 처리**를 제공하는 API다.
|
|
NIO의 핵심 개념은 **버퍼(Buffer), 채널(Channel), 셀렉터(Selector)**이다.
|
|
|
|
---
|
|
|
|
### 1. `Buffer` 클래스 및 주요 메서드
|
|
|
|
| 메서드 | 설명 |
|
|
|--------|-----------------------------|
|
|
| `allocate(int capacity)` | 지정된 크기의 버퍼 생성 (`ByteBuffer.allocate(1024)`) |
|
|
| `wrap(byte[] array)` | 기존 배열을 감싸는 버퍼 생성 |
|
|
| `put(T value)` | 버퍼에 데이터 저장 |
|
|
| `get()` | 버퍼에서 데이터 읽기 |
|
|
| `flip()` | 읽기 모드로 전환 (쓰기 → 읽기) |
|
|
| `clear()` | 버퍼를 초기화 (데이터 삭제 X, 포인터 리셋) |
|
|
| `compact()` | 읽지 않은 데이터를 앞으로 이동하고, 쓰기 모드로 전환 |
|
|
| `position()` | 현재 읽기/쓰기 위치 반환 |
|
|
| `limit()` | 읽기/쓰기 가능한 최대 위치 반환 |
|
|
| `remaining()` | 남은 읽기/쓰기 가능 데이터 개수 반환 |
|
|
|
|
**버퍼의 주요 종류**:
|
|
- `ByteBuffer` (바이트 저장)
|
|
- `CharBuffer` (문자 저장)
|
|
- `IntBuffer`, `FloatBuffer` 등
|
|
|
|
---
|
|
|
|
### 2. `Channel` 인터페이스 및 주요 메서드
|
|
|
|
| 메서드 | 설명 |
|
|
|--------|-----------------------------------|
|
|
| `open(Path path, OpenOption...)` | 파일 채널 열기 (`FileChannel.open(path)`) |
|
|
| `read(ByteBuffer dst)` | 데이터를 버퍼로 읽음 |
|
|
| `write(ByteBuffer src)` | 버퍼의 데이터를 채널에 씀 |
|
|
| `close()` | 채널 닫기 |
|
|
| `position()` | 현재 위치 반환 |
|
|
| `size()` | 파일 크기 반환 |
|
|
| `truncate(long size)` | 파일 크기를 지정한 크기로 자름 |
|
|
| `force(boolean metaData)` | 버퍼 내용을 강제로 디스크에 저장 |
|
|
|
|
**채널의 주요 종류**:
|
|
- `FileChannel` (파일 입출력)
|
|
- `SocketChannel` (TCP 소켓 통신)
|
|
- `ServerSocketChannel` (TCP 서버 소켓)
|
|
- `DatagramChannel` (UDP 통신)
|
|
|
|
---
|
|
|
|
### 3. `Selector` 클래스 및 주요 메서드
|
|
|
|
| 메서드 | 설명 |
|
|
|--------|-----------------------------|
|
|
| `open()` | 새로운 셀렉터 생성 |
|
|
| `select()` | I/O 이벤트가 발생할 때까지 대기 |
|
|
| `selectNow()` | 즉시 이벤트 확인 (블로킹 X) |
|
|
| `select(timeout)` | 지정된 시간 동안 대기 |
|
|
| `keys()` | 등록된 모든 채널 반환 |
|
|
| `selectedKeys()` | 이벤트가 발생한 채널 반환 |
|
|
| `wakeup()` | 블로킹 상태에서 셀렉터를 깨움 |
|
|
| `close()` | 셀렉터 닫기 |
|
|
|
|
**관련 클래스**:
|
|
- `SelectionKey.OP_READ` (읽기 가능)
|
|
- `SelectionKey.OP_WRITE` (쓰기 가능)
|
|
- `SelectionKey.OP_CONNECT` (연결 가능)
|
|
- `SelectionKey.OP_ACCEPT` (새로운 연결 가능)
|
|
|
|
---
|
|
|
|
## 자바 NIO 쉽게 설명하기
|
|
|
|
### NIO란 무엇인가?
|
|
NIO는 기존의 `java.io`보다 **더 빠르고 비동기적으로 입출력을 처리**할 수 있는 기술이다.
|
|
|
|
- **기존 방식 (IO)**
|
|
- 데이터를 **스트림(Stream)** 단위로 처리
|
|
- 블로킹 방식 (데이터를 읽거나 쓸 때 작업이 끝날 때까지 대기)
|
|
- 한 번에 하나의 입출력만 가능
|
|
|
|
- **NIO 방식**
|
|
- 데이터를 **버퍼(Buffer)와 채널(Channel)**을 이용해 처리
|
|
- 논블로킹 방식 (데이터를 읽거나 쓸 때 대기하지 않고 바로 진행)
|
|
- 하나의 스레드가 여러 채널을 관리 가능 (셀렉터 사용)
|
|
|
|
---
|
|
|
|
### 1. **버퍼(Buffer) 이해하기**
|
|
버퍼는 **데이터를 담아두는 공간**이다.
|
|
IO에서는 데이터를 바로 읽고 쓰지만, **NIO에서는 데이터를 버퍼에 담고 처리**한다.
|
|
|
|
```java
|
|
ByteBuffer buffer = ByteBuffer.allocate(1024); // 1KB 크기의 버퍼 생성
|
|
buffer.put("Hello NIO".getBytes()); // 데이터 쓰기
|
|
|
|
buffer.flip(); // 읽기 모드로 변경
|
|
byte[] data = new byte[buffer.remaining()];
|
|
buffer.get(data); // 데이터 읽기
|
|
System.out.println(new String(data)); // "Hello NIO"
|
|
```
|
|
- `put()` → 데이터를 버퍼에 저장
|
|
- `flip()` → 읽기 모드로 변경
|
|
- `get()` → 버퍼에서 데이터 읽기
|
|
|
|
---
|
|
|
|
### 2. **채널(Channel) 이해하기**
|
|
채널은 **데이터가 오가는 통로**다.
|
|
기존의 `InputStream` / `OutputStream` 대신 **파일, 소켓 등과 데이터를 주고받는 역할**을 한다.
|
|
|
|
#### **파일을 읽는 예제 (FileChannel)**
|
|
```java
|
|
Path path = Paths.get("example.txt");
|
|
FileChannel channel = FileChannel.open(path, StandardOpenOption.READ);
|
|
|
|
ByteBuffer buffer = ByteBuffer.allocate(1024);
|
|
channel.read(buffer); // 파일에서 데이터를 읽어 버퍼에 저장
|
|
|
|
buffer.flip();
|
|
byte[] data = new byte[buffer.remaining()];
|
|
buffer.get(data);
|
|
|
|
System.out.println(new String(data)); // 파일 내용 출력
|
|
channel.close();
|
|
```
|
|
- `FileChannel.open()` → 파일을 열고 채널 생성
|
|
- `read(ByteBuffer)` → 파일 데이터를 버퍼에 읽기
|
|
- `flip()` → 읽기 모드로 변경
|
|
- `get()` → 버퍼에서 데이터 가져오기
|
|
|
|
---
|
|
|
|
### 3. **논블로킹 소켓 (SocketChannel) 사용하기**
|
|
NIO의 강점은 **네트워크 프로그래밍에서 논블로킹 소켓**을 사용할 수 있다는 점이다.
|
|
즉, 하나의 스레드가 여러 소켓을 동시에 처리할 수 있다.
|
|
|
|
#### **비동기 TCP 클라이언트 예제**
|
|
```java
|
|
SocketChannel socketChannel = SocketChannel.open();
|
|
socketChannel.configureBlocking(false); // 논블로킹 모드 설정
|
|
socketChannel.connect(new InetSocketAddress("localhost", 8080));
|
|
|
|
while (!socketChannel.finishConnect()) {
|
|
System.out.println("연결 시도 중...");
|
|
}
|
|
|
|
ByteBuffer buffer = ByteBuffer.wrap("Hello Server".getBytes());
|
|
socketChannel.write(buffer); // 서버로 데이터 전송
|
|
|
|
socketChannel.close();
|
|
```
|
|
- `configureBlocking(false)` → 논블로킹 모드 설정
|
|
- `connect()` → 서버에 연결
|
|
- `write(ByteBuffer)` → 서버로 데이터 전송
|
|
|
|
---
|
|
|
|
### 4. **Selector로 다중 채널 관리하기**
|
|
셀렉터(Selector)를 사용하면 **하나의 스레드로 여러 채널을 관리**할 수 있다.
|
|
즉, 효율적인 **멀티플렉싱** 처리가 가능하다.
|
|
|
|
#### **비동기 서버 예제**
|
|
```java
|
|
Selector selector = Selector.open();
|
|
ServerSocketChannel serverChannel = ServerSocketChannel.open();
|
|
serverChannel.bind(new InetSocketAddress(8080));
|
|
serverChannel.configureBlocking(false);
|
|
serverChannel.register(selector, SelectionKey.OP_ACCEPT);
|
|
|
|
while (true) {
|
|
selector.select(); // I/O 이벤트 발생할 때까지 대기
|
|
|
|
for (SelectionKey key : selector.selectedKeys()) {
|
|
if (key.isAcceptable()) { // 클라이언트 연결 요청 처리
|
|
SocketChannel client = serverChannel.accept();
|
|
client.configureBlocking(false);
|
|
client.register(selector, SelectionKey.OP_READ);
|
|
} else if (key.isReadable()) { // 데이터 읽기 처리
|
|
SocketChannel client = (SocketChannel) key.channel();
|
|
ByteBuffer buffer = ByteBuffer.allocate(1024);
|
|
client.read(buffer);
|
|
buffer.flip();
|
|
System.out.println("Received: " + new String(buffer.array()).trim());
|
|
}
|
|
}
|
|
}
|
|
```
|
|
- `Selector.open()` → 셀렉터 생성
|
|
- `select()` → I/O 이벤트 발생 대기
|
|
- `register()` → 채널을 셀렉터에 등록
|
|
|
|
---
|
|
|
|
### 정리
|
|
자바 NIO는 **버퍼 + 채널 + 셀렉터**를 이용해
|
|
1. **파일 입출력을 빠르게 처리**하고
|
|
2. **네트워크 소켓을 논블로킹 방식으로 다룰 수 있게 해준다.**
|
|
|
|
**즉, 적은 스레드로 많은 연결을 처리하는 고성능 서버를 만들 때 강력한 도구가 된다!** |