์ฝ˜ํ…์ธ  ๋Œ€ํ‘œ ์ด๋ฏธ์ง€ - ๐Ÿ—‚๏ธ C# ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ์™€ ํŒŒ์‹ฑ ์™„์ „์ •๋ณต โ€” JSON ยท XML ยท CSV ๋ณ€ํ™˜ ๊ธฐ๋ฒ• ์‹ค์ „ ๊ฐ€์ด๋“œ
C# ํ”„๋กœ๊ทธ๋ž˜๋ฐ

๐Ÿ—‚๏ธ C# ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ์™€ ํŒŒ์‹ฑ ์™„์ „์ •๋ณต โ€” JSON ยท XML ยท CSV ๋ณ€ํ™˜ ๊ธฐ๋ฒ• ์‹ค์ „ ๊ฐ€์ด๋“œ

๋ฐ์ดํ„ฐ๋ฅผ ์ž์œ ์ž์žฌ๋กœ ์ฃผ๋ฌด๋ฅด๋Š” C# ๊ฐœ๋ฐœ์ž๊ฐ€ ๋˜๊ณ  ์‹ถ๋‹ค๋ฉด? ์ง€๊ธˆ ๋ฐ”๋กœ ์‹œ์ž‘ํ•ด๋ณด์ž! ๐Ÿ˜Ž
JSON, XML, CSV โ€” ์„ธ ๊ฐ€์ง€ ํฌ๋งท์˜ ํŒŒ์‹ฑ๊ณผ ๋ณ€ํ™˜์„ ํ•œ ๋ฒˆ์— ๋งˆ์Šคํ„ฐํ•˜๋Š” ์‹ค์ „ ์—ฌ์ • ๐Ÿš€

C# ๋ฐ์ดํ„ฐ ํŒŒ์‹ฑ { } JSON Newtonsoft System.Text.Json </> XML XmlDocument LINQ to XML โ‰ก CSV StreamReader CsvHelper C#์œผ๋กœ ์„ธ ๊ฐ€์ง€ ๋ฐ์ดํ„ฐ ํฌ๋งท์„ ์ž์œ ๋กญ๊ฒŒ ๋ณ€ํ™˜ํ•˜๊ณ  ํŒŒ์‹ฑํ•˜์ž! ์ง๋ ฌํ™”(Serialization) ยท ์—ญ์ง๋ ฌํ™”(Deserialization) ยท ๋ณ€ํ™˜(Transform)

๐Ÿค” ๋ฐ์ดํ„ฐ ํŒŒ์‹ฑ, ์™œ ์ด๋ ‡๊ฒŒ ์ค‘์š”ํ•œ ๊ฑฐ์•ผ?

์†”์งํžˆ ๋งํ•˜๋ฉด, ์š”์ฆ˜ ๊ฐœ๋ฐœํ•˜๋ฉด์„œ ๋ฐ์ดํ„ฐ ํŒŒ์‹ฑ์„ ์•ˆ ์“ฐ๋Š” ํ”„๋กœ์ ํŠธ๋Š” ๊ฑฐ์˜ ์—†๋‹ค๊ณ  ๋ด๋„ ๋ฌด๋ฐฉํ•ด.
API ํ˜ธ์ถœํ•˜๋ฉด JSON์ด ๋‚ ์•„์˜ค๊ณ , ๋ ˆ๊ฑฐ์‹œ ์‹œ์Šคํ…œ์€ XML์„ ๋ฑ‰์–ด๋‚ด๊ณ , ์—‘์…€ ๋ฐ์ดํ„ฐ๋Š” CSV๋กœ ๋„˜์–ด์˜ค๊ณ โ€ฆ
์ด ์„ธ ๊ฐ€์ง€ ํฌ๋งท๋งŒ ์ œ๋Œ€๋กœ ๋‹ค๋ฃฐ ์ค„ ์•Œ์•„๋„ ๊ฐœ๋ฐœ ์ƒ์‚ฐ์„ฑ์ด ๋ˆˆ์— ๋„๊ฒŒ ๋‹ฌ๋ผ์ง„๋‹ค๋Š” ๊ฑฐ, ๊ฒฝํ—˜ํ•ด๋ณธ ์‚ฌ๋žŒ์€ ๋‹ค ์•Œ์ง€! ๐Ÿ˜„

๐Ÿ’ก ๋ฐ์ดํ„ฐ ํŒŒ์‹ฑ(Parsing)์ด๋ž€?
ํŠน์ • ํ˜•์‹์œผ๋กœ ์ธ์ฝ”๋”ฉ๋œ ๋ฌธ์ž์—ด์ด๋‚˜ ๋ฐ”์ดํŠธ ์ŠคํŠธ๋ฆผ์„ ๋ถ„์„ํ•ด์„œ, ํ”„๋กœ๊ทธ๋žจ์ด ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๊ตฌ์กฐํ™”๋œ ๋ฐ์ดํ„ฐ๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ๊ณผ์ •์ด์•ผ.
์‰ฝ๊ฒŒ ๋งํ•˜๋ฉด "์™ธ๊ตญ์–ด ํ…์ŠคํŠธ๋ฅผ ์šฐ๋ฆฌ๋ง๋กœ ๋ฒˆ์—ญํ•˜๋Š” ๊ฒƒ"๊ณผ ๋น„์Šทํ•œ ๊ฐœ๋…์ด์ง€!

C#์€ .NET ์ƒํƒœ๊ณ„ ๋•๋ถ„์— JSON, XML, CSV ํŒŒ์‹ฑ์„ ์œ„ํ•œ ๊ฐ•๋ ฅํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋“ค์ด ์ด๋ฏธ ์ž˜ ๊ฐ–์ถฐ์ ธ ์žˆ์–ด.
System.Text.Json, Newtonsoft.Json, System.Xml, LINQ to XML, CsvHelper ๊ฐ™์€ ๋„๊ตฌ๋“ค์ด ๋Œ€ํ‘œ์ ์ด์•ผ.
์ด ๊ธ€์—์„œ๋Š” ๊ฐ ํฌ๋งท๋ณ„๋กœ ํ•ต์‹ฌ ๊ธฐ๋ฒ•์„ ์‹ค์ „ ์ฝ”๋“œ์™€ ํ•จ๊ป˜ ํŒŒํ—ค์ณ๋ณผ ๊ฑฐ์•ผ. ์ค€๋น„๋์ง€? ๐Ÿ”ฅ

ํฌ๋งท์ฃผ์š” ์‚ฌ์šฉ์ฒ˜C# ์ฃผ์š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌํŠน์ง•
JSONREST API, ์„ค์ • ํŒŒ์ผ, NoSQLSystem.Text.Json, Newtonsoft.Json๊ฐ€๋ณ๊ณ  ์ฝ๊ธฐ ์‰ฌ์›€
XMLSOAP, ์„ค์ • ํŒŒ์ผ, ๋ฌธ์„œ ๊ตํ™˜System.Xml, XDocument, LINQ to XML์Šคํ‚ค๋งˆ ๊ฒ€์ฆ ๊ฐ€๋Šฅ, ๋„ค์ž„์ŠคํŽ˜์ด์Šค ์ง€์›
CSV์—‘์…€ ๋ฐ์ดํ„ฐ, ๋Œ€์šฉ๋Ÿ‰ ๋ฐฐ์น˜, ๋กœ๊ทธStreamReader, CsvHelper, TextFieldParser๋‹จ์ˆœํ•˜๊ณ  ํ˜ธํ™˜์„ฑ ์ตœ๊ณ 

๐Ÿ“ฆ JSON ํŒŒ์‹ฑ โ€” C#์˜ ๋‘ ๊ฐ€์ง€ ๊ฐ•์ž

JSON์€ ํ˜„๋Œ€ ์›น ๊ฐœ๋ฐœ์˜ ๊ตญ๋ฏผ ํฌ๋งท์ด๋ผ๊ณ  ํ•ด๋„ ๊ณผ์–ธ์ด ์•„๋‹ˆ์•ผ.
C#์—์„œ JSON์„ ๋‹ค๋ฃจ๋Š” ๋ฐฉ๋ฒ•์€ ํฌ๊ฒŒ ๋‘ ๊ฐ€์ง€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋กœ ๋‚˜๋‰˜์–ด:

1
System.Text.Json โ€” .NET Core 3.0๋ถ€ํ„ฐ ๊ธฐ๋ณธ ๋‚ด์žฅ, ๋น ๋ฅด๊ณ  ๊ฐ€๋ฒผ์›€
2
Newtonsoft.Json (Json.NET) โ€” ์˜ค๋žœ ์—ญ์‚ฌ, ํ’๋ถ€ํ•œ ๊ธฐ๋Šฅ, ์œ ์—ฐ์„ฑ ์ตœ๊ฐ•

๐Ÿ”น System.Text.Json โ€” ๊ธฐ๋ณธ ๋‚ด์žฅ์˜ ํž˜

.NET 5 ์ด์ƒ์ด๋ผ๋ฉด ๋ณ„๋„ ์„ค์น˜ ์—†์ด ๋ฐ”๋กœ ์“ธ ์ˆ˜ ์žˆ์–ด.
์„ฑ๋Šฅ์ด ๋›ฐ์–ด๋‚˜๊ณ  ๋ฉ”๋ชจ๋ฆฌ ํšจ์œจ๋„ ์ข‹์•„์„œ ๊ณ ์„ฑ๋Šฅ ์„œ๋ฒ„ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์— ๋”ฑ์ด์•ผ!

๐Ÿ“Œ ๊ธฐ๋ณธ ์—ญ์ง๋ ฌํ™” (JSON โ†’ C# ๊ฐ์ฒด)

using System.Text.Json;

// ๋ชจ๋ธ ํด๋ž˜์Šค ์ •์˜
public class User
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Email { get; set; }
    public bool IsActive { get; set; }
}

