Files
java-examples/docs/nio.md

7.5 KiB

자바 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에서는 데이터를 버퍼에 담고 처리한다.

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)

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 클라이언트 예제

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)를 사용하면 하나의 스레드로 여러 채널을 관리할 수 있다.
즉, 효율적인 멀티플렉싱 처리가 가능하다.

비동기 서버 예제

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. 네트워크 소켓을 논블로킹 방식으로 다룰 수 있게 해준다.

즉, 적은 스레드로 많은 연결을 처리하는 고성능 서버를 만들 때 강력한 도구가 된다!