
자바 개발자라면 System.out.println()을 수만 번은 사용해 보셨을 겁니다. 하지만 정작 System.out이 어떤 클래스인지, 그리고 실무 파일 출력이나 네트워크 통신에서 왜 PrintStream 대신 PrintWriter를 권장하는지 명확히 답할 수 있는 개발자는 의외로 많지 않습니다. 오늘은 출력 스트림의 양대 산맥인 두 클래스를 완벽히 해부해 보겠습니다.
1. 뿌리부터 다른 설계: Byte vs Character
가장 근본적인 차이는 데이터를 다루는 단위에 있습니다. 자바의 I/O 시스템은 크게 바이트 기반 스트림(InputStream/OutputStream)과 문자 기반 스트림(Reader/Writer)으로 나뉩니다.
- PrintStream: 바이트 출력 스트림(OutputStream)의 하위 클래스입니다. 주로 로우 레벨의 바이트 데이터를 처리하도록 설계되었습니다.
- PrintWriter: 문자 출력 스트림(Writer)의 하위 클래스입니다. 유니코드 문자를 처리하는 데 최적화되어 있으며, 국제화(i18n) 대응이 필요한 현대적인 애플리케이션에 적합합니다.
2. 왜 PrintWriter를 더 선호하는가?
과거에는 PrintStream이 널리 쓰였으나, 자바가 발전하면서 PrintWriter가 등장했습니다. 그 이유는 문자 인코딩(Character Encoding) 때문입니다. PrintStream은 플랫폼의 기본 인코딩을 사용하여 문자를 변환하는 경향이 있어, 서로 다른 운영체제(Windows vs Linux) 환경에서 한글 깨짐 현상 등이 발생할 확률이 높습니다. 반면 PrintWriter는 인코딩을 명시적으로 설정하기 훨씬 용이하며, 문자 전용 버퍼링을 사용해 효율적입니다.
3. 상세 비교 분석표
| 비교 항목 | PrintStream | PrintWriter |
|---|---|---|
| 기반 스트림 | OutputStream (바이트 기반) | Writer (문자 기반) |
| 주요 대상 | 콘솔 출력, 원시 바이트 데이터 | 텍스트 파일 저장, 네트워크 텍스트 전송 |
| 유니코드 처리 | 바이트 변환 과정에서 인코딩 이슈 가능성 | 문자 단위로 처리하여 유니코드에 안전함 |
| 예외 처리 | 내부적으로 예외를 잡고 플래그만 설정 | PrintStream과 동일 (checkError() 사용) |
| 생성자 유연성 | 파일, 스트림 등 다양하게 지원 | Writer 객체를 래핑하여 확장성 높음 |
4. 실전 코드 예제 (Sample Example)
두 클래스를 사용하여 파일에 텍스트를 기록하는 방식의 차이를 비교해 봅니다.
Case A: PrintStream (전통적인 방식)
import java.io.FileOutputStream;
import java.io.PrintStream;
public class PrintStreamExample {
public static void main(String[] args) {
try (PrintStream ps = new PrintStream(new FileOutputStream("output_ps.txt"))) {
ps.println("Hello, PrintStream!");
ps.printf("Format: %d, %s\n", 100, "Bytes");
} catch (Exception e) {
e.printStackTrace();
}
}
}
Case B: PrintWriter (권장되는 문자 중심 방식)
import java.io.FileWriter;
import java.io.PrintWriter;
import java.io.IOException;
public class PrintWriterExample {
public static void main(String[] args) {
// 두 번째 인자 true는 autoFlush 설정
try (PrintWriter pw = new PrintWriter(new FileWriter("output_pw.txt"), true)) {
pw.println("안녕하세요, PrintWriter입니다.");
pw.printf("값: %.2f (Unicode Safe)\n", 3.14159);
} catch (IOException e) {
e.printStackTrace();
}
}
}
5. 결론: 전문가의 선택 가이드
단순히 화면에 로그를 찍거나 표준 출력(System.out)을 사용할 때는 PrintStream을 그대로 써도 무방합니다. 이미 System.out이 PrintStream으로 구현되어 있기 때문입니다. 하지만 텍스트 기반의 파일을 생성하거나, 소켓 통신을 통해 문자열 데이터를 주고받는 경우라면 반드시 PrintWriter를 선택하십시오. 이는 데이터의 무결성을 보장하고, 다국어 환경에서 발생할 수 있는 잠재적인 버그를 차단하는 가장 전문적인 선택입니다.
출처 및 참고문헌
- Java SE 17 Specification: Class PrintStream Documentation
- Java SE 17 Specification: Class PrintWriter Documentation
- Java I/O: NIO and Networking (Elliotte Rusty Harold)
'Language > Java' 카테고리의 다른 글
| [JAVA] 자바 예외 계층 구조 완벽 가이드 : Checked와 Unchecked의 결정적 차이 (0) | 2026.01.20 |
|---|---|
| [JAVA] 외부 라이브러리 없이 JSON/XML 파싱하기 : 표준 API의 숨겨진 힘 (0) | 2026.01.20 |
| [JAVA] Scanner vs BufferedReader : 성능과 효율을 결정짓는 입력 방식의 모든 것 (0) | 2026.01.20 |
| [JAVA] Java 파일 입출력의 진화: Legacy File 클래스 vs Modern NIO.2 완벽 분석 (0) | 2026.01.20 |
| [JAVA] serialVersionUID란 무엇인가요? 직렬화 버전 관리의 핵심 정리 (0) | 2026.01.20 |