// JSON ๋ฌธ์ž์—ด โ†’ C# ๊ฐ์ฒด
string jsonString = @"{
    ""id"": 1,
    ""name"": ""ํ™๊ธธ๋™"",
    ""email"": ""hong@example.com"",
    ""isActive"": true
}";

User user = JsonSerializer.Deserialize<User>(jsonString);
Console.WriteLine($"์ด๋ฆ„: {user.Name}, ์ด๋ฉ”์ผ: {user.Email}");
// ์ถœ๋ ฅ: ์ด๋ฆ„: ํ™๊ธธ๋™, ์ด๋ฉ”์ผ: hong@example.com

๐Ÿ“Œ ์ง๋ ฌํ™” (C# ๊ฐ์ฒด โ†’ JSON)

// C# ๊ฐ์ฒด โ†’ JSON ๋ฌธ์ž์—ด
var newUser = new User
{
    Id = 2,
    Name = "๊น€์ฒ ์ˆ˜",
    Email = "kim@example.com",
    IsActive = false
};

// ๊ธฐ๋ณธ ์ง๋ ฌํ™”
string json = JsonSerializer.Serialize(newUser);

// ์˜ˆ์˜๊ฒŒ ๋“ค์—ฌ์“ฐ๊ธฐ ํฌํ•จ
var options = new JsonSerializerOptions
{
    WriteIndented = true,
    PropertyNamingPolicy = JsonNamingPolicy.CamelCase // ์นด๋ฉœ์ผ€์ด์Šค๋กœ ๋ณ€ํ™˜
};
string prettyJson = JsonSerializer.Serialize(newUser, options);
Console.WriteLine(prettyJson);

๐Ÿ“Œ ๋ฆฌ์ŠคํŠธ(๋ฐฐ์—ด) JSON ์ฒ˜๋ฆฌ

string jsonArray = @"[
    {""id"": 1, ""name"": ""ํ™๊ธธ๋™""},
    {""id"": 2, ""name"": ""๊น€์ฒ ์ˆ˜""},
    {""id"": 3, ""name"": ""์ด์˜ํฌ""}
]";

List<User> users = JsonSerializer.Deserialize<List<User>>(jsonArray);
foreach (var u in users)
{
    Console.WriteLine($"ID: {u.Id}, ์ด๋ฆ„: {u.Name}");
}

๐Ÿ“Œ JsonDocument๋กœ ๋™์  ํŒŒ์‹ฑ (๊ตฌ์กฐ๋ฅผ ๋ชจ๋ฅผ ๋•Œ)

string dynamicJson = @"{
    ""product"": ""๋…ธํŠธ๋ถ"",
    ""price"": 1500000,
    ""specs"": {
        ""cpu"": ""Intel i7"",
        ""ram"": ""16GB""
    }
}";

using JsonDocument doc = JsonDocument.Parse(dynamicJson);
JsonElement root = doc.RootElement;

string product = root.GetProperty("product").GetString();
int price = root.GetProperty("price").GetInt32();
string cpu = root.GetProperty("specs").GetProperty("cpu").GetString();

Console.WriteLine($"์ œํ’ˆ: {product}, ๊ฐ€๊ฒฉ: {price:N0}์›, CPU: {cpu}");
โœ… JsonDocument ์‚ฌ์šฉ ํŒ! JsonDocument๋Š” using ๋ธ”๋ก ์•ˆ์—์„œ ์‚ฌ์šฉํ•ด์•ผ ํ•ด. ๋‚ด๋ถ€์ ์œผ๋กœ ArrayPool์„ ์‚ฌ์šฉํ•˜๊ธฐ ๋•Œ๋ฌธ์— Dispose()๋ฅผ ๊ผญ ํ˜ธ์ถœํ•ด์ค˜์•ผ ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜๊ฐ€ ์—†์–ด!

๐Ÿ”น Newtonsoft.Json โ€” ์œ ์—ฐํ•จ์˜ ๋ํŒ์™•

NuGet์—์„œ Newtonsoft.Json ํŒจํ‚ค์ง€๋ฅผ ์„ค์น˜ํ•˜๋ฉด ๋ผ.
๋” ๋ณต์žกํ•œ ์‹œ๋‚˜๋ฆฌ์˜ค, ์ปค์Šคํ…€ ์ปจ๋ฒ„ํ„ฐ, ๋™์  ํƒ€์ž… ์ฒ˜๋ฆฌ์—์„œ ์—ฌ์ „ํžˆ ๊ฐ•๋ ฅํ•œ ์„ ํƒ์ง€์•ผ!

using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

// ๊ธฐ๋ณธ ์—ญ์ง๋ ฌํ™”
string json = @"{""name"": ""ํ™๊ธธ๋™"", ""age"": 30}";
User user = JsonConvert.DeserializeObject<User>(json);

// ๊ธฐ๋ณธ ์ง๋ ฌํ™”
string result = JsonConvert.SerializeObject(user, Formatting.Indented);

// JObject๋กœ ๋™์  ํŒŒ์‹ฑ (๊ตฌ์กฐ ๋ชจ๋ฅผ ๋•Œ ์ตœ๊ฐ•!)
JObject jObj = JObject.Parse(json);
string name = (string)jObj["name"];
int age = (int)jObj["age"];

// JArray๋กœ ๋ฐฐ์—ด ์ฒ˜๋ฆฌ
string jsonArr = @"[{""id"":1},{""id"":2}]";
JArray jArr = JArray.Parse(jsonArr);
foreach (JObject item in jArr)
{
    Console.WriteLine(item["id"]);
}

// ํŠน์ • ์†์„ฑ์— JsonProperty ์–ดํŠธ๋ฆฌ๋ทฐํŠธ ์ ์šฉ
public class Product
{
    [JsonProperty("product_name")]  // JSON ํ‚ค ์ด๋ฆ„ ๋งคํ•‘
    public string ProductName { get; set; }
    
    [JsonIgnore]  // ์ง๋ ฌํ™”์—์„œ ์ œ์™ธ
    public string InternalCode { get; set; }
    
    [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
    public string? Description { get; set; }
}
๐Ÿ†š System.Text.Json vs Newtonsoft.Json ์„ ํƒ ๊ธฐ์ค€ System.Text.Json ์ถ”์ฒœ: .NET 5+, ์„ฑ๋Šฅ ์ค‘์‹œ, ๋‹จ์ˆœํ•œ ์ง๋ ฌํ™”/์—ญ์ง๋ ฌํ™”
Newtonsoft.Json ์ถ”์ฒœ: ๋ณต์žกํ•œ ์ปค์Šคํ…€ ๋ณ€ํ™˜, ๋ ˆ๊ฑฐ์‹œ ์ฝ”๋“œ ํ˜ธํ™˜, ๋™์  JSON ์กฐ์ž‘์ด ๋งŽ์„ ๋•Œ

๐Ÿ“Œ ์ปค์Šคํ…€ JsonConverter ๋งŒ๋“ค๊ธฐ (System.Text.Json)

// DateTime์„ ํŠน์ • ํฌ๋งท์œผ๋กœ ์ง๋ ฌํ™”ํ•˜๋Š” ์ปค์Šคํ…€ ์ปจ๋ฒ„ํ„ฐ
public class KoreanDateConverter : JsonConverter<DateTime>
{
    public override DateTime Read(ref Utf8JsonReader reader, 
        Type typeToConvert, JsonSerializerOptions options)
    {
        return DateTime.Parse(reader.GetString()!);
    }

