본문 바로가기
Language/Java

[JAVA] InputStream/OutputStream vs Reader/Writer: 자바 I/O 완벽 가이드

by Papa Martino V 2026. 1. 20.
728x90

InputStream/OutputStream vs Reader/Writer
InputStream/OutputStream vs Reader/Writer

 

자바 개발을 하다 보면 파일을 읽거나 네트워크 통신을 할 때 수많은 클래스 사이에서 갈등하게 됩니다. "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(버퍼)의 활용입니다. BufferedReaderBufferedWriter를 함께 사용하지 않으면 매번 시스템 콜이 발생하여 성능이 저하됩니다. 또한, Java 7부터 지원하는 try-with-resources 구문을 사용하여 자원 반납(close)을 자동화하는 습관을 들이는 것이 가장 중요합니다.


출처 및 참고 자료

  • Oracle Java 17 Documentation: java.io Package
  • OpenJDK Source Code Analysis: I/O Implementation
728x90