CodeGym /행동 /C# SELF /기본적인 직렬화 예제

기본적인 직렬화 예제

C# SELF
레벨 45, 레슨 0
사용 가능

1. 소개

기억할 점: 직렬화는 객체의 상태를 문자열, 파일 또는 스트림 형태로 저장해서 나중에 그 객체를 복원(역직렬화)할 수 있게 해주는 방법이야 — 그러면 동일한 데이터를 가진 객체를 다시 얻을 수 있어.

일상적인 상황 예시:
1) 예를 들어 이름과 나이를 가진 사용자 객체가 있어.
2) 이걸 저장해야 해 — 네트워크로 전송하거나 파일에 쓰거나, 또는 JSON 형식으로 변환한다고 하자.
3) 그다음 문자열/파일에서 데이터를 다시 꺼내서 — 객체를 다시 얻는 거야!

C#에선 거의 몇 줄 코드로 끝나. 어떻게 하는지 같이 보자.

우리 애플리케이션

작은 연락처 관리 앱을 만들고 있다고 하자. 직렬화하려는 Person 클래스가 있어.

public class Person
{
    // 직렬화를 위해 공개 속성(public properties)이 필요해!
    public string Name { get; set; }
    public int Age { get; set; }

    // XmlSerializer를 위해 매개변수 없는 생성자가 필요해
    public Person() { }

    public Person(string name, int age)
    {
        Name = name;
        Age = age;
    }
}

이런 문법이 익숙하지 않다면 걱정 마 — 강의에서 클래스와 속성을 자세히 다룰 거야. 지금은 실험용 데이터 모델로 받아들이면 돼. 주목할 점: 공개 속성인 Name과 Age는 직렬화에 중요하고, XmlSerializer는 매개변수 없는 공개 생성자를 요구한다는 걸 기억해.

2. System.Text.Json을 이용한 JSON 직렬화

가장 간단한 예

약속했지 — 보여줄게! JSON 직렬화는 다음과 같아:

using System;
using System.Text.Json;

Person person = new Person("알리사", 28);

// 직렬화: 객체를 JSON 문자열로 변환
string json = JsonSerializer.Serialize(person);

Console.WriteLine("JSON:");
Console.WriteLine(json);

화면에 뭐가 나올까?

JSON:
{"Name":"알리사","Age":28}

간단하지: 객체 → JSON. 이게 바로 매직이야!

역직렬화 — 다시 객체로 복원하기

이번엔 반대 작업을 해보자 — JSON 문자열에서 객체를 복원해볼게:

string json = "{\"Name\":\"밥\",\"Age\":35}";

// 역직렬화: JSON 문자열에서 Person 타입의 객체 복원
Person restored = JsonSerializer.Deserialize<Person>(json);

Console.WriteLine("복원된 객체:");
Console.WriteLine($"이름: {restored.Name}, 나이: {restored.Age}");

결과:

복원된 객체:
이름: 밥, 나이: 35

주의할 점: 데이터 구조가 일치하지 않으면(예: 해당 속성이 없음) 해당 필드는 기본값으로 남아 있을 거야 (null은 참조형, 숫자는 0 등).

3. XmlSerializer를 이용한 XML 직렬화/역직렬화

XML 직렬화 — 첫인상

using System;
using System.IO;
using System.Xml.Serialization;

Person person = new Person("카챠", 22);

// Person 타입용 serializer 생성
var serializer = new XmlSerializer(typeof(Person));

// XML을 파일에 기록
using (var stream = new FileStream("person.xml", FileMode.Create))
{
    serializer.Serialize(stream, person);
    // using 블록 끝에서 스트림이 자동으로 닫힘
}
Console.WriteLine("XML 파일 생성됨!");

파일 person.xml에는 대략 이렇게 생긴 내용이 들어갈 거야:

<?xml version="1.0"?>
<Person xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Name>카챠</Name>
  <Age>22</Age>
</Person>

중요 포인트:
파일로 직렬화할 때는 스트림(Stream, 예: FileStream)을 사용해. 만약 문자열로 직렬화해서(예: 네트워크 전송용) 보내고 싶다면 StringWriter를 사용해:

var serializer = new XmlSerializer(typeof(Person));
using (var sw = new StringWriter())
{
    serializer.Serialize(sw, person);
    string xmlString = sw.ToString();
    Console.WriteLine(xmlString);
}

XML에서 역직렬화

using (var stream = new FileStream("person.xml", FileMode.Open))
{
    // 원하는 타입으로 캐스팅하는 것 잊지 마!
    Person restored = (Person)serializer.Deserialize(stream);
    Console.WriteLine($"이름: {restored.Name}, 나이: {restored.Age}");
}

다시 한 번: XmlSerializer는 직렬화되는 클래스에 매개변수 없는 공개 기본 생성자가 있어야 해. 없으면 역직렬화 도중 예외가 발생할 거야.