    public override void Write(Utf8JsonWriter writer, 
        DateTime value, JsonSerializerOptions options)
    {
        writer.WriteStringValue(value.ToString("yyyy๋…„ MM์›” dd์ผ"));
    }
}

// ์‚ฌ์šฉ ์˜ˆ์‹œ
var options = new JsonSerializerOptions();
options.Converters.Add(new KoreanDateConverter());

var data = new { Name = "์ด๋ฒคํŠธ", Date = DateTime.Now };
string json = JsonSerializer.Serialize(data, options);
// ์ถœ๋ ฅ: {"Name":"์ด๋ฒคํŠธ","Date":"2024๋…„ 01์›” 15์ผ"}
JSON ์ง๋ ฌํ™” / ์—ญ์ง๋ ฌํ™” ํ๋ฆ„ C# ๊ฐ์ฒด class User { Id = 1 Name = "ํ™๊ธธ๋™" Email = "..." } ๊ฐ•ํƒ€์ž…(Strongly Typed) ์ง๋ ฌํ™” Serialize() ์—ญ์ง๋ ฌํ™” Deserialize() JSON ๋ฌธ์ž์—ด { "id": 1, "name": "ํ™๊ธธ๋™", "email": "..." } ํ…์ŠคํŠธ ํฌ๋งท API / ํŒŒ์ผ REST API ์‘๋‹ต config.json ๋“ฑ JsonSerializer.Serialize() / Deserialize() โ€” System.Text.Json

๐Ÿท๏ธ XML ํŒŒ์‹ฑ โ€” ๋ ˆ๊ฑฐ์‹œ์˜ ์™•, ์—ฌ์ „ํžˆ ํ˜„์—ญ!

XML์€ "๊ตฌ์‹์ด๋‹ค"๋Š” ํŽธ๊ฒฌ์ด ์žˆ์ง€๋งŒ, ์‹ค์ œ ํ˜„์—…์—์„œ๋Š” ์—ฌ์ „ํžˆ ์—„์ฒญ๋‚˜๊ฒŒ ๋งŽ์ด ์“ฐ์—ฌ.
SOAP ์›น์„œ๋น„์Šค, ์„ค์ • ํŒŒ์ผ(App.config, Web.config), ์˜คํ”ผ์Šค ๋ฌธ์„œ(docx, xlsx ๋‚ด๋ถ€), RSS ํ”ผ๋“œ ๋“ฑโ€ฆ
C#์—์„œ XML์„ ๋‹ค๋ฃจ๋Š” ๋ฐฉ๋ฒ•๋„ ์—ฌ๋Ÿฌ ๊ฐ€์ง€๊ฐ€ ์žˆ๋Š”๋ฐ, ์ƒํ™ฉ์— ๋งž๊ฒŒ ๊ณจ๋ผ ์“ฐ๋Š” ๊ฒŒ ํฌ์ธํŠธ์•ผ! ๐ŸŽฏ

๋ฐฉ๋ฒ•ํŠน์ง•์ถ”์ฒœ ์ƒํ™ฉ
XmlDocumentDOM ๋ฐฉ์‹, ์ „ํ†ต์ , ์ง๊ด€์ ์†Œ~์ค‘๊ฐ„ ํฌ๊ธฐ XML, ์ˆ˜์ • ์ž‘์—…
XDocument (LINQ to XML)LINQ ์ฟผ๋ฆฌ ๊ฐ€๋Šฅ, ํ˜„๋Œ€์ ๋ณต์žกํ•œ ์ฟผ๋ฆฌ, ์ƒˆ ํ”„๋กœ์ ํŠธ
XmlReader์ŠคํŠธ๋ฆฌ๋ฐ ๋ฐฉ์‹, ๋ฉ”๋ชจ๋ฆฌ ํšจ์œจ๋Œ€์šฉ๋Ÿ‰ XML ์ฒ˜๋ฆฌ
XmlSerializer๊ฐ์ฒด ์ง๋ ฌํ™”/์—ญ์ง๋ ฌํ™”XML โ†” C# ๊ฐ์ฒด ๋ณ€ํ™˜

๐Ÿ”น XDocument (LINQ to XML) โ€” ๊ฐ€์žฅ ํ˜„๋Œ€์ ์ธ ๋ฐฉ๋ฒ•

LINQ to XML์€ C# 3.0๋ถ€ํ„ฐ ๋„์ž…๋œ ๋ฐฉ์‹์œผ๋กœ, LINQ ์ฟผ๋ฆฌ๋ฅผ XML์— ๊ทธ๋Œ€๋กœ ์ ์šฉํ•  ์ˆ˜ ์žˆ์–ด์„œ ์ •๋ง ํŽธ๋ฆฌํ•ด!

using System.Xml.Linq;

// XML ๋ฌธ์ž์—ด ํŒŒ์‹ฑ
string xmlString = @"
<์ง์›๋ชฉ๋ก>
    <์ง์› ๋ถ€์„œ=""๊ฐœ๋ฐœํŒ€"">
        <์ด๋ฆ„>ํ™๊ธธ๋™</์ด๋ฆ„>
        <๋‚˜์ด>30</๋‚˜์ด>
        <๊ธ‰์—ฌ>5000000</๊ธ‰์—ฌ>
    </์ง์›>
    <์ง์› ๋ถ€์„œ=""๋””์ž์ธํŒ€"">
        <์ด๋ฆ„>๊น€์ฒ ์ˆ˜</์ด๋ฆ„>
        <๋‚˜์ด>28</๋‚˜์ด>
        <๊ธ‰์—ฌ>4500000</๊ธ‰์—ฌ>
    </์ง์›>
    <์ง์› ๋ถ€์„œ=""๊ฐœ๋ฐœํŒ€"">
        <์ด๋ฆ„>์ด์˜ํฌ</์ด๋ฆ„>
        <๋‚˜์ด>32</๋‚˜์ด>
        <๊ธ‰์—ฌ>5500000</๊ธ‰์—ฌ>
    </์ง์›>
</์ง์›๋ชฉ๋ก>";

XDocument xDoc = XDocument.Parse(xmlString);

// LINQ๋กœ ๊ฐœ๋ฐœํŒ€ ์ง์›๋งŒ ํ•„ํ„ฐ๋ง
var ๊ฐœ๋ฐœํŒ€์ง์› = xDoc.Root
    .Elements("์ง์›")
    .Where(e => (string)e.Attribute("๋ถ€์„œ") == "๊ฐœ๋ฐœํŒ€")
    .Select(e => new
    {
        ์ด๋ฆ„ = (string)e.Element("์ด๋ฆ„"),
        ๋‚˜์ด = (int)e.Element("๋‚˜์ด"),
        ๊ธ‰์—ฌ = (int)e.Element("๊ธ‰์—ฌ")
    })
    .OrderByDescending(e => e.๊ธ‰์—ฌ);

foreach (var ์ง์› in ๊ฐœ๋ฐœํŒ€์ง์›)
{
    Console.WriteLine($"{์ง์›.์ด๋ฆ„} ({์ง์›.๋‚˜์ด}์„ธ) - ๊ธ‰์—ฌ: {์ง์›.๊ธ‰์—ฌ:N0}์›");
}

๐Ÿ“Œ XDocument๋กœ XML ์ƒ์„ฑํ•˜๊ธฐ

// C# ์ฝ”๋“œ๋กœ XML ์ง์ ‘ ์ƒ์„ฑ
XDocument newXml = new XDocument(
    new XDeclaration("1.0", "utf-8", "yes"),
    new XElement("์ œํ’ˆ๋ชฉ๋ก",
        new XElement("์ œํ’ˆ",
            new XAttribute("id", "001"),
            new XElement("์ด๋ฆ„", "๋…ธํŠธ๋ถ"),
            new XElement("๊ฐ€๊ฒฉ", 1500000),
            new XElement("์žฌ๊ณ ", 50)
        ),
        new XElement("์ œํ’ˆ",
            new XAttribute("id", "002"),
            new XElement("์ด๋ฆ„", "๋งˆ์šฐ์Šค"),
            new XElement("๊ฐ€๊ฒฉ", 35000),
            new XElement("์žฌ๊ณ ", 200)
        )
    )
);

// ํŒŒ์ผ๋กœ ์ €์žฅ
newXml.Save("products.xml");

// ๋ฌธ์ž์—ด๋กœ ๋ณ€ํ™˜
string xmlOutput = newXml.ToString();
Console.WriteLine(xmlOutput);

๐Ÿ”น XmlSerializer โ€” ๊ฐ์ฒด์™€ XML์„ ์ž๋™์œผ๋กœ ๋งคํ•‘

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

// ์ง๋ ฌํ™”ํ•  ํด๋ž˜์Šค ์ •์˜
[XmlRoot("์ง์›")]
public class Employee
{
    [XmlAttribute("๋ถ€์„œ")]
    public string Department { get; set; }
    
    [XmlElement("์ด๋ฆ„")]
    public string Name { get; set; }
    
    [XmlElement("๋‚˜์ด")]
    public int Age { get; set; }
    
    [XmlIgnore]  // XML์—์„œ ์ œ์™ธ
    public string InternalId { get; set; }
}

[XmlRoot("์ง์›๋ชฉ๋ก")]
public class EmployeeList
{
    [XmlElement("์ง์›")]
    public List<Employee> Employees { get; set; } = new();
}

// ์ง๋ ฌํ™” (C# ๊ฐ์ฒด โ†’ XML)
var empList = new EmployeeList
{
    Employees = new List<Employee>
    {
        new Employee { Department = "๊ฐœ๋ฐœํŒ€", Name = "ํ™๊ธธ๋™", Age = 30 },
        new Employee { Department = "๋””์ž์ธํŒ€", Name = "๊น€์ฒ ์ˆ˜", Age = 28 }
    }
};

var serializer = new XmlSerializer(typeof(EmployeeList));
using var writer = new StringWriter();
serializer.Serialize(writer, empList);
string xmlResult = writer.ToString();

// ์—ญ์ง๋ ฌํ™” (XML โ†’ C# ๊ฐ์ฒด)
using var reader = new StringReader(xmlResult);
var deserialized = (EmployeeList)serializer.Deserialize(reader);
Console.WriteLine($"์ง์› ์ˆ˜: {deserialized.Employees.Count}");

๐Ÿ”น XmlReader โ€” ๋Œ€์šฉ๋Ÿ‰ XML์˜ ๊ตฌ์›์ž

์ˆ˜๋ฐฑ MB์งœ๋ฆฌ XML ํŒŒ์ผ์„ ์ฒ˜๋ฆฌํ•ด์•ผ ํ•œ๋‹ค๋ฉด? XmlDocument๋‚˜ XDocument๋Š” ์ „์ฒด๋ฅผ ๋ฉ”๋ชจ๋ฆฌ์— ์˜ฌ๋ฆฌ๊ธฐ ๋•Œ๋ฌธ์— ์œ„ํ—˜ํ•ด.
XmlReader๋Š” ์ŠคํŠธ๋ฆฌ๋ฐ ๋ฐฉ์‹์œผ๋กœ ํ•œ ์ค„์”ฉ ์ฝ์–ด์„œ ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋Ÿ‰์„ ์ตœ์†Œํ™”ํ•ด!

using System.Xml;

// ์ŠคํŠธ๋ฆฌ๋ฐ ๋ฐฉ์‹์œผ๋กœ ๋Œ€์šฉ๋Ÿ‰ XML ์ฝ๊ธฐ
using XmlReader reader = XmlReader.Create("large_data.xml");

while (reader.Read())
{
    // ์‹œ์ž‘ ํƒœ๊ทธ์ผ ๋•Œ
    if (reader.NodeType == XmlNodeType.Element && reader.Name == "์ง์›")
    {
        string ๋ถ€์„œ = reader.GetAttribute("๋ถ€์„œ");
        
        // ํ•˜์œ„ ์š”์†Œ ์ฝ๊ธฐ
        using XmlReader subtree = reader.ReadSubtree();
        while (subtree.Read())
        {
            if (subtree.NodeType == XmlNodeType.Element)
            {
                switch (subtree.Name)
                {
                    case "์ด๋ฆ„":
                        Console.Write($"์ด๋ฆ„: {subtree.ReadElementContentAsString()}, ");
                        break;
                    case "๊ธ‰์—ฌ":
                        Console.WriteLine($"๊ธ‰์—ฌ: {subtree.ReadElementContentAsInt():N0}์›");
                        break;
                }
            }
        }
    }
}
โš ๏ธ XML ๋„ค์ž„์ŠคํŽ˜์ด์Šค ์ฃผ์˜! ์‹ค๋ฌด์—์„œ XML์„ ๋‹ค๋ฃจ๋‹ค ๋ณด๋ฉด ๋„ค์ž„์ŠคํŽ˜์ด์Šค ๋•Œ๋ฌธ์— ์š”์†Œ๋ฅผ ๋ชป ์ฐพ๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋งŽ์•„.
XNamespace ns = "http://example.com/schema";
xDoc.Root.Elements(ns + "์ง์›") ์ด๋Ÿฐ ์‹์œผ๋กœ ๋„ค์ž„์ŠคํŽ˜์ด์Šค๋ฅผ ๋ช…์‹œํ•ด์ค˜์•ผ ํ•ด!

๐Ÿ“Š CSV ํŒŒ์‹ฑ โ€” ๋‹จ์ˆœํ•˜์ง€๋งŒ ํ•จ์ •์ด ๋งŽ์•„!

CSV๋Š” ๊ฒ‰๋ณด๊ธฐ์—” ๋‹จ์ˆœํ•ด ๋ณด์ด์ง€๋งŒ, ์‹ค์ œ๋กœ ํŒŒ์‹ฑํ•˜๋‹ค ๋ณด๋ฉด ์ƒ๊ฐ์ง€๋„ ๋ชปํ•œ ํ•จ์ •๋“ค์ด ๋งŽ์•„.
์‰ผํ‘œ๊ฐ€ ํฌํ•จ๋œ ๋ฐ์ดํ„ฐ, ์ค„๋ฐ”๊ฟˆ์ด ํฌํ•จ๋œ ํ•„๋“œ, ์ธ์ฝ”๋”ฉ ๋ฌธ์ œ, ๋”ฐ์˜ดํ‘œ ์ฒ˜๋ฆฌโ€ฆ
์ด๋Ÿฐ ๊ฒƒ๋“ค์„ ์ œ๋Œ€๋กœ ์ฒ˜๋ฆฌํ•˜๋ ค๋ฉด ์ง์ ‘ ๊ตฌํ˜„๋ณด๋‹ค๋Š” CsvHelper ๊ฐ™์€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์“ฐ๋Š” ๊ฒŒ ํ›จ์”ฌ ์•ˆ์ „ํ•ด! ๐Ÿ˜…

๐Ÿ”น ๊ธฐ๋ณธ StreamReader๋กœ CSV ์ฝ๊ธฐ

๊ฐ„๋‹จํ•œ CSV๋ผ๋ฉด StreamReader๋กœ๋„ ์ถฉ๋ถ„ํ•ด. ํ•˜์ง€๋งŒ ๋ณต์žกํ•œ ์ผ€์ด์Šค๋Š” ์ฃผ์˜๊ฐ€ ํ•„์š”ํ•ด!

using System.IO;

// ๊ธฐ๋ณธ CSV ์ฝ๊ธฐ
string csvContent = @"์ด๋ฆ„,๋‚˜์ด,์ด๋ฉ”์ผ,๋„์‹œ
ํ™๊ธธ๋™,30,hong@example.com,์„œ์šธ
๊น€์ฒ ์ˆ˜,28,kim@example.com,๋ถ€์‚ฐ
์ด์˜ํฌ,32,lee@example.com,๋Œ€๊ตฌ";

// ๋ฐฉ๋ฒ• 1: ๋ฌธ์ž์—ด์—์„œ ์ง์ ‘ ํŒŒ์‹ฑ
var lines = csvContent.Split('\n');
string[] headers = lines[0].Split(',');

for (int i = 1; i < lines.Length; i++)
{
    if (string.IsNullOrWhiteSpace(lines[i])) continue;
    
    string[] values = lines[i].Split(',');
    var record = new Dictionary<string, string>();
    
    for (int j = 0; j < headers.Length; j++)
    {
        record[headers[j].Trim()] = values[j].Trim();
    }
    
    Console.WriteLine($"์ด๋ฆ„: {record["์ด๋ฆ„"]}, ๋„์‹œ: {record["๋„์‹œ"]}");
}

// ๋ฐฉ๋ฒ• 2: ํŒŒ์ผ์—์„œ ์ฝ๊ธฐ
using var fileReader = new StreamReader("data.csv", System.Text.Encoding.UTF8);
string? line;
bool isFirstLine = true;

while ((line = fileReader.ReadLine()) != null)
{
    if (isFirstLine) { isFirstLine = false; continue; } // ํ—ค๋” ์Šคํ‚ต
    
    string[] fields = line.Split(',');
    Console.WriteLine(string.Join(" | ", fields));
}
โš ๏ธ ๊ธฐ๋ณธ Split(',') ๋ฐฉ์‹์˜ ํ•œ๊ณ„! "ํ™๊ธธ๋™, ๊ฐœ๋ฐœ์ž","์„œ์šธ, ๊ฐ•๋‚จ๊ตฌ",30 ๊ฐ™์ด ์‰ผํ‘œ๊ฐ€ ํฌํ•จ๋œ ํ•„๋“œ๋Š” Split(',')์œผ๋กœ ์ œ๋Œ€๋กœ ํŒŒ์‹ฑ์ด ์•ˆ ๋ผ.
์ด๋Ÿฐ ๊ฒฝ์šฐ์—” CsvHelper๋ฅผ ์“ฐ๋Š” ๊ฒŒ ์ •๋‹ต์ด์•ผ!

๐Ÿ”น CsvHelper โ€” CSV ํŒŒ์‹ฑ์˜ ๋ํŒ์™•

NuGet์—์„œ CsvHelper ํŒจํ‚ค์ง€๋ฅผ ์„ค์น˜ํ•˜๋ฉด ๋ผ.
์‰ผํ‘œ ํฌํ•จ, ์ค„๋ฐ”๊ฟˆ ํฌํ•จ, ๋”ฐ์˜ดํ‘œ ์ฒ˜๋ฆฌ ๋“ฑ ๋ชจ๋“  ์—ฃ์ง€ ์ผ€์ด์Šค๋ฅผ ์ž๋™์œผ๋กœ ์ฒ˜๋ฆฌํ•ด์ค˜!

using CsvHelper;
using CsvHelper.Configuration;
using System.Globalization;

// ๋ชจ๋ธ ํด๋ž˜์Šค
public class Person
{
    public string ์ด๋ฆ„ { get; set; }
    public int ๋‚˜์ด { get; set; }
    public string ์ด๋ฉ”์ผ { get; set; }
    public string ๋„์‹œ { get; set; }
}

// CSV ํŒŒ์ผ ์ฝ๊ธฐ โ†’ ๊ฐ์ฒด ๋ฆฌ์ŠคํŠธ
var config = new CsvConfiguration(CultureInfo.InvariantCulture)
{
    HasHeaderRecord = true,
    Encoding = System.Text.Encoding.UTF8,
    MissingFieldFound = null // ๋ˆ„๋ฝ ํ•„๋“œ ๋ฌด์‹œ
};

using var reader = new StreamReader("people.csv");
using var csv = new CsvReader(reader, config);

List<Person> people = csv.GetRecords<Person>().ToList();

foreach (var person in people)
{
    Console.WriteLine($"{person.์ด๋ฆ„} ({person.๋‚˜์ด}์„ธ) - {person.๋„์‹œ}");
}

๐Ÿ“Œ CsvHelper๋กœ CSV ์“ฐ๊ธฐ

// ๊ฐ์ฒด ๋ฆฌ์ŠคํŠธ โ†’ CSV ํŒŒ์ผ ์ €์žฅ
var data = new List<Person>
{
    new Person { ์ด๋ฆ„ = "ํ™๊ธธ๋™", ๋‚˜์ด = 30, ์ด๋ฉ”์ผ = "hong@example.com", ๋„์‹œ = "์„œ์šธ" },
    new Person { ์ด๋ฆ„ = "๊น€์ฒ ์ˆ˜", ๋‚˜์ด = 28, ์ด๋ฉ”์ผ = "kim@example.com", ๋„์‹œ = "๋ถ€์‚ฐ" }
};

using var writer = new StreamWriter("output.csv", false, System.Text.Encoding.UTF8);
using var csvWriter = new CsvWriter(writer, CultureInfo.InvariantCulture);

csvWriter.WriteRecords(data);
Console.WriteLine("CSV ํŒŒ์ผ ์ €์žฅ ์™„๋ฃŒ!");

๐Ÿ“Œ ClassMap์œผ๋กœ ์ปฌ๋Ÿผ ๋งคํ•‘ ์ปค์Šคํ„ฐ๋งˆ์ด์ง•

// CSV ์ปฌ๋Ÿผ๋ช…๊ณผ C# ์†์„ฑ๋ช…์ด ๋‹ค๋ฅผ ๋•Œ
public class PersonMap : ClassMap<Person>
{
    public PersonMap()
    {
        Map(m => m.์ด๋ฆ„).Name("Name");        // CSV์˜ "Name" โ†’ ์ด๋ฆ„
        Map(m => m.๋‚˜์ด).Name("Age");          // CSV์˜ "Age" โ†’ ๋‚˜์ด
        Map(m => m.์ด๋ฉ”์ผ).Name("Email");      // CSV์˜ "Email" โ†’ ์ด๋ฉ”์ผ
        Map(m => m.๋„์‹œ).Name("City");         // CSV์˜ "City" โ†’ ๋„์‹œ
    }
}

// ClassMap ๋“ฑ๋ก ํ›„ ์‚ฌ์šฉ
using var csv = new CsvReader(reader, config);
csv.Context.RegisterClassMap<PersonMap>();
var people = csv.GetRecords<Person>().ToList();

๐Ÿ”น TextFieldParser โ€” .NET ๋‚ด์žฅ CSV ํŒŒ์„œ

์™ธ๋ถ€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์—†์ด ์“ฐ๊ณ  ์‹ถ๋‹ค๋ฉด Microsoft.VisualBasic.FileIO.TextFieldParser๋„ ์ข‹์€ ์„ ํƒ์ด์•ผ!

using Microsoft.VisualBasic.FileIO;

using var parser = new TextFieldParser("data.csv");
parser.TextFieldType = FieldType.Delimited;
parser.SetDelimiters(",");
parser.HasFieldsEnclosedInQuotes = true; // ๋”ฐ์˜ดํ‘œ ์ฒ˜๋ฆฌ ์ž๋™ํ™”!

// ํ—ค๋” ์ฝ๊ธฐ
string[] headers = parser.ReadFields();

while (!parser.EndOfData)
{
    string[] fields = parser.ReadFields();
    
    for (int i = 0; i < headers.Length; i++)
    {
        Console.Write($"{headers[i]}: {fields[i]}  ");
    }
    Console.WriteLine();
}
CSV ์ฒ˜๋ฆฌ ๋ฐฉ๋ฒ• ์„ ํƒ ๊ฐ€์ด๋“œ CSV ํŒŒ์‹ฑ์ด ํ•„์š”ํ•ด! ์–ด๋–ค ๋ฐฉ๋ฒ•์„ ์“ธ๊นŒ? ๋‹จ์ˆœํ•œ CSV ์‰ผํ‘œ/๋”ฐ์˜ดํ‘œ ์—†์Œ โ†’ StreamReader Split(',') ์‚ฌ์šฉ ๋ณต์žกํ•œ CSV ์‰ผํ‘œ/์ค„๋ฐ”๊ฟˆ ํฌํ•จ โ†’ CsvHelper NuGet ํŒจํ‚ค์ง€ ์™ธ๋ถ€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ NO ๋‚ด์žฅ๋งŒ ์‚ฌ์šฉ โ†’ TextFieldParser VB.NET ๋‚ด์žฅ ์ƒํ™ฉ์— ๋งž๋Š” ๋„๊ตฌ ์„ ํƒ์ด ํ•ต์‹ฌ! ๋ณต์žกํ•œ CSV๋Š” ๋ฐ˜๋“œ์‹œ ์ „์šฉ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜์ž.

๐Ÿ”„ ํฌ๋งท ๊ฐ„ ๋ณ€ํ™˜ โ€” JSON โ†” XML โ†” CSV

์‹ค๋ฌด์—์„œ๋Š” ํ•œ ํฌ๋งท์„ ๋‹ค๋ฅธ ํฌ๋งท์œผ๋กœ ๋ณ€ํ™˜ํ•ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ์ •๋ง ๋งŽ์•„.
API์—์„œ JSON์œผ๋กœ ๋ฐ›์€ ๋ฐ์ดํ„ฐ๋ฅผ XML๋กœ ์ €์žฅํ•˜๊ฑฐ๋‚˜, CSV ๋ฐ์ดํ„ฐ๋ฅผ JSON API๋กœ ์ „์†กํ•˜๋Š” ์‹์ด์ง€.
์ด๋Ÿฐ ๋ณ€ํ™˜ ์ž‘์—…์„ ๊น”๋”ํ•˜๊ฒŒ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์•Œ์•„๋ณด์ž! ๐Ÿ”„

๐Ÿ”น JSON โ†’ XML ๋ณ€ํ™˜

using System.Xml.Linq;
using System.Text.Json;

// ๋ฐฉ๋ฒ• 1: Newtonsoft.Json ํ™œ์šฉ (๊ฐ€์žฅ ๊ฐ„ํŽธ!)
// NuGet: Newtonsoft.Json
using Newtonsoft.Json;

string json = @"{
    ""์ง์›๋ชฉ๋ก"": {
        ""์ง์›"": [
            {""์ด๋ฆ„"": ""ํ™๊ธธ๋™"", ""๋‚˜์ด"": 30},
            {""์ด๋ฆ„"": ""๊น€์ฒ ์ˆ˜"", ""๋‚˜์ด"": 28}
        ]
    }
}";

