Java ‐ Input & Output - dnwls16071/Backend_Study_TIL GitHub Wiki

📚 스트림

  • 자바 프로세스가 가지고 있는 데이터를 밖으로 보내려면 출력 스트림을 사용하면 되고 반대로 외부 데이터를 자바 프로세스 안으로 가져오려면 입력 스트림을 사용하면 된다.
  • 참고로 각 스트림은 단방향으로 흐른다.

스크린샷 2025-06-15 오후 8 59 09

  • FileOutputStream
    • 파일에 데이터를 출력하는 스트림
    • 파일이 없으면 파일을 자동으로 만들고 데이터를 해당 파일에 저장한다.
    • 폴더는 미리 만들어두어야 한다.
  • write()
    • byte 단위로 값을 출력한다.
  • FileInputStream
    • 파일에서 데이터를 읽어오는 스트림
  • read()
    • 파일에서 데이터를 byte 단위로 하나씩 읽어온다.
    • 파일의 끝(EOF, End of File)에 도달하면 -1을 리턴한다.
  • close()
    • 파일에 접근하는 것은 자바 입장에서 외부 자원을 사용하는 것이다.
    • 자바에서 내부 객체는 자동으로 GC가 되지만 외부 자원은 사용 후 반드시 닫아주어야 한다.

[ 부분으로 나누어 읽기와 전체 읽기 비교 ]

  • read(byte[], offset, length)
    • 스트림의 내용을 부분적으로 읽거나, 읽은 내용을 처리하면서 스트림을 계속해서 읽어야 할 경우에 적합하다.
    • 메모리 사용량을 제어할 수 있다.
    • 파일이나 스트림에서 일정한 크기의 데이터를 반복적으로 읽어야 할 때 유용하다.
  • readAllBytes()
    • 한 번의 호출로 모든 데이터를 읽을 수 있어 편리하다.
    • 작은 파일이나 메모리에 모든 내용을 올려 처리해야 하는 경우에 적합하다.
    • 메모리 사용량을 제어할 수 없다.
    • 큰 파일의 경우 OutOfMemoryError가 발생할 수 있다.

📚 InputStream/OutputStream

스크린샷 2025-06-15 오후 9 32 22

  • 현대 컴퓨터는 대부분 byte 단위로 데이터를 주고 받는다. 참고로 bit 단위는 너무 작기 때문에 byte 단위를 기본으로 사용한다.
  • 이렇게 데이터를 주고받는 것을 Input/Output(I/O)라 한다.
  • 자바 내부에 있는 데이터를 외부에 전달할 때 각각 데이터를 주고 받는 방식이 다르면 불편하기 때문에 이런 문제를 해결하기 위해 자바는 InputStream, OutputStream이라는 기본 추상 클래스를 제공한다.

스크린샷 2025-06-15 오후 9 35 13

스크린샷 2025-06-15 오후 9 35 20

  • InputStreamOutputStream이 다양한 스트림을 추상화하고 기본 기능에 대한 표준을 잡아둔 덕에 편리하게 입출력 작업을 수행할 수 있다.
    • 일관성 : 모든 종류 입출력 작업에 대해 동일한 인터페이스를 사용할 수 있어 코드 일관성이 유지된다.
    • 유연성 : 실제 데이터 소스나 목적지가 무엇인지에 관계없이 동일한 방식으로 코드를 작성할 수 있다.
    • 확장성 : 새로운 유형의 입출력 스트림을 쉽게 추가할 수 있다.
    • 재사용성 : 다양한 스트림 클래스들을 조합해 복잡한 입출력 작업을 수행할 수 있다.
    • 에러 처리 : 표준화된 예외 처리 메커니즘을 통해 일관된 방식으로 오류를 처리할 수 있다.

📚 파일 입출력과 성능 최적화

  • 자바에서 운영체제를 통해 디스크에 1Byte씩 전달하면 운영체제나 하드웨어 레벨에서 여러가지 최적화가 발생한다.
  • 따라서 실제로 디스크에 1Byte씩 계속 쓰는 것은 아니다.
  • 자바에서 1Byte씩 write()read()를 호출할 때마다 운영체제로의 시스템 콜이 발생하고 이 시스템 콜 자체가 상당한 오버헤드를 유발한다.
  • 운영체제와 하드웨어가 어느 정도 최적화를 제공하더라도 자주 발생하는 시스템 콜로 인한 성능 저하는 피할 수 없다. 결국 자바에서 read(), write() 호출 횟수를 줄여서 시스템 콜 횟수를 줄여야 한다.

📚 문자 다루기

  • 스트림은 byte만 사용할 수 있다.
  • 스트림을 문자로 저장할 수 있도록 해주는 것이 바로 OutputStreamWriter, InputStreamReader이다.

📚 Reader/Writer

스크린샷 2025-06-15 오후 10 13 00

  • 모든 데이터는 byte 단위로 저장된다.
  • 따라서 Reader/Writer가 아무리 문자를 다룬다고 해도 문자를 바로 저장할 순 없다.
  • 결과적으로 해당 클래스에 문자를 전달하면 결과적으로 내부에서는 지정된 문자 집합을 사용해서 문자를 byte를 인코딩해서 저장한다.

📚 XML, JSON, Database

객체 직렬화의 한계

  • 객체 직렬화를 사용하지 않는 이유
    • 버전 관리의 어려움 - 클래스 구조가 변경되면 이전에 직렬화된 객체와의 호환성 문제가 발생, serialVersionUID 관리가 복잡하다.
    • 플랫폼 종속성 - 자바 직렬화는 자바 플랫폼에 종속적이어서 다른 언어나 시스템과의 상호 운용성이 떨어진다.
    • 성능 이슈 - 직렬화/역직렬화 과정이 상대적으로 느리고 리소스를 많이 사용한다.
    • 유연성 부족 - 직렬화된 형식은 커스터마이징하기 어렵다.
    • 크기 효율성 - 직렬화된 데이터 크기가 상대적으로 크다.

1. 객체 직렬화의 대안 - XML

  • 플랫폼 종속성 문제를 해결하기 위해 XML이라는 기술이 인기를 끌었다.
  • 허나 XML은 복잡성과 무거움이라는 문제가 존재한다.
  • 태그를 포함한 XML 문서 크기가 커서 네트워크 전송 비용도 증가했다.

2. 객체 직렬화의 대안 - JSON

  • JSON은 가볍고 간결하며 자바스크립트와의 자연스러운 호환성 덕분에 웹 개발자들 사이에서 빠르게 확산되었다.
  • 웹 API와 RESTful 서비스가 대중화되면서 JSON은 표준 데이터 교환 포맷으로 자리 잡았다.

3. 객체 직렬화의 대안 - Protobuf, Avro

  • JSON은 거의 모든 곳에서 호환이 가능하고 사람이 읽고 쓰기 쉬운 포맷이어서 디버깅과 개발이 쉽다.
  • 매우 작은 용량으로 더 빠른 속도가 필요하다면 Protobuf, Avro 등을 고려할 수 있다.
  • 하지만 이런 기술들은 호환성은 떨어지지만 용량과 성능 최적화가 되어 있어 매우 빠르다.
  • 다만 byte 기반이기 때문에 사람이 읽기 쉽지 않다.

결론 : 자바 객체 직렬화는 사용하지 마라.

⚠️ **GitHub.com Fallback** ⚠️