상세 컨텐츠

본문 제목

BinaryFormatter / XmlSerializer / DataContractJsonSerializer

C#

by 탑~! 2018. 6. 29. 15:07

본문

C#에서는 문자열이나 정수와 같은 타입의 데이터를 byte배열로 변환하는 직렬화를 수행할 수 있으며 물론 그 반대로 가능합니다. 그렇다면 기본 데이터타입이 아닌 직접 만든 클래스와 같은 요소는 어떻게 직렬화를 수행할 수 있을까?

 

System.Runtime.Serialization.Formatters.Binary.BinaryFormatter가 그 답이 될 수 있습니다.

 

예를 들어 아래와 같은 클래스가 있습니다.

 

class Employee
{
    public Employee(string name, string department, int level)
    {
        Name = name;
        Department = department;
        Level = level;
    }

    public string Name
    {
        get;
        set;
    }

    public string Department
    {
        get;
        set;
    }

    public int Level
    {
        get;
        set;
    }
}

 

이 클래스를 직렬화하기 위해서는 우선 [Serializable] 이라는 특성을 클래스에 추가해 해당 클래스가 직렬화가능함을 알려줘야 합니다.

 

[Serializable]
class Employee

 

그리고 직렬화를 수행하려는 클래스에 대해 필요한 적절한 작업을 수행한 뒤

 

Employee e1 = new test.Employee("홍길동""관리부"4);

 

BinaryFormatter를 통해 MemoryStream으로 다음과 같이 직렬화를 수행합니다.

 

System.Runtime.Serialization.Formatters.Binary.BinaryFormatter bf = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();

MemoryStream ms = new MemoryStream();
bf.Serialize(ms, e1);

 

대부분 네트워크를 통해 다른 시스템으로 개체전체를 전송하고자 할때 직렬화를 많이 수행하는데 문제는 직렬화방식이 내부에 감춰져 있어서 .NET이 아닌 다른 플렛폼에서는 역직렬화가 힘들다는 단점이 있습니다.

 

Employee e1 = new test.Employee("홍길동""관리부"4);

System.Runtime.Serialization.Formatters.Binary.BinaryFormatter bf = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();

MemoryStream ms = new MemoryStream();
bf.Serialize(ms, e1);

ms.Position = 0;

Employee e2 = (Employee)bf.Deserialize(ms);

Console.WriteLine(e2.Name);

 

역직렬화는 간단합니다. BinaryFormatter의 Deserialize메서드를 호출해 Stream으로 읽기만 하면 됩니다. 물론 이 방법은 타 플렛폼과는 맞추기 힘든 부분이 있지만 같은 .NET환경이라면 비교적 빠르고 간단히 처리할 수 있습니다.

 

BinaryFormatter는 주어진 요소를 Binary로 직렬화하지만 System.Xml.Serialization.XmlSerializer는 문자열형태(기본 UTF8로 인코딩)로 직렬화를 수행합니다. 그런데 이름에서도 알 수 있듯이 그 문자열 포멧 형식이 XML입니다. 다만 XmlSerializer를 사용하려면 클래스를 다음과 같이 바꿔야 합니다.

 

public class Employee
{
    public Employee()
    { }
    public Employee(string name, string department, int level)
    {
        Name = name;
        Department = department;
        Level = level;
    }

    public string Name
    {
        get;
        set;
    }

    public string Department
    {
        get;
        set;
    }

    public int Level
    {
        get;
        set;
    }
}

 

먼저 클래스에 public 접근제한자가 있어야 하며 클래스안에 기본생성자를 포함해야 합니다. 하지만 이전에 추가했던 [Serializable]특성은 필요하지 않습니다.

 

Employee e1 = new test.Employee("홍길동""관리부"4);

System.Xml.Serialization.XmlSerializer xs = new System.Xml.Serialization.XmlSerializer(typeof(Employee));

MemoryStream ms = new MemoryStream();
xs.Serialize(ms, e1);

ms.Position = 0;

Employee e2 = (Employee)xs.Deserialize(ms);

Console.WriteLine(e2.Name);

 

BinaryFormatter와 클래스명만 다를뿐 사용법의 거의 똑같습니다. 차이라면 클래스를 통해 개체를 생성하는 부분에서는 XML스키마 작성을 위해 직렬화하려는 요소의 타입을 명시해야 한다는 것입니다.

 

XmlSerializer는 BinaryFormatter보다는 성능이 떨어지지만 XML이라는 표준포멧으로 직렬화를 수행하기에 타 플렛폼과의 호환성을 확보할 수 있다는 장점이 있습니다. 단, 직렬화되는 요소는 public제한자가 있는 필드만 가능합니다.

 

.NET 아닌 타 플렛폼입장에서 BinaryFormatter은 Binary변환으로 빠르게 처리될 수 있기는 하나 호환성에 문제가 생길 수 있고 XmlSerializer는 다소 긴 XML데이터를 생성하기는 하지만 XML포멧으로 인해 호환성문제는 해결될 수 있습니다. 각각 장단점이 존재하는데 이 둘의 장점만을 결합한 것이 바로 System.Runtime.Serialization.Json.DataContractJsonSerializer입니다. DataContractJsonSerializer는 문자열로 직렬화를 수행하기는 하지만 json포멧이기에 XML보다 훨씬 적은 데이터용량을 가질 수 있고 포멧또한 타 플렛폼에서 많이 다루는 것이므로 호환성도 확보할 수 있습니다.

 

Employee e1 = new test.Employee("홍길동""관리부"4);

System.Runtime.Serialization.Json.DataContractJsonSerializer dc = new System.Runtime.Serialization.Json.DataContractJsonSerializer(typeof(Employee));

MemoryStream ms = new MemoryStream();
dc.WriteObject(ms, e1);

ms.Position = 0;

Employee e2 = (Employee)dc.ReadObject(ms);

Console.WriteLine(e2.Name);

 

DataContractJsonSerializer에서 직렬화는 WriteObject()로 역직렬화는 ReadObject()메서드로 처리합니다.



출처: http://lab.cliel.com/entry/SystemRuntimeSerializationFormattersBinaryBinaryFormatter?category=478966 [CLIEL LAB]

'C#' 카테고리의 다른 글

대용량 txt 파일 짜르기  (0) 2018.06.29
ENCODING / BITCONVERTER  (0) 2018.06.29
EVENTWAITHANDLE  (0) 2018.06.29
LINQ  (0) 2018.06.29
MemoryStream / StreamWriter / StreamReader / BinaryWriter / BinaryReader  (0) 2018.06.29

관련글 더보기