// JSON โ†’ XmlDocument ๋ณ€ํ™˜ (Newtonsoft)
System.Xml.XmlDocument xmlDoc = JsonConvert.DeserializeXmlNode(json, "๋ฃจํŠธ");
string xmlString = xmlDoc.OuterXml;
Console.WriteLine(xmlString);

// ๋ฐฉ๋ฒ• 2: ์ˆ˜๋™ ๋ณ€ํ™˜ (System.Text.Json + LINQ to XML)
using JsonDocument doc = JsonDocument.Parse(json);
XElement root = ConvertJsonToXml(doc.RootElement, "๋ฃจํŠธ");

XElement ConvertJsonToXml(JsonElement element, string name)
{
    var xElement = new XElement(name);
    
    switch (element.ValueKind)
    {
        case JsonValueKind.Object:
            foreach (var prop in element.EnumerateObject())
                xElement.Add(ConvertJsonToXml(prop.Value, prop.Name));
            break;
        case JsonValueKind.Array:
            foreach (var item in element.EnumerateArray())
                xElement.Add(ConvertJsonToXml(item, "ํ•ญ๋ชฉ"));
            break;
        default:
            xElement.Value = element.ToString();
            break;
    }
    return xElement;
}

๐Ÿ”น XML โ†’ JSON ๋ณ€ํ™˜

// Newtonsoft.Json์œผ๋กœ XML โ†’ JSON (์ดˆ๊ฐ„๋‹จ!)
using Newtonsoft.Json;

string xmlInput = @"
<์ง์›๋ชฉ๋ก>
    <์ง์›>
        <์ด๋ฆ„>ํ™๊ธธ๋™</์ด๋ฆ„>
        <๋‚˜์ด>30</๋‚˜์ด>
    </์ง์›>
</์ง์›๋ชฉ๋ก>";

var xmlDoc = new System.Xml.XmlDocument();
xmlDoc.LoadXml(xmlInput);

string jsonResult = JsonConvert.SerializeXmlNode(xmlDoc, Formatting.Indented);
Console.WriteLine(jsonResult);

// ์ˆ˜๋™ ๋ณ€ํ™˜ (LINQ to XML + System.Text.Json)
XDocument xDoc = XDocument.Parse(xmlInput);

var employees = xDoc.Root
    .Elements("์ง์›")
    .Select(e => new
    {
        ์ด๋ฆ„ = (string)e.Element("์ด๋ฆ„"),
        ๋‚˜์ด = (int)e.Element("๋‚˜์ด")
    })
    .ToList();

string json = JsonSerializer.Serialize(new { ์ง์›๋ชฉ๋ก = employees }, 
    new JsonSerializerOptions { WriteIndented = true });
Console.WriteLine(json);

๐Ÿ”น CSV โ†’ JSON ๋ณ€ํ™˜

using CsvHelper;
using System.Text.Json;
using System.Globalization;

// CSV ํŒŒ์ผ โ†’ JSON ๋ณ€ํ™˜
public static string CsvToJson(string csvFilePath)
{
    using var reader = new StreamReader(csvFilePath, System.Text.Encoding.UTF8);
    using var csv = new CsvReader(reader, CultureInfo.InvariantCulture);
    
    // ๋™์ ์œผ๋กœ ๋ ˆ์ฝ”๋“œ ์ฝ๊ธฐ
    var records = csv.GetRecords<dynamic>().ToList();
    
    return JsonSerializer.Serialize(records, new JsonSerializerOptions 
    { 
        WriteIndented = true 
    });
}

// ๋˜๋Š” Dictionary๋กœ ๋ณ€ํ™˜
public static string CsvToJsonManual(string csvContent)
{
    var lines = csvContent.Trim().Split('\n');
    var headers = lines[0].Split(',').Select(h => h.Trim()).ToArray();
    
    var records = new List<Dictionary<string, string>>();
    
    for (int i = 1; i < lines.Length; i++)
    {
        var values = lines[i].Split(',');
        var record = new Dictionary<string, string>();
        
        for (int j = 0; j < headers.Length && j < values.Length; j++)
        {
            record[headers[j]] = values[j].Trim();
        }
        records.Add(record);
    }
    
    return JsonSerializer.Serialize(records, new JsonSerializerOptions 
    { 
        WriteIndented = true,
        Encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping
    });
}

๐Ÿ”น JSON โ†’ CSV ๋ณ€ํ™˜

using System.Text.Json;
using CsvHelper;

// JSON ๋ฐฐ์—ด โ†’ CSV ํŒŒ์ผ
public static void JsonToCsv<T>(string jsonString, string outputPath)
{
    var items = JsonSerializer.Deserialize<List<T>>(jsonString);
    
    using var writer = new StreamWriter(outputPath, false, System.Text.Encoding.UTF8);
    using var csv = new CsvWriter(writer, System.Globalization.CultureInfo.InvariantCulture);
    
    csv.WriteRecords(items);
}