4. 파일 vs 문자열: 뭘 선택할까?

실무에서는 직렬화를 문자열로 바로 해서(네트워크 전송/DB 저장) 쓰기도 하고, 파일로 저장해서(장기 보관) 쓰기도 해.

문자열 직렬화 (예: API로 전송할 때):

  • JSON: JsonSerializer.Serialize(obj) 사용.
  • XML: StringWriter 통해.

파일 직렬화 (예: 내보내기/백업):

  • JSON: 보통 문자열을 만들어 파일에 쓰면 돼.
  • XML: XmlSerializer로 스트림에 바로 쓰는 게 일반적.

예: 파일에 직렬화하고 다시 읽기 (JSON)

using System.IO;
using System.Text.Json;

Person person = new Person("톰", 42);

// 문자열로 직렬화
string json = JsonSerializer.Serialize(person);

// 파일에 기록
File.WriteAllText("contact.json", json);

// 파일에서 읽기
string readJson = File.ReadAllText("contact.json");
Person restored = JsonSerializer.Deserialize<Person>(readJson);

Console.WriteLine($"{restored.Name}, 나이: {restored.Age}");

5. JSON vs XML 비교

프로세스 시각화

헷갈리지 않게 직렬화/역직렬화 과정을 그림으로 보면:

flowchart LR
    A[객체] -- 직렬화 --> B[문자열/파일/스트림]
    B -- 역직렬화 --> C[객체]

    A -. JSON 또는 XML .-> B
    B -. JSON 또는 XML .-> C

직렬화는 짐을 싸는 것, 역직렬화는 집에서 짐을 푸는 것이라고 생각하면 돼.

비교 테이블

기능 JSON (System.Text.Json) XML (XmlSerializer)
문자열 읽기/쓰기 ++ +
파일 읽기/쓰기 ++ ++
기본 생성자 필요 여부 아니오 예
사람이 읽기 쉬운 정도 ++ +
엄격한 데이터 스키마(검증) - ++
유연성 (커스터마이즈 가능한 어트리뷰트) + ++
성능 ++ +
인터넷 호환성 ++ +

++ — 매우 좋음, + — 괜찮음, - — 지원 안 됨

6. 우리 앱에 직렬화 추가하기

연락처 관리자에 연락처 목록을 파일에 저장하고 복원하는 기능을 추가한다고 하자.

문맥: 연락처 목록은 List<Person> 형태로 되어 있어.

List<Person> contacts = new List<Person>
{
    new Person("바샤", 30),
    new Person("페챠", 25),
    new Person("마샤", 27)
};

// 모든 연락처 저장 — JSON으로 직렬화
string jsonContacts = JsonSerializer.Serialize(contacts);
File.WriteAllText("contacts.json", jsonContacts);

// 연락처 목록 복원
string readContactsJson = File.ReadAllText("contacts.json");
List<Person> restored = JsonSerializer.Deserialize<List<Person>>(readContactsJson);

foreach (var c in restored)
{
    Console.WriteLine($"{c.Name}, 나이: {c.Age}");
}

같은 걸 XML로도 할 수 있지만 몇 가지 특이점이 있어. XmlSerializer로 컬렉션을 직렬화할 때는 보통 리스트를 별도의 래퍼 클래스(루트 요소)로 감싸서 포맷과 요소 이름을 제어하는 편이 더 쉬워.

7. 직렬화/역직렬화에서 흔한 실수

오류 #1: 직렬화와 역직렬화 시 타입 불일치.
을 직렬화했으면 역직렬화할 때도 List<Person>로 복원해야 해. List<object>나 IEnumerable<Person>로 하려면 오류나 예상치 못한 결과가 날 수 있어.

오류 #2: 비공개 필드/속성을 직렬화하려는 시도.
일반 직렬화기(JsonSerializer, XmlSerializer)는 공개 멤버와 작업해. 속성에 공개 getter/setter가 없으면 값이 JSON/XML에 들어가지 않을 수 있고, 그래서 null이 되는 이유를 찾게 될 거야.

오류 #3: 기본 생성자 누락.
XmlSerializer는 공개 기본 생성자를 요구해. 없으면 역직렬화 중 예외가 남.

오류 #4: 객체 참조에 대한 오해.
한 객체가 다른 객체를 참조하고 있으면 직렬화는 값 기준으로(중첩된 객체로) 진행돼. 참조 자체가 저장되는 게 아니라서 데이터 중복이나 순환 참조 문제를 겪을 수 있어.

오류 #5: 직렬화 포맷 혼용 시도.
XML과 JSON은 다른 포맷이고 다른 직렬화기를 사용해. JSON 문자열을 XmlSerializer로 주입하거나 그 반대로 하면 오류가 발생해.

2
과제
C# SELF, 레벨 45, 레슨 0
잠금
객체의 JSON 직렬화와 역직렬화
객체의 JSON 직렬화와 역직렬화
코멘트
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION