1. 기존 IO vs NIO 비교
자바에서는 기존 java.io 패키지와 새로운 java.nio 패키지를 이용해 입출력을 처리할 수 있다. 각각의 차이점과 사용처를 이해하면 적절한 방법을 선택하는 데 도움이 된다.
비교 항목 | 기존 IO (java.io) | NIO (java.nio) |
데이터 처리 방식 | 스트림(Stream) 기반 | 버퍼(Buffer) 기반 |
입출력 방식 | 블로킹(Blocking) 방식 | 논블로킹(Non-blocking) 방식 |
성능 | 작은 데이터 처리에 적합 | 대량 데이터 처리에 유리 |
주요 클래스 | InputStream, OutputStream, Reader, Writer | ByteBuffer, CharBuffer, FileChannel, SocketChannel |
사용 예시 | 파일 읽기/쓰기, 간단한 콘솔 입력 | 네트워크 서버, 대용량 파일 처리 |
2. 자바 NIO(New IO)란?
자바 NIO는 기존의 java.io 패키지 기반 입출력보다 더 빠르고 유연한 입출력 처리를 제공하는 API이다. NIO는 채널(Channel), 버퍼(Buffer), 비동기 입출력(Asynchronous IO) 등의 개념을 기반으로 한다.
2.1 주요 개념
- 채널 (Channel): NIO에서 데이터를 읽고 쓰는 핵심 요소로, 기존 IO의 스트림(Stream)과 비슷하지만 더 강력한 기능을 제공한다. 스트림이 한 방향으로만 데이터를 처리하는 것과 달리, 채널은 양방향 입출력을 지원한다. 대표적인 채널 클래스에는 FileChannel, SocketChannel, ServerSocketChannel 등이 있다/
* 양방향 입출력이란?
양방향 입출력(Bidirectional I/O)은 한 개의 스트림이나 채널을 통해 데이터를 읽고 쓰는 것이 모두 가능한 방식을 의미한다. 기존 IO에서는 입력 스트림(InputStream)과 출력 스트림(OutputStream)이 분리되어 있지만, NIO의 Channel을 사용하면 하나의 채널을 통해 동시에 읽기와 쓰기가 가능하다. 이 방식은 네트워크 통신 및 파일 처리를 더욱 유연하게 만들어준다.
- 버퍼 (Buffer): 데이터를 임시로 저장하는 메모리 공간으로, 입출력 성능을 향상시키는 데 사용된다.
- 셀렉터 (Selector): 다중 채널을 효율적으로 관리하는 역할을 하며, 단일 스레드에서 여러 개의 채널을 모니터링할 수 있어 네트워크 서버 개발에 유용하다.
2.2 FileChannel을 이용한 파일 읽기
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
public class NIOFileReadExample {
public static void main(String[] args) {
Path path = Path.of("example.txt");
try (FileChannel fileChannel = FileChannel.open(path, StandardOpenOption.READ)) {
ByteBuffer buffer = ByteBuffer.allocate(1024);
int bytesRead;
while ((bytesRead = fileChannel.read(buffer)) > 0) {
buffer.flip();
while (buffer.hasRemaining()) {
System.out.print((char) buffer.get());
}
buffer.clear();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
3. 직렬화(Serialization)와 역직렬화(Deserialization)
자바에서 객체를 파일이나 네트워크를 통해 저장하거나 전송할 때 **직렬화(Serialization)**를 사용한다. 직렬화는 객체를 바이트 스트림으로 변환하는 과정이며, **역직렬화(Deserialization)**는 다시 객체로 복원하는 과정이다.
3.1 직렬화 개념과 필요성
직렬화는 객체를 전송하거나 저장하기 위해 이진 데이터 형태로 변환하는 과정이다. 직렬화된 객체는 파일 시스템에 저장되거나 네트워크를 통해 전송될 수 있다. 대표적인 사용 사례는 다음과 같다.
- 객체를 파일에 저장할 때: 프로그램 실행 중 생성된 객체를 저장하고, 이후 다시 불러와 사용할 수 있다.
- 네트워크 통신에서 데이터 전송: 클라이언트와 서버 간 객체 데이터를 주고받을 때 직렬화가 필수적이다.
- 캐싱 및 데이터베이스 저장: 객체를 직렬화하여 캐싱 시스템에 저장하면 빠르게 복원할 수 있다.
3.2 직렬화 구현 방법
자바에서는 Serializable 인터페이스를 구현하여 직렬화를 지원한다.
import java.io.*;
class Person implements Serializable {
private static final long serialVersionUID = 1L;
String name;
int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
}
3.3 직렬화와 역직렬화 예제
import java.io.*;
public class SerializationExample {
public static void main(String[] args) {
Person person = new Person("Alice", 30);
String filename = "person.ser";
// 직렬화
try (ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(filename))) {
out.writeObject(person);
System.out.println("직렬화 완료");
} catch (IOException e) {
e.printStackTrace();
}
// 역직렬화
try (ObjectInputStream in = new ObjectInputStream(new FileInputStream(filename))) {
Person deserializedPerson = (Person) in.readObject();
System.out.println("역직렬화된 객체: " + deserializedPerson.name + ", " + deserializedPerson.age);
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
}
}
4. 마무리
이번 글에서는 자바의 고급 입출력 기법인 NIO와 직렬화에 대해 살펴보았다.
- 기존 IO vs NIO 비교를 통해 각각의 특징과 장단점을 파악했다.
- 채널, 버퍼, 셀렉터를 활용한 NIO의 핵심 개념을 설명했다.
- 파일 채널을 활용한 입출력 예제를 살펴보았다.
- 직렬화와 역직렬화 개념을 학습하고, 실제로 객체를 저장하고 불러오는 과정을 코드로 확인했다.
NIO와 직렬화는 대규모 데이터 처리 및 네트워크 통신에서 필수적인 개념이므로, 다양한 예제와 실습을 통해 익히는 것이 중요하다. 앞으로도 다양한 입출력 방식과 최적화 기법을 활용하여 효율적인 프로그램을 작성할 수 있도록 연습하자.
'JAVA' 카테고리의 다른 글
자바 네트워크 입출력(Network IO) (0) | 2025.03.07 |
---|---|
자바 입출력(IO) 쉽게 이해하기 (1) | 2025.03.05 |
[java] 변수의 타입(자료형, data type) (0) | 2024.05.14 |
요청 URL 가져오는 메서드들 정리 (0) | 2023.09.28 |
[java] 지네릭스-<T extends Fruit>과 <? extends Fruit>의 차이 (0) | 2023.07.14 |