“복사”라고 하면 보통 “완전히 똑같은 걸 하나 더 만든다”를 떠올립니다.
하지만 C#에서 복사는 생각보다 단순하지 않습니다. 왜냐하면 객체 안에 또 다른 객체(참조형)가 들어있을 수 있기 때문입니다.
그래서 복사에는 크게 두 가지가 있습니다.

값 형식(int, float 등)은 복사하면 그냥 값이 복사되니 직관적입니다.
문제는 참조 형식(class, 배열, List 등)입니다.
참조 형식의 객체는 “겉(객체)” 안에 필드들이 있고, 그 필드 중 일부가 또 다른 객체를 가리킬 수 있습니다.
즉, 이런 구조가 가능합니다.
이때 “Player를 복사했다”는 말이 Inventory도 새로 복사했다는 뜻인지가 애매해집니다.
이 애매함을 정리한 개념이 얕은 복사/깊은 복사입니다.
class Player
{
public int Level;
public int[] Inventory; // 참조형(배열)
}
var p1 = new Player { Level = 1, Inventory = new[] { 10, 20 } };
// 얕은 복사(의미): Player는 새로 만들었지만 Inventory는 공유
var p2 = new Player { Level = p1.Level, Inventory = p1.Inventory };
p2.Level = 99; // p2의 값 필드만 변경
p2.Inventory[0] = 777; // 공유된 배열을 변경
Console.WriteLine(p1.Level); // 1 (영향 없음)
Console.WriteLine(p1.Inventory[0]); // 777 (영향 있음)
왜 이런 일이 생길까?
Inventory는 배열이고(참조형), p1.Inventory를 그대로 넣으면 p2.Inventory도 같은 배열을 가리키게 됩니다.
var p3 = new Player
{
Level = p1.Level,
Inventory = (int[])p1.Inventory.Clone() // 배열 자체를 새로 복사
};
p3.Inventory[0] = 123;
Console.WriteLine(p1.Inventory[0]); // 777 (p3와 무관)
Console.WriteLine(p3.Inventory[0]); // 123
여기서는 Inventory 배열도 새로 만들었기 때문에, p3는 p1과 독립적입니다.
배열이 int[]처럼 값형을 담으면 Clone()이 꽤 안전합니다.
그런데 배열이 Item[]처럼 참조형 객체를 담는 배열이면 얘기가 달라집니다.
class Item { public string Name; }
class Bag { public Item[] Items; }
var b1 = new Bag { Items = new[] { new Item { Name = "Potion" } } };
var b2 = new Bag { Items = (Item[])b1.Items.Clone() }; // 배열만 새로, Item은 공유
b2.Items[0].Name = "Elixir";
Console.WriteLine(b1.Items[0].Name); // Elixir (같이 바뀜)
여기서 Clone()은 “배열”은 새로 만들지만, 배열 안의 Item 객체까지 새로 만들지는 않습니다.
그래서 b1.Items[0]과 b2.Items[0]이 같은 Item 객체를 가리키는 공유 상태가 됩니다.
배열만 복사하지 말고, 각 Item도 새로 만들어 담아야 합니다.
var b3 = new Bag
{
Items = b1.Items.Select(item => new Item { Name = item.Name }).ToArray()
};
b3.Items[0].Name = "Elixir";
Console.WriteLine(b1.Items[0].Name); // Potion ← 안 바뀜
Console.WriteLine(b3.Items[0].Name); // Elixir
핵심은 이 한 줄입니다.
만약 Items가 int[] 같은 값형 배열이라면, Clone()만으로도 사실상 깊은 복사처럼 동작합니다.
왜냐하면 요소 자체가 값이라 “참조 공유”라는 문제가 없기 때문입니다.
얕은 복사가 “나쁘다”가 아니라, 공유가 의도와 맞는지가 중요합니다.
| [C# 이해하기] 값형식(Value Type)과 참조 형식(Reference Type) (0) | 2026.01.03 |
|---|---|
| 컴퓨터 구조 (0) | 2025.12.09 |
| [C언어] 데이터 입력 (0) | 2025.12.09 |
| [C언어] 문자열 (0) | 2025.11.30 |
| [C언어] 정수 자료형과 실수 자료형 (0) | 2025.11.29 |