// ์‚ฌ์šฉ ์˜ˆ์‹œ
string json = @"[
    {""์ด๋ฆ„"": ""ํ™๊ธธ๋™"", ""๋‚˜์ด"": 30, ""๋„์‹œ"": ""์„œ์šธ""},
    {""์ด๋ฆ„"": ""๊น€์ฒ ์ˆ˜"", ""๋‚˜์ด"": 28, ""๋„์‹œ"": ""๋ถ€์‚ฐ""}
]";

JsonToCsv<Person>(json, "output.csv");
Console.WriteLine("JSON โ†’ CSV ๋ณ€ํ™˜ ์™„๋ฃŒ!");

โšก ๊ณ ๊ธ‰ ๊ธฐ๋ฒ• โ€” ์‹ค๋ฌด์—์„œ ๋ฐ”๋กœ ์“ฐ๋Š” ํ…Œํฌ๋‹‰

๐Ÿ”น ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ (Async/Await)

ํŒŒ์ผ I/O๋‚˜ HTTP ์š”์ฒญ์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ํŒŒ์‹ฑํ•  ๋•Œ๋Š” ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ๊ฐ€ ํ•„์ˆ˜์•ผ.
ํŠนํžˆ ๋Œ€์šฉ๋Ÿ‰ ๋ฐ์ดํ„ฐ๋ฅผ ๋‹ค๋ฃฐ ๋•Œ UI ์Šค๋ ˆ๋“œ๋ฅผ ๋ธ”๋กœํ‚นํ•˜์ง€ ์•Š์œผ๋ ค๋ฉด ๊ผญ ์•Œ์•„์•ผ ํ•ด!

using System.Net.Http;
using System.Text.Json;

// HTTP API์—์„œ JSON ๋น„๋™๊ธฐ ํŒŒ์‹ฑ
public class ApiService
{
    private readonly HttpClient _httpClient;
    
    public ApiService(HttpClient httpClient)
    {
        _httpClient = httpClient;
    }
    
    public async Task<List<User>> GetUsersAsync(string apiUrl)
    {
        // HTTP GET ์š”์ฒญ
        HttpResponseMessage response = await _httpClient.GetAsync(apiUrl);
        response.EnsureSuccessStatusCode();
        
        // ์ŠคํŠธ๋ฆผ์œผ๋กœ ์ง์ ‘ ์—ญ์ง๋ ฌํ™” (๋ฉ”๋ชจ๋ฆฌ ํšจ์œจ์ !)
        await using Stream stream = await response.Content.ReadAsStreamAsync();
        
        var options = new JsonSerializerOptions
        {
            PropertyNameCaseInsensitive = true // ๋Œ€์†Œ๋ฌธ์ž ๋ฌด์‹œ
        };
        
        return await JsonSerializer.DeserializeAsync<List<User>>(stream, options)
               ?? new List<User>();
    }
    
    // ๋น„๋™๊ธฐ ํŒŒ์ผ ์ฝ๊ธฐ + JSON ํŒŒ์‹ฑ
    public async Task<T?> ReadJsonFileAsync<T>(string filePath)
    {
        await using FileStream fs = File.OpenRead(filePath);
        return await JsonSerializer.DeserializeAsync<T>(fs);
    }
}

๐Ÿ”น Source Generator ํ™œ์šฉ (AOT ์ตœ์ ํ™”)

.NET 6+์—์„œ๋Š” JsonSerializerContext๋ฅผ ์‚ฌ์šฉํ•œ ์†Œ์Šค ์ œ๋„ˆ๋ ˆ์ดํ„ฐ ๋ฐฉ์‹์œผ๋กœ
๋ฆฌํ”Œ๋ ‰์…˜ ์—†์ด JSON ์ง๋ ฌํ™”๋ฅผ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์–ด. AOT(Ahead-of-Time) ์ปดํŒŒ์ผ ํ™˜๊ฒฝ์—์„œ ํ•„์ˆ˜์•ผ!

using System.Text.Json.Serialization;

// JsonSerializerContext ์ •์˜
[JsonSerializable(typeof(User))]
[JsonSerializable(typeof(List<User>))]
[JsonSerializable(typeof(Product))]
public partial class AppJsonContext : JsonSerializerContext { }

// ์‚ฌ์šฉ ์˜ˆ์‹œ (๋ฆฌํ”Œ๋ ‰์…˜ ์—†์ด ๋น ๋ฅธ ์ง๋ ฌํ™”!)
var user = new User { Id = 1, Name = "ํ™๊ธธ๋™" };

// Source Generator ๋ฐฉ์‹
string json = JsonSerializer.Serialize(user, AppJsonContext.Default.User);
User? parsed = JsonSerializer.Deserialize(json, AppJsonContext.Default.User);

Console.WriteLine($"์ด๋ฆ„: {parsed?.Name}");

๐Ÿ”น ๋Œ€์šฉ๋Ÿ‰ ๋ฐ์ดํ„ฐ ์ŠคํŠธ๋ฆฌ๋ฐ ์ฒ˜๋ฆฌ

using System.Text.Json;

// Utf8JsonWriter๋กœ ๋Œ€์šฉ๋Ÿ‰ JSON ์ŠคํŠธ๋ฆฌ๋ฐ ์ƒ์„ฑ
public async Task WriteHugeJsonAsync(IEnumerable<User> users, Stream outputStream)
{
    await using var writer = new Utf8JsonWriter(outputStream, 
        new JsonWriterOptions { Indented = false });
    
    writer.WriteStartArray();
    
    foreach (var user in users)
    {
        writer.WriteStartObject();
        writer.WriteNumber("id", user.Id);
        writer.WriteString("name", user.Name);
        writer.WriteString("email", user.Email);
        writer.WriteBoolean("isActive", user.IsActive);
        writer.WriteEndObject();
        
        // ์ฃผ๊ธฐ์ ์œผ๋กœ ํ”Œ๋Ÿฌ์‹œ (๋ฉ”๋ชจ๋ฆฌ ๊ด€๋ฆฌ)
        if (writer.BytesPending > 65536) // 64KB๋งˆ๋‹ค
        {
            await writer.FlushAsync();
        }
    }
    
    writer.WriteEndArray();
    await writer.FlushAsync();
}

๐Ÿ”น ์—๋Ÿฌ ์ฒ˜๋ฆฌ ํŒจํ„ด

// ์•ˆ์ „ํ•œ JSON ํŒŒ์‹ฑ ํŒจํ„ด
public static T? SafeDeserialize<T>(string json, ILogger? logger = null)
{
    try
    {
        if (string.IsNullOrWhiteSpace(json))
        {
            logger?.LogWarning("๋นˆ JSON ๋ฌธ์ž์—ด์ด ์ž…๋ ฅ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.");
            return default;
        }
        
        return JsonSerializer.Deserialize<T>(json, new JsonSerializerOptions
        {
            PropertyNameCaseInsensitive = true,
            AllowTrailingCommas = true,  // ํ›„ํ–‰ ์‰ผํ‘œ ํ—ˆ์šฉ
            ReadCommentHandling = JsonCommentHandling.Skip  // ์ฃผ์„ ๋ฌด์‹œ
        });
    }
    catch (JsonException ex)
    {
        logger?.LogError(ex, "JSON ํŒŒ์‹ฑ ์‹คํŒจ: {Path}", ex.Path);
        return default;
    }
}

// Result ํŒจํ„ด์œผ๋กœ ์—๋Ÿฌ ์ฒ˜๋ฆฌ
public record ParseResult<T>(bool Success, T? Data, string? ErrorMessage);

public static ParseResult<T> TryParseJson<T>(string json)
{
    try
    {
        var data = JsonSerializer.Deserialize<T>(json);
        return new ParseResult<T>(true, data, null);
    }
    catch (JsonException ex)
    {
        return new ParseResult<T>(false, default, ex.Message);
    }
}

// ์‚ฌ์šฉ
var result = TryParseJson<User>(someJson);
if (result.Success)
    Console.WriteLine($"ํŒŒ์‹ฑ ์„ฑ๊ณต: {result.Data?.Name}");
else
    Console.WriteLine($"ํŒŒ์‹ฑ ์‹คํŒจ: {result.ErrorMessage}");

๐ŸŽ๏ธ ์„ฑ๋Šฅ ๋น„๊ต โ€” ์–ด๋–ค ๋ฐฉ๋ฒ•์ด ๊ฐ€์žฅ ๋น ๋ฅผ๊นŒ?

๊ฐ™์€ ์ž‘์—…์ด๋ผ๋„ ์–ด๋–ค ๋ฐฉ๋ฒ•์„ ์“ฐ๋А๋ƒ์— ๋”ฐ๋ผ ์„ฑ๋Šฅ ์ฐจ์ด๊ฐ€ ํฌ๊ฒŒ ๋‚  ์ˆ˜ ์žˆ์–ด.
BenchmarkDotNet ๊ธฐ๋ฐ˜ ์‹ค์ œ ๋ฒค์น˜๋งˆํฌ ๊ฒฐ๊ณผ๋ฅผ ์ฐธ๊ณ ํ•ด์„œ ์ƒํ™ฉ์— ๋งž๋Š” ์„ ํƒ์„ ํ•˜์ž!

