본문 바로가기

JAVA/Android

[JAVA][Android] 데이터 직렬화 (Serialize)

데이터 직렬화 (Serialize)

*데이터 직렬화는

   1. 객체를 저장하는 경우

   2. 데이터를 DB에 올리는 경우

   3. 파일을 작성하는 경우
   4. 파싱할 데이터를 통신하는 경우
등 여러가지 케이스에 유의미한 데이터를 저장해두기 위해 사용한다.

 

*유의미한 데이터 : 값(value)을 가지고 있다.
*무의미한 데이터 : 참조변수. 유의미한 데이터의 주소(address)를 가지고 있다.
                                -> 데이터가 값의 주소를 가지고 있는 경우, 데이터를 사용하려고 할 때

                                    해당 데이터의 주소는 바뀌어 의미를 잃었을 가능성이 크다.

또한 String 형식의 값이 참조변수로 구현되어 있는 경우, 
다른 형식들과는 다르게 메모리가 순서대로 배열되어 있지 않다.
따라서 직렬화가 필요하다. == 연속적인 데이터로 변환하는 과정이 필요하다.
                                            == 스트림으로 변환하는 과정이 필요하다.

*여기서 스트림(Stream)이란
    : 자바에서는 입출력을 스트림으로 처리하는데, 
    데이터의 연속적 배열을 의미하며 데이터를 보관할 경우 데이터 형식을 변환할 때 이용한다.
    이를 이용하여 파일에 저장할 경우 데이터를 영구히 보관할 수 있다.
    스트림은 단방향이며 선입선출 구조이다. 또한 연결 및 지연 될 수 있다. 
    -> 읽을 데이터가 없다면 생길 때까지 대기하고, 데이터가 꽉 차 있다면 순서가 될 때까지 대기한다.

*스트림의 종류
 1. 바이트 스트림
    : 바이트(8비트)의 입출력 시 이용
     (InputStream, OutputStram 클래스와 그의 하위 클래스 이용함
       주요 메서드 : abstract int read(), abstract void write(int byte) *한 바이트 단위 입출력 )
      문자 데이터와 바이너리 데이터에 관계없이 이용할 수 있음
 2. 문자 스트림
    : 16비트 형식의 문자나 문자열의 입출력 시 이용
      (Reader, Writer 클래스와 그의 하위 클래스 이용함
       주요 메서드 : abstract int read(), abstract void write(int byte) *한 문자 단위 입출력 )
      문자가 아닌 데이터에 적용할 경우 정상적으로 처리하지 못함 (깨짐 현상 발생)

*데이터 직렬화 예제
 데이터를 직렬화 하려면 해당 데이터 클래스에 java.io.Serializable 인터페이스를 상속받아야 한다.

import java.io.Serializable;

public class Fruit implements Serializable {
    private String taste;
    private String color;
    private int number;

    public Fruit(String taste, String color,int number){
        this.taste = taste;
        this.color = color;
        this.number = number;
    }

    public String getTaste() {
        return taste;
    }

    public void setTaste(String taste) {
        this.taste = taste;
    }

    public String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }

    public int getNumber() {
        return number;
    }

    public void setNumber(int number) {
        this.number = number;
    }
}
import android.os.Build;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.util.Base64;

import androidx.annotation.RequiresApi;

public class PracticeActivity {

    @RequiresApi(api = Build.VERSION_CODES.O)
    public void main(String[] args){
        convertSerializedData();
        convertJson();
    }

	/**JAVA format*/
    @RequiresApi(api = Build.VERSION_CODES.O)
    public void convertSerializedData(){
        Fruit fruit = new Fruit("sweet","yellow",1);
        byte[] serializedData = new byte[0];

        /**데이터 직렬화 과정*/
        try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()) {
            try (ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream)) {
                objectOutputStream.writeObject(fruit);
                serializedData = byteArrayOutputStream.toByteArray();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

        /**직렬화 된 데이터 serializedData를 출력함*/
        System.out.println(Base64.getEncoder().encodeToString(serializedData));
    }

	/**JSON format*/
    public void convertJson(){
        Fruit fruit = new Fruit("sweet","yellow",1);
        String json = String.format(
                "{\"taste\":\"%s\",\"color\":\"%s\",\"number\":%d}",
                fruit.getTaste(), fruit.getColor(), fruit.getNumber());
        System.out.println(json);
    }
}

나는 데이터 통신 시에 직렬화를 가장 많이 사용하기 때문에

InputStream 과 OutputStream을 이용한 직렬화 외에도 JSON형태로 직렬화 하는 경우를 추가로 정리한다. 

(이외에도 XML, CSV 형태가 있다.)

이렇게 직접 JSON 문자열을 작성하는 경우는 거의 없긴 하다.

JSON이란?

 

다만 APP끼리의 통신에서 직렬화 데이터의 전달 및 수신이 필요한 경우가 있는데,

그런 케이스에는 아래와 같이 통신하여 사용한다.

/**직렬화 데이터 전달*/
bundle.putSerializable("KEY","VALUE");
intent.putExtras(bundle)

/**직렬화 데이터 수신*/
Serializable data = bundle.getSerializableExtra("dataset");
FruitData fruitData = (FruitData)data;

 

데이터 직렬화가 필요한 경우에 직렬화를 하지 않을 경우 (Serializable 인터페이스를 상속받지 않는 경우), 

RuntimeException 등이 발생할 수 있다.