개발 기록

> [Java] 직렬화 (Serializable) 에 대해서 3. Java 객체 직렬화/역직렬화 방법(Json, YAML, binary ) - GSON, YAML Bean, Protocol Buffers 등 본문

JAVA

> [Java] 직렬화 (Serializable) 에 대해서 3. Java 객체 직렬화/역직렬화 방법(Json, YAML, binary ) - GSON, YAML Bean, Protocol Buffers 등

1z 2020. 12. 14. 10:52

 

Java 객체에 대한 다양한 직렬화(객체-> 바이트 스트림으로 변환) 접근 방식

① CSV

② JSON

③ YAML

④ 이진데이터

 

* 데이터 편집에는 YAML 이 적합하다. 반면에 바이너리 형식은 텍스트 형식보다 빠르므로. 애플리케이션에 속도가 중요한 경우 Apache Thrift 및 Google 프로토콜 버퍼를 사용하기 좋다. 둘 다 XML이나 JSON 형식보다 더 작고 빠르다.

1. CSV  

CSV 는 표 형태의 데이터에서 많이 사용되며 데이터를 표현하는 가장 많이 사용되는 방법 중 하나로 콤마(,) 기준으로 데이터를 구분하는 방법이다.  (ex. 홍길동, user@email.com, 40)

Member member = new Member("kimuser", "user@email.com", 25);
// member 객체를 csv로 변환 
String csv = String.format("%s,%s,%d",member.getName(), member.getEmail(), member.getAge());

 

★ 자바에서는 Apache Commons CSVopencsv 등의 라이브러리 등을 이용할 수 있다.

 


2. JSON  

 

JSON 는 구조적인 데이터를 전달하는 API 시스템 등에서 많이 사용한다. 다른 데이터 포맷 방식에 비해 오버헤드가 적다. 

★ 자바에서는 JacksonGSON  등의 라이브러리 등을 이용할 수 있다.

 

(1) Gson

   Google의 Gson은 Java 개체를 JSON 표현으로 직렬화 및 역직렬화하는 데 사용되는 라이브러리로  toJson() 및 fromJson() 메서드를 제공한다.

 

☞ Gson 기능

- 컬렉션, 일반 및 중첩 클래스를 처리할 수 있니다.

- Gson을 사용하면 전체 프로세스를 제어할 수 있도록 사용자 정의 직렬 변환기 및/또는 역직렬 변환기를 사용할 수 있다.

- 소스 코드에 액세스할 수 없는 클래스의 인스턴스를 역직렬화할 수 있다.

- 클래스 파일이 다른 버전으로 수정된 경우 @Since 주석과 setVersion()  메서드를 사용하여 버전 관리를 할 수 있다.

<dependency>
    <groupId>com.google.code.gson</groupId>
    <artifactId>gson</artifactId>
    <version>2.10.1</version>
</dependency>

 

 

▶ ex. User 개체를 " gson_user.json" 파일로 직렬화 

String filePath = "src/test/resources/protocols/gson_user.json";

// 직렬화
Writer writer = new FileWriter(filePath);
Gson gson = new GsonBuilder().setPrettyPrinting().create();
gson.toJson(user, writer);

// 역직렬화
Gson gson = new GsonBuilder().setPrettyPrinting().create();
User deserializedUser = gson.fromJson(new FileReader(filePath), User.class);

 

 

 

 

(2) Jackson API

ObjectMapper 클래스 에 속하는 writeValue(), readValue() 메소드를 사용하여 직렬화/ 역직렬화 한다.

 

Jackson 특징

- Java용 JSON 직렬화 라이브러리

- ObjectMapper 사용

- the highly customizable serialization and deserialization process

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-core</artifactId>
    <version>2.12.4</version>
</dependency>
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-annotations</artifactId>
    <version>2.12.4</version>
</dependency>
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
     <version>2.12.4</version>
</dependency>
String filePath = "src/test/resources/protocols/jackson_user.json";

// 직렬화 (jackson_user.json 파일 작성) 
File file = new File(filePath);
ObjectMapper mapper = new ObjectMapper();
mapper.writeValue(file, user);

// 역직렬화
User deserializedUser = mapper.readValue(new File(filePath), User.class);

 

 


3. 이진 직렬화 방법

데이터 변환 및 전송 속도에 최적화하여 별도의 직렬화 방법을 제시하는 구조이다. 바이너리 전송 형식으로 즉, 데이터가 바이너리로 전송된다. 

☞ 장점

- 언어와 플랫폼에 의존하지 않는다.

- 공간과 대역폭을 덜 차지 하므로 전송 속도를 향상 시킨다.

- 새 버전이 이전 데이터를 읽을 수 있고 그 반대로도 읽을 수 있도록 이전 버전 및 이후 버전과의 호환성을 모두 지원한다.

 

Protocol Buffer, Apache Avro, Apache Thrift  의 라이브러리를 이용할 수 있다.

(1)  Google Protocol Buffer

<dependency>
    <groupId>com.google.protobuf</groupId>
    <artifactId>protobuf-java</artifactId>
    <version>3.17.3</version>
</dependency>

 

▶ user.proto 문서 생성

message Member {
  required string name = 1;
  optional string email = 2;
  required int32 age = 3;
}

 

 

위의  user.proto 문서를 프로토콜 버퍼 컴파일러를 이용해서 변환한다.

 : 자바로 변환하게 되면 프로토콜 버퍼 형태의 Member 클래스가 생성되며, 자바 직렬화와 다른 점은 데이터 스펙을 표현하기 위한 문서가 존재한다는 것이다. 나머지는 같다.

Member member = Member.newBuilder()
    .setAge(10)
    .setName("홍길동")
    .setEmail("user@email.com")
    .build();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
member.writeTo(baos);
// 프로토콜 버퍼 직렬화된 데이터
byte[] serializedMember = baos.toByteArray();

 

▶  mergeFrom()  메서드를 사용하여 파일에서 해당 데이터를 로드하고 다시 User 개체로 역직렬화할 수 있다.

 


 

4. YAML 

 

Jackson API, SnakeYAML, YAML Bean  의 라이브러리를 이용할 수 있다.

* SnakeYAML의 경우 Java 객체를 YAML 문서로 직렬화하거나 그 반대로 직렬화하는 고급 API를 제공한다. Object, String , List 및 Map 과 같은 Java 구조를 구문 분석할 수 있다.

 

(1)  YAML Bean 

<dependency>
    <groupId>com.esotericsoftware.yamlbeans</groupId>
    <artifactId>yamlbeans</artifactId>
    <version>1.15</version>
</dependency>

 

▶YamlWriter 클래스의 write () 메소드를 사용하여 Java 객체를 YAML로 직렬화 한다. public field 와 Bean의 getter 메소드를 인식하여 이를 자동으로 처리한다.

 

▶반대로 YamlReader 클래스의  read () 메서드는 YAML 문서를 읽고 Java 객체로 역직렬화한다. 

// 직렬화
YamlWriter writer = new YamlWriter(new FileWriter(filePath));
writer.write(userMap()); // Map<String, User>
writer.close();

// 역직렬화
YamlReader reader = new YamlReader(new FileReader(filePath));
Object object = reader.read();
Map<String, User> deserializedUsers = (Map<String, User>) object;

 

 

 

 

 

참고

https://techblog.woowahan.com/2550/

https://www.baeldung.com/java-serialization-approaches