๋ฐฉ๋ฒ•์ƒ๋Œ€ ์†๋„๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ์ถ”์ฒœ ์ƒํ™ฉ
System.Text.Json (Source Gen)๐Ÿš€ ๊ฐ€์žฅ ๋น ๋ฆ„์ตœ์†ŒAOT, ๊ณ ์„ฑ๋Šฅ ์„œ๋ฒ„
System.Text.Json (Reflection)โšก ๋น ๋ฆ„๋‚ฎ์Œ์ผ๋ฐ˜์ ์ธ .NET 5+ ์•ฑ
Newtonsoft.Json๐Ÿƒ ๋ณดํ†ต์ค‘๊ฐ„๋ณต์žกํ•œ ๋ณ€ํ™˜, ๋ ˆ๊ฑฐ์‹œ
XDocument (LINQ to XML)๐Ÿšถ ๋ณดํ†ต์ค‘๊ฐ„~๋†’์Œ์†Œ~์ค‘๊ฐ„ XML
XmlReader (์ŠคํŠธ๋ฆฌ๋ฐ)โšก ๋น ๋ฆ„์ตœ์†Œ๋Œ€์šฉ๋Ÿ‰ XML
CsvHelperโšก ๋น ๋ฆ„๋‚ฎ์Œ๋ณต์žกํ•œ CSV
StreamReader + Split๐Ÿš€ ๋น ๋ฆ„์ตœ์†Œ๋‹จ์ˆœํ•œ CSV
โœ… ์„ฑ๋Šฅ ์ตœ์ ํ™” ํ•ต์‹ฌ ํŒ! 1๏ธโƒฃ JsonSerializer ์˜ต์…˜ ์žฌ์‚ฌ์šฉ: JsonSerializerOptions๋Š” ์ƒ์„ฑ ๋น„์šฉ์ด ๋†’์œผ๋‹ˆ static์œผ๋กœ ํ•œ ๋ฒˆ๋งŒ ๋งŒ๋“ค์–ด ์žฌ์‚ฌ์šฉํ•ด!
2๏ธโƒฃ ์ŠคํŠธ๋ฆผ ์ง์ ‘ ์ฒ˜๋ฆฌ: ๋ฌธ์ž์—ด๋กœ ๋ณ€ํ™˜ํ•˜์ง€ ๋ง๊ณ  Stream์„ ์ง์ ‘ JsonSerializer์— ๋„˜๊ฒจ์ค˜.
3๏ธโƒฃ ๋Œ€์šฉ๋Ÿ‰ XML: XDocument ๋Œ€์‹  XmlReader๋ฅผ ์จ์„œ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์•„๊ปด!
4๏ธโƒฃ CSV ๋Œ€์šฉ๋Ÿ‰: CsvHelper์˜ GetRecords()๋Š” ์ง€์—ฐ ํ‰๊ฐ€(lazy evaluation)๋ฅผ ํ™œ์šฉํ•ด!
// โœ… ์ข‹์€ ์˜ˆ: JsonSerializerOptions๋ฅผ static์œผ๋กœ ์žฌ์‚ฌ์šฉ
public static class JsonHelper
{
    private static readonly JsonSerializerOptions _options = new()
    {
        PropertyNameCaseInsensitive = true,
        WriteIndented = false,
        DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull
    };
    
    public static T? Deserialize<T>(string json) 
        => JsonSerializer.Deserialize<T>(json, _options);
    
    public static string Serialize<T>(T obj) 
        => JsonSerializer.Serialize(obj, _options);
}

// โŒ ๋‚˜์œ ์˜ˆ: ๋งค๋ฒˆ ์ƒˆ ์˜ต์…˜ ๊ฐ์ฒด ์ƒ์„ฑ (์„ฑ๋Šฅ ์ €ํ•˜!)
public static T? BadDeserialize<T>(string json)
    => JsonSerializer.Deserialize<T>(json, new JsonSerializerOptions 
    { 
        PropertyNameCaseInsensitive = true  // ๋งค๋ฒˆ ์ƒˆ๋กœ ์ƒ์„ฑ = ๋А๋ฆผ!
    });

๐Ÿ› ๏ธ ์‹ค์ „ ์˜ˆ์ œ โ€” ์ข…ํ•ฉ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ ํŒŒ์ดํ”„๋ผ์ธ

์ง€๊ธˆ๊นŒ์ง€ ๋ฐฐ์šด ๋‚ด์šฉ์„ ์ข…ํ•ฉํ•ด์„œ ์‹ค์ œ ์—…๋ฌด์—์„œ ์“ธ ์ˆ˜ ์žˆ๋Š” ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ ํŒŒ์ดํ”„๋ผ์ธ์„ ๋งŒ๋“ค์–ด๋ณด์ž!
CSV ํŒŒ์ผ์„ ์ฝ์–ด์„œ ์ฒ˜๋ฆฌํ•˜๊ณ , JSON API๋กœ ์ „์†กํ•˜๊ณ , ๊ฒฐ๊ณผ๋ฅผ XML๋กœ ์ €์žฅํ•˜๋Š” ์‹œ๋‚˜๋ฆฌ์˜ค์•ผ. ๐ŸŽฏ

๐Ÿ“‹ ์‹œ๋‚˜๋ฆฌ์˜ค: ์ง์› ๋ฐ์ดํ„ฐ CSV ํŒŒ์ผ โ†’ ์ฒ˜๋ฆฌ โ†’ JSON API ์ „์†ก โ†’ XML ๊ฒฐ๊ณผ ์ €์žฅ
using System.Text.Json;
using System.Xml.Linq;
using CsvHelper;
using System.Globalization;
using System.Net.Http;

// ๋ฐ์ดํ„ฐ ๋ชจ๋ธ
public record Employee(
    int Id,
    string Name,
    string Department,
    decimal Salary,
    DateTime HireDate
);

public class DataPipeline
{
    private readonly HttpClient _httpClient;
    
    public DataPipeline(HttpClient httpClient)
    {
        _httpClient = httpClient;
    }
    
    // Step 1: CSV ์ฝ๊ธฐ
    public async Task<List<Employee>> ReadFromCsvAsync(string filePath)
    {
        using var reader = new StreamReader(filePath, System.Text.Encoding.UTF8);
        using var csv = new CsvReader(reader, CultureInfo.InvariantCulture);
        
        return await Task.Run(() => csv.GetRecords<Employee>().ToList());
    }
    
    // Step 2: ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ (์˜ˆ: ๊ธ‰์—ฌ 10% ์ธ์ƒ)
    public List<Employee> ProcessData(List<Employee> employees)
    {
        return employees
            .Where(e => e.Salary > 0)  // ์œ ํšจํ•œ ๋ฐ์ดํ„ฐ๋งŒ
            .Select(e => e with { Salary = e.Salary * 1.1m })  // 10% ์ธ์ƒ
            .OrderBy(e => e.Department)
            .ThenBy(e => e.Name)
            .ToList();
    }
    
    // Step 3: JSON API๋กœ ์ „์†ก
    public async Task<bool> SendToApiAsync(List<Employee> employees, string apiUrl)
    {
        var json = JsonSerializer.Serialize(employees, new JsonSerializerOptions
        {
            WriteIndented = false,
            PropertyNamingPolicy = JsonNamingPolicy.CamelCase
        });
        
        var content = new StringContent(json, System.Text.Encoding.UTF8, "application/json");
        
        try
        {
            var response = await _httpClient.PostAsync(apiUrl, content);
            return response.IsSuccessStatusCode;
        }
        catch (HttpRequestException ex)
        {
            Console.WriteLine($"API ์ „์†ก ์‹คํŒจ: {ex.Message}");
            return false;
        }
    }
    
