자바 I/O의 **데코레이터 스트림(Decorator Stream)**은 기본 스트림에 특별한 기능을 '장식'처럼 덧입혀주는 아주 똑똑한 도구들입니다.
📘 데코레이터 스트림: "기본 수도관의 변신"
데코레이터 스트림은 스스로 데이터를 읽거나 쓸 수는 없지만, 다른 스트림을 감싸서 새로운 능력을 부여합니다.
1. Character Conversion (문자 변환: InputStreamReader / OutputStreamWriter)
- 기능: 바이트(0, 1)만 흐르는 수도관에 '통역사'를 앉히는 것과 같습니다.
- 설명: InputStream 같은 바이트 기반 스트림을 Reader 같은 문자 기반 스트림으로 변환해 줍니다.
- 예시: 네트워크에서 들어오는 바이트 데이터를 우리가 읽을 수 있는 한글 텍스트로 바꿀 때 필수적입니다.
2. Performance Enhancement (성능 향상: BufferedInputStream / BufferedReader)
- 기능: 수도관 중간에 '임시 저장 탱크(버퍼)'를 설치하는 것입니다.
- 설명: 데이터를 하나씩 옮기지 않고 바구니에 가득 모았다가 한꺼번에 옮겨서 속도를 획기적으로 높여줍니다.
- 예시: 수만 줄의 텍스트 파일을 읽을 때 버퍼를 쓰지 않으면 컴퓨터가 매우 힘들어하지만, 이 장식을 쓰면 순식간에 끝납니다.
3. Primitive Type I/O (기본 타입 입출력: DataInputStream / DataOutputStream)
- 기능: 단순한 바이트를 자바의 '자료형' 단위로 해석해 주는 장치입니다.
- 설명: int, double, boolean 같은 자바의 기본 자료형 데이터를 깨지지 않게 그대로 읽고 쓸 수 있게 해줍니다.
- 예시: 숫자 100을 저장할 때 문자 '1', '0', '0'이 아니라 정수 int 값 그대로 파일에 기록하고 싶을 때 사용합니다.
4. Printing a Newline (줄바꿈 출력: PrintWriter / PrintStream)
- 기능: 데이터를 예쁘게 출력해 주는 '고급 프린터' 기능을 추가합니다.
- 설명: 우리가 흔히 쓰는 System.out.println()이 바로 이 계열입니다.
- 예시: 특히 println() 메서드는 자동으로 **줄바꿈(Newline)**을 처리해 주어, 일일이 \n을 넣지 않아도 데이터를 보기 좋게 정렬해 줍니다.
📦 데코레이터 사용 예제 (한 번에 감싸기)
여러 개의 장식을 겹겹이 포장하는 실제 코드를 확인해 보세요.
Java
import java.io.*;
public class DecoratorExample {
public static void main(String[] args) {
// 1. 파일 쓰기 예시 (기본 + 성능향상 + 줄바꿈기능)
try (PrintWriter pw = new PrintWriter(new BufferedWriter(new FileWriter("magic.txt")))) {
pw.println("첫 번째 줄입니다."); // Printing a newline (자동 줄바꿈)
pw.println("데코레이터 패턴은 정말 편리해요!");
} catch (IOException e) {
e.printStackTrace();
}
// 2. 기본 타입 쓰기 예시 (기본 + 자료형 입출력)
try (DataOutputStream dos = new DataOutputStream(new FileOutputStream("data.bin"))) {
dos.writeInt(2026); // Primitive type (int)
dos.writeDouble(3.14159); // Primitive type (double)
dos.writeBoolean(true); // Primitive type (boolean)
} catch (IOException e) {
e.printStackTrace();
}
}
}
👨🏫 쉽게 이해하는 핵심 포인트
자바 I/O 클래스 이름만 봐도 용도를 알 수 있습니다.
- 이름에 **Buffered**가 들어가면? → Performance Enhancement (빠름!)
- 이름에 **Data**가 들어가면? → Primitive Type I/O (자바 자료형 그대로!)
- 이름에 **InputStreamReader**처럼 두 단어가 섞여 있으면? → Character Conversion (변환!)
오늘의 요약
- 데코레이터는 기본 스트림을 '감싸서' 기능을 확장한다.
- 성능을 생각한다면 Buffered를, 자료형이 중요하다면 Data를 감싼다.
- **PrintWriter**는 줄바꿈(println) 기능을 제공하여 출력을 아주 편하게 해준다.
이제 데코레이터 스트림을 활용해 더 강력하고 효율적인 프로그램을 만드실 수 있게 되었습니다!
이번에는 앞서 언급한 4가지 핵심 키워드를 각각의 독립된 예제 코드로 만들어, 어떤 상황에서 어떤 클래스를 써야 하는지 확실히 보여드릴게요.
📘 데코레이터 스트림 실무 예제 정복
1. Character Conversion (문자 변환)
상황: 바이트 단위로 읽는 System.in(키보드 입력)을 우리가 읽기 쉬운 '문자'로 바꾸고 싶을 때 사용합니다.
Java
import java.io.*;
public class ConversionExample {
public static void main(String[] args) throws IOException {
// InputStream(바이트)을 Reader(문자)로 변환해주는 다리 역할을 합니다.
InputStreamReader isr = new InputStreamReader(System.in);
System.out.print("아무 글자나 입력하고 엔터를 치세요: ");
int data = isr.read(); // 바이트가 아닌 '문자' 단위로 읽습니다.
System.out.println("읽은 문자: " + (char)data);
}
}
2. Performance Enhancement (성능 향상)
상황: 아주 큰 텍스트 파일을 읽을 때, 한 글자씩 읽는 것(FileReader)과 양동이에 담아 읽는 것(BufferedReader)의 차이를 보여줍니다.
Java
import java.io.*;
public class PerformanceExample {
public static void main(String[] args) {
try (BufferedReader br = new BufferedReader(new FileReader("large_text.txt"))) {
String line;
// 한 줄씩 통째로 읽기 때문에 속도가 어마어마하게 빠릅니다.
while ((line = br.readLine()) != null) {
// 데이터 처리 (예: 출력)
}
System.out.println("성능 향상 스트림으로 읽기 완료!");
} catch (IOException e) {
System.out.println("파일이 없으면 실행되지 않아요!");
}
}
}
3. Primitive Type I/O (기본 자료형 입출력)
상황: 메모장에 적힌 "100"이라는 글자가 아니라, 컴퓨터가 인식하는 숫자 100(int) 그대로를 파일에 저장하고 싶을 때 씁니다.
Java
import java.io.*;
public class PrimitiveExample {
public static void main(String[] args) {
// 1. 데이터 쓰기 (int, double, boolean 저장)
try (DataOutputStream dos = new DataOutputStream(new FileOutputStream("data.dat"))) {
dos.writeInt(2026);
dos.writeDouble(99.9);
dos.writeBoolean(true);
} catch (IOException e) { e.printStackTrace(); }
// 2. 데이터 읽기 (저장한 순서대로 읽어야 합니다!)
try (DataInputStream dis = new DataInputStream(new FileInputStream("data.dat"))) {
System.out.println("정수: " + dis.readInt());
System.out.println("실수: " + dis.readDouble());
System.out.println("불린: " + dis.readBoolean());
} catch (IOException e) { e.printStackTrace(); }
}
}
4. Printing a Newline (줄바꿈 출력)
상황: 가장 편하게 데이터를 출력하고 싶을 때 사용합니다. \n을 직접 치지 않아도 자동으로 줄을 바꿔줍니다.
Java
import java.io.*;
public class PrintExample {
public static void main(String[] args) {
// PrintWriter는 모든 타입을 문자열로 예쁘게 출력해줍니다.
try (PrintWriter pw = new PrintWriter(new FileWriter("print.txt"))) {
pw.println("첫 줄입니다."); // Printing a newline (자동 줄바꿈)
pw.println(100); // 숫자도 자동으로 문자열로 변환
pw.printf("이름: %s, 나이: %d", "제미나이", 1); // 포맷 출력도 가능
} catch (IOException e) { e.printStackTrace(); }
}
}
👨🏫 한눈에 정리하는 데코레이터 조합 공식
실무에서는 보통 이렇게 3단 합체를 즐겨 사용합니다.
- new PrintWriter(new BufferedWriter(new FileWriter("file.txt")))
- FileWriter: 파일을 만든다. (기본)
- BufferedWriter: 속도를 올린다. (성능)
- PrintWriter: println() 기능을 쓴다. (편의성)
오늘의 요약
- InputStreamReader: 바이트를 문자로 변환할 때 쓴다.
- BufferedReader: 대용량 데이터를 빠르게 처리할 때 필수다.
- DataStream: 자바의 자료형(int, boolean 등)을 그대로 보존한다.
- PrintWriter: 줄바꿈(println) 기능을 활용해 보고서를 쓰듯 데이터를 출력한다.
예제 코드가 추가되니 데코레이터의 역할이 더 명확해지셨나요?

'JAVA 80%' 카테고리의 다른 글
| Thread (0) | 2026.01.31 |
|---|---|
| I/0 API (0) | 2025.11.06 |
| I/O Stream (0) | 2025.11.06 |
| LIFO/FIFO collection - Stack - Queue (0) | 2025.11.06 |
| Collection framework (0) | 2025.11.05 |