[Java] 48. 자바 I/O 활용

2025. 7. 1. 16:53·Java/IO, Network
I/O 활용

I/O 활용

#Java/adv2


회원 데이터를 관리하는 콘솔 프로그램 예제(Create, Read)

  • Member 클래스 정의 및 Repository 인터페이스 정의

/회원 관리 예제1 - 메모리

  • ArrayList에 저장하는 방법
  • 문제: 자바 프로그램 종료 시 모든 회원 정보가 사라진다

/회원 관리 예제2 - 파일에 보관

  • 파일에 저장해서 데이터를 영구 보존해보자.
  • 한 줄 단위로 회원 데이터를 파일에 저장(ID,Name,Age)
  • BufferedReader, BufferedWriter 보조 스트림을 이용.
  • try-with-resource로 스트림 선언 및 해제
    • 코드 블록이 끝나면 자동으로 close()가 호출
  • try (BufferedWriter bw = new BufferedWriter(new FileWriter(FILE_PATH, UTF_8, true)))
    • bw.write(member.getId() + DELIMITER + member.getName() + DELIMITER + member.getAge());
    • bw.newLine(); (회원 구분)
  • try (BufferedReader br = new BufferedReader(new FileReader(FILE_PATH, UTF_8)))
    • while ((line = br.readLine()) != null) : 한 줄씩(회원 한 명씩) 읽기
      • String[] memberData = line.split(DELIMITER);
      • members.add(new Member(memberData[0], memberData[1], Integer.valueOf(memberData[2])));
  • FileNotFoundException의 경우 IOException의 자식이다. findAll()에서 파일이 존재하지 않는 경우, 예외를 잡아서 빈 ArrayList를 반환해준다.
    • 해당 컬렉션에 데이터를 추가하지 않는 경우에는 List.of()를 사용하는게 좋다.
    • (BW로 쓰기를 할 때는 컬렉션을 거치지 않고 파일에 작성한다 List.of()로 불변 컬렉션 받는게 더 좋음)
  • 문제점: 각 필드를 구분하기 위해 구분자를 사용하여 저장할 때 구분자를 넣어주고, 조회할 때 구분자를 사용해서 구분해야 함.

/회원 관리 예제3 - DataStream

  • DataOutputStream, DataInputStream을 사용하면 자바의 데이터 타입을 그대로 사용할 수 있다.
  • 구분자를 사용하지 않아도 된다
  • try (DataOutputStream dos = new DataOutputStream(new FileOutputStream(FILE_PATH, true)))
    • dos.writeUTF(member.getName());, dos.writeInt(member.getAge());, …
  • try (DataInputStream dis = new DataInputStream(new FileInputStream(FILE_PATH)))
    • while (dis.available() > 0)
      • members.add(new Member(dis.readUTF(), dis.readUTF(), dis.readInt()));
  • FileNotFoundException의 경우 예외 처리는 이전과 동일
  • /DataStream 원리: 구분자나 개행 없이 데이터를 저장하고 조회할 수 있는 이유?
    • id와 name은 모두 문자열이라서, id1name1 이렇게 저장되는데, 어떻게 id와 name을 딱 끊어서 구분할까?
    • writeUTF() 은 UTF-8 형식으로 문자를 저장하는데, 저장할 때 2byte를 추가로 사용해서 앞에 글자의 길이를 저장해둔다. (3id1 5바이트(2 + 3), 5name1 7바이트(2 + 5), 20(정수, 나이, 4바이트))
    • readUTF()로 읽어들일 때 먼저 앞의 2byte로 글자의 길이를 확인하고 해당 길이 만큼 글자를 읽어들인다.
  • DataStream 덕분에 자바의 타입도 그대로 사용하고, 구분자도 제거할 수 있었다.
  • 모든 데이터를 문자로 저장할 때 보다 저장 용량도 더 최적화 할 수 있다.
  • 문제점: 더 편리해지긴 했는데, 여전히 회원의 필드 하나하나를 다 조회해서 각 타입에 맞도록 따로따로 저장하고 조회해야 한다.

