"깊이"가 다른 게임개발자 허민영

유저에서 게임까지, 철학에서 코딩까지, 본질을 보는 게임개발

소프트웨어 공학/코딩

C# 얕은 복사(Shallow Copy)와 깊은 복사(Deep Copy) 완벽 이해하기!

허민영 2025. 2. 3. 20:52
using System;
using System.Collections.Generic;

class Person
{
    public string Name;
    public List<string> Hobbies;

    // 깊은 복사 메서드
    public Person DeepCopy()
    {
        Person copy = new Person();
        copy.Name = this.Name;
        copy.Hobbies = new List<string>(this.Hobbies); // 새로운 리스트 생성 (깊은 복사)
        return copy;
    }
}

class Program
{
    static void Main()
    {
        // 원본 객체
        Person person1 = new Person();
        person1.Name = "홍길동";
        person1.Hobbies = new List<string> { "독서", "게임" };

        // 깊은 복사
        Person person2 = person1.DeepCopy();

        // 복사본의 취미 목록 수정
        person2.Hobbies.Add("축구");

        // 결과 출력
        Console.WriteLine($"person1 Hobbies: {string.Join(", ", person1.Hobbies)}");
        Console.WriteLine($"person2 Hobbies: {string.Join(", ", person2.Hobbies)}");
    }
}

C#에서 객체를 복사하는 방법에는 크게 두 가지가 있습니다.

  • 얕은 복사(Shallow Copy): 객체의 참조(주소)만 복사
  • 깊은 복사(Deep Copy): 객체의 내부 값까지 완전히 복사

📌 1. 얕은 복사(Shallow Copy)

얕은 복사객체의 "참조(주소)"만 복사하는 방식입니다.
즉, 같은 데이터를 가리키는 두 개의 참조가 생성됩니다.

💡 얕은 복사의 특징

✔️ 복사된 객체와 원본 객체는 같은 메모리 주소를 공유
✔️ 하나를 수정하면 다른 객체에도 영향을 줌

📝 예제: 얕은 복사 (Shallow Copy)

using System;

class Person
{
    public string Name;
    public int Age;
}

class Program
{
    static void Main()
    {
        // 원본 객체 생성
        Person person1 = new Person();
        person1.Name = "홍길동";
        person1.Age = 25;

        // 얕은 복사 (참조만 복사됨)
        Person person2 = person1;

        // 복사한 객체의 값을 변경
        person2.Name = "이순신";
        person2.Age = 30;

        // 결과 출력
        Console.WriteLine($"person1: {person1.Name}, {person1.Age}");
        Console.WriteLine($"person2: {person2.Name}, {person2.Age}");
    }
}

🛠 실행 결과

person1: 이순신, 30
person2: 이순신, 30

❗️ 왜 이런 결과가 나올까?

  • person2 = person1;
    → person2는 person1과 같은 객체의 주소를 가리킵니다.
  • 따라서 person2에서 Name과 Age를 변경하면
    원본 객체(person1)도 변경된 것처럼 보임

✔️ 즉, 얕은 복사는 객체의 "값"을 복사하는 것이 아니라 "주소"를 복사한 것입니다.


📌 2. 깊은 복사(Deep Copy)

깊은 복사는 객체를 복사할 때 완전히 새로운 객체를 생성하고, 내부 데이터까지 새롭게 복사하는 방법입니다.
즉, 원본 객체와 복사본 객체가 서로 독립적인 데이터를 가집니다.

💡 깊은 복사의 특징

✔️ 새로운 메모리 공간을 할당하여 완전히 새로운 객체를 생성
✔️ 복사본을 수정해도 원본 객체에는 영향을 주지 않음

📝 예제: 깊은 복사 (Deep Copy)

using System;

class Person
{
    public string Name;
    public int Age;

    // 깊은 복사 메서드 (새로운 객체 생성)
    public Person DeepCopy()
    {
        Person copy = new Person();
        copy.Name = this.Name;
        copy.Age = this.Age;
        return copy;
    }
}