    // Step 4: XML๋กœ ๊ฒฐ๊ณผ ์ €์žฅ
    public async Task SaveToXmlAsync(List<Employee> employees, string outputPath)
    {
        var xDoc = new XDocument(
            new XDeclaration("1.0", "utf-8", "yes"),
            new XElement("์ง์›๋ชฉ๋ก",
                new XAttribute("์ƒ์„ฑ์ผ์‹œ", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")),
                new XAttribute("์ด์ธ์›", employees.Count),
                employees.Select(e => new XElement("์ง์›",
                    new XAttribute("id", e.Id),
                    new XElement("์ด๋ฆ„", e.Name),
                    new XElement("๋ถ€์„œ", e.Department),
                    new XElement("๊ธ‰์—ฌ", e.Salary.ToString("N0")),
                    new XElement("์ž…์‚ฌ์ผ", e.HireDate.ToString("yyyy-MM-dd"))
                ))
            )
        );
        
        await Task.Run(() => xDoc.Save(outputPath));
        Console.WriteLine($"XML ์ €์žฅ ์™„๋ฃŒ: {outputPath}");
    }
    
    // ์ „์ฒด ํŒŒ์ดํ”„๋ผ์ธ ์‹คํ–‰
    public async Task RunPipelineAsync(string csvPath, string apiUrl, string xmlOutput)
    {
        Console.WriteLine("๐Ÿš€ ๋ฐ์ดํ„ฐ ํŒŒ์ดํ”„๋ผ์ธ ์‹œ์ž‘...");
        
        // 1. CSV ์ฝ๊ธฐ
        var rawData = await ReadFromCsvAsync(csvPath);
        Console.WriteLine($"โœ… CSV ์ฝ๊ธฐ ์™„๋ฃŒ: {rawData.Count}๊ฑด");
        
        // 2. ์ฒ˜๋ฆฌ
        var processed = ProcessData(rawData);
        Console.WriteLine($"โœ… ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ ์™„๋ฃŒ: {processed.Count}๊ฑด");
        
        // 3. API ์ „์†ก
        bool apiSuccess = await SendToApiAsync(processed, apiUrl);
        Console.WriteLine($"โœ… API ์ „์†ก: {(apiSuccess ? "์„ฑ๊ณต" : "์‹คํŒจ")}");
        
        // 4. XML ์ €์žฅ
        await SaveToXmlAsync(processed, xmlOutput);
        Console.WriteLine("๐ŸŽ‰ ํŒŒ์ดํ”„๋ผ์ธ ์™„๋ฃŒ!");
    }
}

// ์‹คํ–‰
var pipeline = new DataPipeline(new HttpClient());
await pipeline.RunPipelineAsync(
    csvPath: "employees.csv",
    apiUrl: "https://api.example.com/employees",
    xmlOutput: "result.xml"
);

๐Ÿ’ก ๋งˆ๋ฌด๋ฆฌ โ€” ์‹ค๋ฌด์—์„œ ๊ผญ ๊ธฐ์–ตํ•  ๊ฒƒ๋“ค

์—ฌ๊ธฐ๊นŒ์ง€ JSON, XML, CSV ํŒŒ์‹ฑ๊ณผ ๋ณ€ํ™˜์˜ ํ•ต์‹ฌ์„ ๋ชจ๋‘ ์‚ดํŽด๋ดค์–ด!
๋งˆ์ง€๋ง‰์œผ๋กœ ์‹ค๋ฌด์—์„œ ๊ผญ ๊ธฐ์–ตํ•ด์•ผ ํ•  ๋ฒ ์ŠคํŠธ ํ”„๋ž™ํ‹ฐ์Šค๋“ค์„ ์ •๋ฆฌํ•ด์ค„๊ฒŒ. ๐Ÿ“

โœ… ์ธ์ฝ”๋”ฉ ํ•ญ์ƒ ๋ช…์‹œ! ํŒŒ์ผ ์ฝ๊ธฐ/์“ฐ๊ธฐ ์‹œ Encoding.UTF8์„ ํ•ญ์ƒ ๋ช…์‹œํ•ด์ค˜.
ํŠนํžˆ ํ•œ๊ธ€ ๋ฐ์ดํ„ฐ๊ฐ€ ์žˆ์„ ๋•Œ ์ธ์ฝ”๋”ฉ์„ ๋น ๋œจ๋ฆฌ๋ฉด ๊นจ์ง ํ˜„์ƒ์ด ๋ฐœ์ƒํ•ด!
โœ… Null ์ฒ˜๋ฆฌ ์ฒ ์ €ํžˆ! JSON ์—ญ์ง๋ ฌํ™” ๊ฒฐ๊ณผ๋Š” ํ•ญ์ƒ null์ผ ์ˆ˜ ์žˆ์–ด. ?? throw new InvalidOperationException() ํŒจํ„ด์ด๋‚˜
nullable reference type์„ ํ™œ์šฉํ•ด์„œ null ์•ˆ์ „์„ฑ์„ ํ™•๋ณดํ•ด!
โœ… ๋Œ€์šฉ๋Ÿ‰ ๋ฐ์ดํ„ฐ๋Š” ์ŠคํŠธ๋ฆฌ๋ฐ! 10MB ์ด์ƒ์˜ JSON/XML ํŒŒ์ผ์€ ์ ˆ๋Œ€ ์ „์ฒด๋ฅผ ๋ฉ”๋ชจ๋ฆฌ์— ์˜ฌ๋ฆฌ์ง€ ๋งˆ.
JsonSerializer.DeserializeAsync(stream)์ด๋‚˜ XmlReader๋ฅผ ํ™œ์šฉํ•ด!
โš ๏ธ CSV์˜ ํ•จ์ • ์กฐ์‹ฌ! ์ง์ ‘ Split(',')์œผ๋กœ ํŒŒ์‹ฑํ•˜๋ฉด ์‰ผํ‘œ๊ฐ€ ํฌํ•จ๋œ ํ•„๋“œ์—์„œ ๋ฐ˜๋“œ์‹œ ๋ฌธ์ œ๊ฐ€ ์ƒ๊ฒจ.
์‹ค๋ฌด ๋ฐ์ดํ„ฐ๋Š” ํ•ญ์ƒ CsvHelper๋‚˜ TextFieldParser๋ฅผ ์จ!
๐ŸŽฏ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์„ ํƒ ์ตœ์ข… ์ •๋ฆฌ JSON: .NET 5+ โ†’ System.Text.Json / ๋ณต์žกํ•œ ๋ณ€ํ™˜ โ†’ Newtonsoft.Json
XML: ์ƒˆ ํ”„๋กœ์ ํŠธ โ†’ XDocument + LINQ / ๋Œ€์šฉ๋Ÿ‰ โ†’ XmlReader / ๊ฐ์ฒด ๋งคํ•‘ โ†’ XmlSerializer
CSV: ๋‹จ์ˆœ โ†’ StreamReader + Split / ๋ณต์žก โ†’ CsvHelper / ๋‚ด์žฅ๋งŒ โ†’ TextFieldParser

๋ฐ์ดํ„ฐ ํŒŒ์‹ฑ ์‹ค๋ ฅ์€ C# ๊ฐœ๋ฐœ์ž๋กœ์„œ์˜ ๊ธฐ๋ณธ๊ธฐ ์ค‘์—์„œ๋„ ํ•ต์‹ฌ์ด์•ผ.
์ด ๊ธ€์—์„œ ๋‹ค๋ฃฌ ๊ธฐ๋ฒ•๋“ค์„ ์‹ค์ œ ํ”„๋กœ์ ํŠธ์— ์ ์šฉํ•ด๋ณด๋ฉด์„œ ์†์— ์ตํžˆ๋Š” ๊ฒŒ ๊ฐ€์žฅ ์ค‘์š”ํ•ด!

ํ˜น์‹œ C# ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ ๊ด€๋ จ ํ”„๋กœ์ ํŠธ๋ฅผ ์ง„ํ–‰ํ•˜๋‹ค๊ฐ€ ๋ง‰ํžˆ๋Š” ๋ถ€๋ถ„์ด ์žˆ๋‹ค๋ฉด,
์žฌ๋Šฅ๋„ท์—์„œ C# ์ „๋ฌธ ๊ฐœ๋ฐœ์ž์˜ ๋„์›€์„ ๋ฐ›์•„๋ณด๋Š” ๊ฒƒ๋„ ์ข‹์€ ๋ฐฉ๋ฒ•์ด์•ผ.
๋‹ค์–‘ํ•œ ์‹ค๋ ฅ์ž๋“ค์ด ๋ฐ์ดํ„ฐ ํŒŒ์‹ฑ๋ถ€ํ„ฐ ์•„ํ‚คํ…์ฒ˜ ์„ค๊ณ„๊นŒ์ง€ ๋„์›€์„ ์ค„ ์ˆ˜ ์žˆ๊ฑฐ๋“ ! ๐Ÿ˜Š

C# ๋ฐ์ดํ„ฐ ํŒŒ์‹ฑ ํ•ต์‹ฌ ์š”์•ฝ JSON System.Text.Json ยท ๊ธฐ๋ณธ ๋‚ด์žฅ (.NET 5+) ยท ๊ณ ์„ฑ๋Šฅ, ๋ฉ”๋ชจ๋ฆฌ ํšจ์œจ ยท Source Generator ์ง€์› Newtonsoft.Json ยท ํ’๋ถ€ํ•œ ๊ธฐ๋Šฅ ยท JObject ๋™์  ํŒŒ์‹ฑ ยท ์ปค์Šคํ…€ ์ปจ๋ฒ„ํ„ฐ ยท XML ๋ณ€ํ™˜ ๋‚ด์žฅ JsonSerializer.Serialize() JsonSerializer.Deserialize() XML XDocument (LINQ to XML) ยท LINQ ์ฟผ๋ฆฌ ๊ฐ€๋Šฅ ยท ํ˜„๋Œ€์ , ์ง๊ด€์  ยท ์†Œ~์ค‘๊ฐ„ XML ์ ํ•ฉ XmlReader / XmlSerializer ยท ๋Œ€์šฉ๋Ÿ‰ ์ŠคํŠธ๋ฆฌ๋ฐ ยท ๊ฐ์ฒด ์ž๋™ ๋งคํ•‘ ยท ์–ดํŠธ๋ฆฌ๋ทฐํŠธ ๊ธฐ๋ฐ˜ ยท ์Šคํ‚ค๋งˆ ๊ฒ€์ฆ ๊ฐ€๋Šฅ XDocument.Parse() XmlSerializer.Serialize() CSV CsvHelper (NuGet) ยท ๋ณต์žกํ•œ CSV ์ฒ˜๋ฆฌ ยท ๋”ฐ์˜ดํ‘œ/์ค„๋ฐ”๊ฟˆ ์ž๋™์ฒ˜๋ฆฌ ยท ClassMap ์ปค์Šคํ„ฐ๋งˆ์ด์ง• StreamReader / TextFieldParser ยท ๋‹จ์ˆœ CSV ์ฒ˜๋ฆฌ ยท ์™ธ๋ถ€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๋ถˆํ•„์š” ยท ์ธ์ฝ”๋”ฉ ๋ช…์‹œ ํ•„์ˆ˜ ยท ๋Œ€์šฉ๋Ÿ‰ ์ง€์—ฐ ํ‰๊ฐ€ csv.GetRecords<T>() csv.WriteRecords(data) ์ƒํ™ฉ์— ๋งž๋Š” ๋„๊ตฌ ์„ ํƒ + ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ + ์—๋Ÿฌ ํ•ธ๋“ค๋ง = ์™„๋ฒฝํ•œ ๋ฐ์ดํ„ฐ ํŒŒ์‹ฑ! ๐ŸŽฏ
๋Œ“๊ธ€ ์ž‘์„ฑ

์ด ๊ธ€์— ๋Œ€ํ•œ ์—ฌ๋Ÿฌ๋ถ„์˜ ์ƒ๊ฐ์„ ๋“ค๋ ค์ฃผ์„ธ์š”

๋Œ“๊ธ€ 0
๋Œ“๊ธ€์„ ๋ถˆ๋Ÿฌ์˜ค๋Š” ์ค‘์ž…๋‹ˆ๋‹ค.

์•„์ง ๋Œ“๊ธ€์ด ์—†์Šต๋‹ˆ๋‹ค.