[Etc] 직렬화 (Serialization)와 역직렬화(Deserialization)

직렬화 (Serialization)와 역직렬화(Deserialization)에 대해 알아보자.


직렬화(Serialization)과 역직렬화(Deserialization) 💾 ➡️ 💻

  • 직렬화
    • 프로그램에서 사용하는 데이터를 파일이나 네트워크를 통해 전송하거나 저장하기 쉬운 형태로 변환하는 과정
  • 역직렬화
    • 그 반대로, 저장되거나 전송된 데이터를 다시 프로그램에서 사용할 수 있는 원래의 데이터 형태로 복원하는 과정

직렬화 (Serialization) 이란? 📦

직렬화는 메모리 상에 있는 객체나 데이터 구조를 바이트 스트림 형태로 변환하는 것을 의미한다.

마치 택배 상자에 물건을 포장하는 것처럼, 데이터를 “직렬” 형태로 나열하여 보관하거나 전송하기 좋게 만드는 것.

  • 주요 목적:

    • 데이터 저장: 객체의 상태를 파일이나 데이터베이스에 저장하여 영구적으로 보관 💾
    • 데이터 전송: 네트워크를 통해 객체를 다른 시스템으로 전송 🌐
    • 원격 호출 (RPC, RMI): 객체를 네트워크를 통해 다른 시스템의 메소드 인자로 전달 📞
  • 예시:

    • 객체를 JSON이나 XML 형태로 변환하여 텍스트 파일에 저장
    • 객체를 바이너리 형태로 변환하여 네트워크 소켓을 통해 전송

역직렬화 (Deserialization) 이란? 📦 ➡️ 💻

역직렬화는 직렬화된 바이트 스트림을 다시 원래의 객체나 데이터 구조로 복원하는 과정

택배 상자를 열어 내용물을 꺼내는 것과 비슷하게, 직렬화된 데이터를 “역으로 직렬”화하여 프로그램이 이해할 수 있는 형태로 되돌리는 것.

  • 주요 목적:

    • 저장된 데이터 로드: 파일이나 데이터베이스에서 직렬화된 객체를 읽어와 메모리에 복원 💾 ➡️ 💻
    • 전송된 데이터 수신: 네트워크를 통해 수신된 직렬화된 데이터를 객체로 변환 🌐 ➡️ 💻
    • 원격 호출 결과 처리: 원격 시스템으로부터 직렬화된 객체 형태로 결과를 받아 원래 객체로 복원 📞 ➡️ 💻
  • 예시:

    • JSON이나 XML 텍스트 파일을 읽어 객체로 복원
    • 바이너리 데이터를 네트워크 소켓으로부터 읽어 객체로 복원

언어별 직렬화 및 역직렬화 예시

JavaScripnt (Node.js)

JavaScript에서는 기본적으로 JSON 객체를 사용하여 직렬화 및 역직렬화를 많이 수행

  • 바이너리 직렬화는 Buffer 객체 등을 활용해야 합니다.
// 직렬화 (Serialization)
const data = { name: "David", city: "Seoul" };
const jsonString = JSON.stringify(data); // 📦 -> JSON String
console.log(jsonString); // {"name":"David","city":"Seoul"}

// 역직렬화 (Deserialization)
const loadedData = JSON.parse(jsonString); // JSON String -> 📦 -> 💻
console.log(loadedData); // { name: 'David', city: 'Seoul' }

Python

Python에서는 pickle 모듈을 사용하여 직렬화 및 역직렬화를 기본적으로 지원한다.

  • JSON, marshal 등 다양한 모듈도 활용 가능
    import pickle

    # 직렬화 (Serialization)
    data = {'name': 'Alice', 'age': 30}
    with open('data.pickle', 'wb') as f:
        pickle.dump(data, f) # 📦 -> 💾

    # 역직렬화 (Deserialization)
    with open('data.pickle', 'rb') as f:
        loaded_data = pickle.load(f) # 💾 -> 📦 -> 💻
    print(loaded_data) # {'name': 'Alice', 'age': 30}

Java

Java는 java.io.Serializable 인터페이스를 구현한 클래스에 대해 직렬화를 기본적으로 지원합니다.

  • JSON 라이브러리 (Jackson, Gson 등)를 사용하여 JSON 직렬화/역직렬화도 많이 사용됨.
import java.io.*;

class Person implements Serializable {
    String name;
    int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person{name='" + name + "', age=" + age + '}';
    }
}

public class SerializationExample {
    public static void main(String[] args) {
        // 직렬화 (Serialization)
        Person person = new Person("Bob", 25);
        try (FileOutputStream fileOut = new FileOutputStream("person.ser");
             ObjectOutputStream out = new ObjectOutputStream(fileOut)) {
            out.writeObject(person); // 📦 -> 💾
            System.out.println("Serialized data is saved in person.ser");
        } catch (IOException i) {
            i.printStackTrace();
        }

        // 역직렬화 (Deserialization)
        Person loadedPerson = null;
        try (FileInputStream fileIn = new FileInputStream("person.ser");
             ObjectInputStream in = new ObjectInputStream(fileIn)) {
            loadedPerson = (Person) in.readObject(); // 💾 -> 📦 -> 💻
        } catch (IOException i) {
            i.printStackTrace();
            return;
        } catch (ClassNotFoundException c) {
            System.out.println("Person class not found");
            c.printStackTrace();
            return;
        }
        System.out.println("Deserialized Person: " + loadedPerson); // Deserialized Person: Person{name='Bob', age=25}
    }
}

Kotlin

Kotlin은 Java와 유사하게 java.io.Serializable 인터페이스를 사용하거나, Jackson, Gson 같은 JSON 라이브러리를 활용

  • Kotlin Serialization library를 사용하여 더 간편하게 직렬화/역직렬화를 할 수도 있음
    import kotlinx.serialization.*
    import kotlinx.serialization.json.*
    import java.io.*

    @Serializable
    data class User(val name: String, val age: Int)

    fun main() {
        // 직렬화 (Serialization)
        val user = User("Eve", 28)
        val json = Json.encodeToString(User.serializer(), user) # 📦 -> JSON String
        println(json) # {"name":"Eve","age":28}

        // 역직렬화 (Deserialization)
        val loadedUser = Json.decodeFromString(User.serializer(), json) # JSON String -> 📦 -> 💻
        println(loadedUser) # User(name=Eve, age=28)


        // Java Serializable 사용 (Java와 동일)
        // ... (Java 예시 코드와 유사)
    }