/회원 관리 예제4 - ObjectStream :회원 객체 통채로 편하게 저장할 수 있는 방법

  • 회원 인스턴스도 생각해보면 메모리 어딘가에 보관되어 있다 메모리의 객체를 읽어서 저장해보자.
  • ObjectStream 을 사용하면 이렇게 메모리에 보관되어 있는 회원 인스턴스를 파일에 편리하게 저장할 수 있다.
  • /객체 직렬화
    • 메모리에 있는 객체 인스턴스를 바이트 스트림으로 변환하여 파일에 저장하거나 네트워크를 통해 전송할 수 있도록 하는 기능
    • 객체의 상태를 유지하여 나중에 역직렬화(Deserialization)를 통해 원래의 객체로 복원할 수 있다.
    • 객체 직렬화를 사용하려면 직렬화하려는 클래스는 반드시 Serializable 인터페이스를 구현해야 한다.
      • 아무런 기능이 없는 인터페이스다. 직렬화 가능한 클래스라는 표시가 목적이다.
      • 메서드 없이 단지 표시가 목적인 인터페이스를 마커 인터페이스라 한다.
      • 구현하지 않으면 NotSerializableException 예외가 발생한다.
    • 객체 직렬화와 관련된 키워드(참고 사항)
      • serialVersionUID: 객체 직렬화 버전을 관리한다.
      • transient 키워드: transient가 붙은 필드는 직렬화하지 않고 무시한다.
  • try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(FILE_PATH)))
    • List<Member> members = findAll(); members.add(member)
    • oos.writeObject(members);
    • 컬렉션 + 컬렉션에 포함된 member를 통째로 write한다.
    • 메모리의 객체를 읽어서 완전히 새로 쓴다. 대상 스트림 만들 때 append 이런 거 붙이면 안 된다.
  • try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(FILE_PATH)))
    • Object findObject = ois.readObject();
    • return (List<Member>) findObject;
    • add() 메서드에서 findAll()에서 반환된 컬렉션에 member를 추가하므로, 불변 컬렉션을 반환하는 List.of()를 사용하면 안 된다.
  • /직렬화
    • ObjectOutputStream을 사용하면 객체 인스턴스를 직렬화하여 byte로 변환할 수 있다.
    • 회원 목록 전체를 파일에 저장해야 하므로, members 컬렉션을 직렬화 해야한다
    • oos.writeObject(members)를 호출하면 members 컬렉션과 그 안에 포함된 Member를 모두 직렬화하여 byte로 변경한다. 그리고 oos와 연결되어 있는 FileOutputStream에 결과를 출력한다.
      • ArrayList, Member 같은 클래스 정보도 함께 저장된다
  • /역직렬화
    • ObjectInputStream을 사용하면 byte를 역직렬화하여 객체 인스턴스로 만들 수 있다.
    • 반환타입이 Object이므로 캐스팅해서 사용해야 한다.
  • 현재는 객체 직렬화를 거의 사용하지 않는다.