class Program
{
    static void Main()
    {
        // 원본 객체 생성
        Person person1 = new Person();
        person1.Name = "홍길동";
        person1.Age = 25;

        // 깊은 복사 실행
        Person person2 = person1.DeepCopy();

        // 복사한 객체의 값을 변경
        person2.Name = "이순신";
        person2.Age = 30;

        // 결과 출력
        Console.WriteLine($"person1: {person1.Name}, {person1.Age}");
        Console.WriteLine($"person2: {person2.Name}, {person2.Age}");
    }
}

🛠 실행 결과

person1: 홍길동, 25
person2: 이순신, 30

❗️ 왜 이런 결과가 나올까?

  • person2 = person1.DeepCopy();
    새로운 객체를 생성하고, Name과 Age 값을 복사
  • 따라서 person2의 값을 변경해도
    원본 객체(person1)는 영향을 받지 않음

✔️ 즉, 깊은 복사는 완전히 새로운 객체를 만들어서 원본과 독립적으로 동작하도록 함


📌 3. 얕은 복사 vs 깊은 복사 차이 정리

비교 항목얕은 복사(Shallow Copy)깊은 복사(Deep Copy)

복사 방식 참조(주소)만 복사 내부 데이터까지 새 객체로 복사
메모리 공유 원본과 복사본이 동일한 데이터 참조 원본과 복사본이 각각 독립적인 데이터 보유
한 객체 변경 시 영향 원본과 복사본이 서로 영향을 줌 원본과 복사본이 서로 독립적
복사 속도 빠름 느림 (새로운 객체 생성 필요)
사용 예시 간단한 데이터 저장, 캐싱 데이터 변경이 독립적으로 필요할 때

✔️ 얕은 복사는 가볍고 빠르지만, 객체의 변경이 원본에도 영향을 줄 수 있음
✔️ 깊은 복사는 안전하지만, 새로운 객체를 생성하므로 성능 부담이 있음


📌 4. 객체가 배열이나 컬렉션을 포함할 때?

배열이나 List<T> 같은 컬렉션이 포함된 객체는 참조 타입을 포함하고 있기 때문에,
얕은 복사를 하면 내부 참조까지 공유됩니다.

📝 복잡한 객체의 깊은 복사 예제

using System;
using System.Collections.Generic;

class Person
{
    public string Name;
    public List<string> Hobbies;

    // 깊은 복사 메서드
    public Person DeepCopy()
    {
        Person copy = new Person();
        copy.Name = this.Name;
        copy.Hobbies = new List<string>(this.Hobbies); // 새로운 리스트 생성 (깊은 복사)
        return copy;
    }
}

class Program
{
    static void Main()
    {
        // 원본 객체
        Person person1 = new Person();
        person1.Name = "홍길동";
        person1.Hobbies = new List<string> { "독서", "게임" };

        // 깊은 복사
        Person person2 = person1.DeepCopy();

        // 복사본의 취미 목록 수정
        person2.Hobbies.Add("축구");

        // 결과 출력
        Console.WriteLine($"person1 Hobbies: {string.Join(", ", person1.Hobbies)}");
        Console.WriteLine($"person2 Hobbies: {string.Join(", ", person2.Hobbies)}");
    }
}

🛠 실행 결과

person1 Hobbies: 독서, 게임
person2 Hobbies: 독서, 게임, 축구

✔️ person2.Hobbies가 변경되어도 person1.Hobbies는 그대로 유지됨
✔️ 리스트까지 새롭게 복사했기 때문에 서로 독립적인 객체가 됨


🎯 결론

  • 얕은 복사: 객체의 참조(주소)만 복사, 하나를 변경하면 다른 객체에도 영향
  • 깊은 복사: 새로운 객체를 생성, 원본과 복사본이 서로 독립적으로 동작

👉 데이터 공유가 필요하면 얕은 복사
👉 독립적인 객체가 필요하면 깊은 복사