
자바 개발을 하다 보면 파일을 읽거나 네트워크 통신을 할 때 수많은 클래스 사이에서 갈등하게 됩니다. "InputStream을 써야 하나, Reader를 써야 하나?" 이 질문은 자바 입출력(I/O)의 핵심을 관통하는 아주 중요한 질문입니다. 단순히 기능의 차이를 넘어, 데이터의 '타입'과 '인코딩'에 대한 이해가 필요하기 때문입니다. 오늘 포스팅에서는 이 네 가지 핵심 클래스의 차이점과 실무 활용 팁을 완벽하게 정리해 드립니다.
1. 데이터의 근간, 바이트 기반 스트림 (InputStream / OutputStream)
바이트 기반 스트림은 모든 입출력 시스템의 가장 낮은 단계에서 작동합니다. 8비트(1바이트) 단위로 데이터를 처리하며, 데이터의 실제 내용이 무엇인지(문자인지, 이미지인지) 상관하지 않고 '있는 그대로' 전송합니다.
- 용도: 이미지, 동영상, 실행 파일(.exe), 압축 파일(.zip) 등 텍스트가 아닌 이진 데이터(Binary Data) 처리.
- 특징: 데이터를 가공하지 않으므로 전송 속도가 빠르고 데이터 변형이 없습니다. 하지만 한글과 같은 다중 바이트 문자를 읽을 때는 글자가 깨지는 현상이 발생합니다.
2. 인간의 언어를 위해 탄생한 문자 기반 스트림 (Reader / Writer)
바이트 기반 스트림의 한계를 극복하기 위해 등장한 것이 문자 기반 스트림입니다. 16비트(2바이트) 단위로 데이터를 처리하며, 자바 내부의 유니코드 시스템과 외부 인코딩(UTF-8, MS949 등) 사이의 변환을 자동으로 수행합니다.
- 용도: 텍스트 파일(.txt), 소스 코드(.java), 설정 파일(.xml, .json) 등 문자 데이터(Character Data) 처리.
- 특징: 세계 각국의 언어를 인코딩 설정에 맞춰 안전하게 읽고 쓸 수 있습니다. 텍스트 처리의 표준이라고 할 수 있습니다.
3. 한눈에 비교하는 I/O 클래스 핵심 요약
두 그룹의 차이점을 표로 정리하면 다음과 같습니다. 이 표를 기억해 두시면 입출력 설계 시 큰 도움이 됩니다.
| 항목 | InputStream / OutputStream | Reader / Writer |
|---|---|---|
| 처리 단위 | 8-bit (Byte) | 16-bit (Unicode Character) |
| 데이터 종류 | Binary (이미지, 영상, 파일 등) | Text (문자열, 문서 등) |
| 인코딩 변환 | 수행하지 않음 | 자동 변환 수행 |
| 주요 메서드 | read(), write(int b) | read(), write(char[] cbuf) |
| 실무 팁 | 네트워크 전송, 파일 복사 | 파일 로그 기록, 텍스트 분석 |
4. 실전 샘플 예제 (Sample Example)
바이트 기반으로 읽어서 문자로 변환하는 InputStreamReader 활용 예제입니다. 이는 바이트 스트림과 문자 스트림을 연결하는 징검다리 역할을 합니다.
import java.io.*;
public class IOConverterExample {
public static void main(String[] args) {
// 파일에서 바이트 단위로 읽어 문자로 변환하는 예제
try (InputStream is = new FileInputStream("input.txt");
InputStreamReader isr = new InputStreamReader(is, "UTF-8");
BufferedReader br = new BufferedReader(isr)) {
String line;
while ((line = br.readLine()) != null) {
System.out.println("문자열 출력: " + line);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
5. 전문적인 관점에서의 조언
단순히 Reader와 Writer를 쓰는 것보다 중요한 것은 Buffer(버퍼)의 활용입니다. BufferedReader나 BufferedWriter를 함께 사용하지 않으면 매번 시스템 콜이 발생하여 성능이 저하됩니다. 또한, Java 7부터 지원하는 try-with-resources 구문을 사용하여 자원 반납(close)을 자동화하는 습관을 들이는 것이 가장 중요합니다.
출처 및 참고 자료
- Oracle Java 17 Documentation: java.io Package
- OpenJDK Source Code Analysis: I/O Implementation
'Language > Java' 카테고리의 다른 글
| [JAVA] 직렬화(Serialization) 완벽 이해와 Serializable 인터페이스의 비밀 (0) | 2026.01.20 |
|---|---|
| [JAVA] 버퍼(Buffered) 스트림을 사용하는 이유 : 입출력 성능의 비약적 향상 (0) | 2026.01.20 |
| [JAVA] 개발자의 숙명, Checked vs Unchecked Exception 깊이 파헤치기 (0) | 2026.01.20 |
| [JAVA] 프로그램의 안전벨트, try-catch-finally 실행 순서 완벽 가이드 (0) | 2026.01.20 |
| [JAVA] 프로그램의 생존을 결정짓는 분수령, Error와 Exception 완벽 분석 (0) | 2026.01.20 |