직렬화란 무엇인가?
직렬화는 객체의 상태를 저장하거나 전송할 수 있는 형식(0과 1의 순서, 즉 바이너리 데이터)으로 변환하는 과정이다.
여기서 객체의 상태란, 객체가 가지고 있는 필드의 값들을 의미한다.
예를 들면, 어떤 클래스의 인스턴스가 'Name'이라는 문자열 필드와 'Age'라는 정수형 필드를 가지고 있다면,
직렬화는 이 'Name'과 'Age' 값을 메모리나 파일, 혹은 네트워크를 통해 전송할 수 있도록 변환하는 과정이다.
직렬화가 필요한 이유
프로그래머가 정의한 클래스나 구조체 같은 복합 데이터 형식은 단순한 기본 데이터 형식(int, string, float 등)과 달리,
한 번에 쉽게 스트림에 기록하거나 읽을 수 없다.
BinaryWriter/Reader, StreamWriter/Reader는 기본 데이터 형식을 스트림에 쓰고 읽을 수 있는 편리한 메서드를 제공한다.
하지만 복합 데이터 형식을 처리할 때는, 각 필드의 값을 특정 순서대로 기록하고, 동일한 순서로 읽는 코드를 작성해야 한다.
이 작업 가운데 오류가 발생하기 좋아서 C#에서는 직렬화를 통해 복합 데이터 형식을 쉽게 저장하고 읽을 수 있는 방법을 제공한다.
직렬화된 객체는 파일로 저장하거나, 네트워크로 전송할 수 있고, 후에 동일한 상태로 다시 복원하는 역직렬화도 가능하다.
.NET의 직렬화가 지원하는 형식
.NET에서는 0과 1의 순서로 구성되는 이진(Binary) 형식으로의 직렬화도 지원하지만 JSON(JavaScript Object Notation)이나 XML(Extensible Markup Language) 같은 텍스트 형식으로의 직렬화도 지원한다.
형식에 상관없이 결과만 다르고 직렬화 또는 역직렬화하는 요령은 비슷하다.
Serializable
C#에서는 객체를 직렬화할 수 있는 아주 간단한 방법을 제공한다.
그저 Serializable [[어트리뷰트(Attribute)]]를 클래스 선언부에 붙여주면 이 클래스는 메모리나 영구 저장 장치에 저장이 가능한 형식이 된다.
[Serializable]
class MyClass
{
public int Id;
public string Name;
public float Value;
public MyClass(int id, string name, float value)
{
Id = id;
Name = name;
Value = value;
}
}
이렇게 선언한 MyClass를 직렬화하는 방법
1. BinaryFormatter를 사용한 직렬화
다음과 같이 Stream 클래스와 BinaryFormatter를 이용해서 간단히 저장할 수 있다.
// 객체 생성
MyClass myObject = new MyClass(1, "Test Object", 123.45f);
// 직렬화
BinaryFormatter formatter = new BinaryFormatter();
using (FileStream stream = new FileStream("myData.bin", FileMode.Create))
{
formatter.Serialize(stream, myObject);
}
이제 저장한 myData.bin 파일을 역직렬화해보자.
MyClass deserializedObject;
BinaryFormatter formatter = new BinaryFormatter();
using (FileStream stream = new FileStream("myData.bin", FileMode.Open))
{
deserializedObject = (MyClass)formatter.Deserialize(stream);
}
2. Json 직렬화를 사용한 직렬화
최근에는 보안 및 가독성 때문에 'BinaryFormatter' 대신 JSON 직렬화를 많이 사용한다.
UnityEngine.JsonUtility를 사용한 직렬화
// 객체 생성
MyClass myObject = new MyClass(1, "Test Object", 123.45f);
// JSON 직렬화
string jsonString = JsonUtility.ToJson(myObject);
Debug.Log("Serialized JSON: " + jsonString);
System.IO.File.WriteAllText(Application.persistentDataPath + "/myData.json", jsonString);
이제 저장한 myData.json을 역직렬화해보자
MyClass deserializedObject;
// Json 직렬화
string jsonString = System.IO.File.ReadAllText(Application.persistentDataPath + "/myData.json");
deserializedObject = JsonUtility.FromJson<MyClass>(jsonString);
Debug.Log(deserializedObject.Value);