/XML, JSON, 데이터베이스

  • /객체 직렬화의 한계
    • 버전관리: 클래스 구조가 변경되면 이전 직렬화된 객체와 호환성 문제가 발생, UID 관리가 복잡함
    • 플랫폼 종속성: 자바에 종속적이어서, 다른 언어나 시스템과 상호 운영성 떨어짐
    • 성능 이슈: 직렬화/역직렬화 과정이 상대적으로 느리고 리소스를 많이 사용한다.
    • 유연성 부족: 직렬화된 형식 커스터마이징이 어려움
    • 크기 효율성: 데이터 크기가 상대적으로 크다
  • 객체 직렬화 대안1: XML
    • 플랫폼 종속성 문제를 해결하기 위해 등장
    • 복잡성과 무거움이라는 문제가 있었다. (데이터에 비해 태그 껍데기가 많음)
  • 객체 직렬화의 대안2 - JSON
    • JSON은 가볍고 간결
    • 자바스크립트와의 자연스러운 호환성
    • 웹 API와 RESTful 서비스가 대중화되면서 사실상 JSON은 표준 데이터 교환 포맷이 됨
    • 거의 모든 곳에서 호환이 가능하고, 사람이 읽고 쓰기 쉬운 텍스트 기반 포맷이어서 디버깅과 개발이 쉬움
    • 단점: 텍스트 기반 포맷이라 용량이 큼
  • 객체 직렬화의 대안3 - Protobuf, Avro - 더 적은 용량, 더 빠른 성능
    • 매우 작은 용량으로 더 빠른 속도가 필요하다면 Protobuf, Avro 같은 대안 기술이 있다.
    • 언어별로 존재한다. 협의가 편한곳에서 사용한다. 이 정도까지 최적화가 필요한 경우는 정말 드물다.
    • 호환성은 떨어지지만 byte 기반에, 용량과 성능 최적화가 되어 있으므로 매우 빠르다.
      • byte 기반이라 사람이 읽기는 어려움
  • /데이터베이스
    • 파일에 데이터를 저장하는 방식: 한계점
      • 데이터의 무결성을 보장하기 어렵다.
      • 데이터 검색과 관리의 비효율성이다.
      • 보안 문제, 대교모 데이터의 효율적인 백업과 복구
    • 이러한 문제점들을 하나하나 해결하면서 발전한 서버 프로그램이 바로 데이터베이스이다.
    • 실무에서는 이미지, 영상처럼 큰 데이터를 제외하면 대부분의 데이터를 파일에 저장하지 않고 데이터베이스에 저장한다.

Ref) 김영한의 실전 자바 - 고급 2편, I/O, 네트워크, 리플렉션 강의 | 김영한 - 인프런

'Java > IO, Network' 카테고리의 다른 글

[Java] 51. 네트워크 - 프로그램(2)  (0) 2025.07.01
[Java] 50. 네트워크 - 프로그램(1)  (0) 2025.07.01
[Java] 49. File, Files  (0) 2025.07.01
[Java] 47. 자바 IO 기본(2)  (0) 2025.07.01
[Java] 46. 자바 IO 기본(1)  (0) 2025.07.01
'Java/IO, Network' 카테고리의 다른 글
  • [Java] 50. 네트워크 - 프로그램(1)
  • [Java] 49. File, Files
  • [Java] 47. 자바 IO 기본(2)
  • [Java] 46. 자바 IO 기본(1)
lumana
lumana
배움을 나누는 공간 https://github.com/bebeis
  • lumana
    Brute force Study
    lumana
  • 전체
    오늘
    어제
    • 분류 전체보기 N
      • Software Development N
        • Performance
        • TroubleShooting
        • Refactoring
        • Test N
        • Code Style, Convetion
        • DDD
        • Software Engineering
      • Java N
        • Basic
        • Core
        • Collection
        • 멀티스레드&동시성
        • IO, Network
        • Reflection, Annotation
        • Modern Java(8~) N
        • JVM N
      • Spring
        • Framework
        • MVC
        • Transaction
        • AOP
        • Boot
        • AI
      • DB Access
        • Jdbc
        • JdbcTemplate
        • JPA
        • Spring Data JPA
        • QueryDSL
      • Computer Science
        • Data Structure
        • OS
        • Database
        • Network
        • 컴퓨터구조
        • 시스템 프로그래밍
        • Algorithm
      • HTTP
      • Infra N
        • Docker N
      • 프로그래밍언어론
      • Programming Language(Sub) N
        • Kotlin N
        • Python
        • C++
        • JavaScript
      • FE
        • HTML
        • CSS
        • React
        • Application
      • Unix_Linux
        • Common
      • PS
        • BOJ
        • Tip
        • 프로그래머스
        • CodeForce
      • Book Review
        • Clean Code
      • Math
        • Linear Algebra
      • AI
        • DL
        • ML
        • DA
        • Concepts
      • 프리코스
      • Project Review
      • LegacyPosts
      • 모니터
      • Diary
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
lumana
[Java] 48. 자바 I/O 활용
상단으로

티스토리툴바