WIPIVERSE

객체 복사

정의

객체 복사는 프로그램 실행 중에 메모리 상에 존재하는 객체의 상태와 구조를 동일하게 복제하여 새로운 객체를 생성하는 과정을 의미한다. 복제된 객체는 원본과 독립적인 메모리 영역을 차지하므로, 복사 후의 변경은 서로에게 영향을 미치지 않는다.

복사의 종류

  1. 얕은 복사(Shallow Copy)

    • 객체 자체는 새로 복제하지만, 객체가 참조하고 있는 다른 객체(예: 배열, 리스트, 다른 객체 등)는 동일한 메모리 주소를 공유한다.
    • 결과적으로 복제된 객체와 원본 객체는 내부 참조 대상에 대해 동일한 인스턴스를 가리키게 된다.
  2. 깊은 복사(Deep Copy)

    • 객체와 그 객체가 직접 또는 간접적으로 참조하고 있는 모든 하위 객체까지 재귀적으로 복제한다.
    • 복제된 객체와 원본 객체는 완전히 독립적인 메모리 구조를 가지며, 어느 한쪽을 수정해도 다른 쪽에 영향을 주지 않는다.

구현 방식

  • 프로그래밍 언어별 지원

    • Java: clone() 메서드(Object 클래스 제공)와 Cloneable 인터페이스를 이용해 얕은 복사를 수행한다. 깊은 복사는 사용자 정의 코드가 필요하다.
    • C++: 복사 생성자와 대입 연산자를 구현함으로써 얕은 복사와 깊은 복사를 제어한다. 표준 라이브러리에서는 std::copy 등이 활용된다.
    • Python: copy 모듈의 copy() 함수가 얕은 복사를, deepcopy() 함수가 깊은 복사를 제공한다.
    • C#: 기본적으로 참조형 객체는 얕은 복사만 제공되며, 깊은 복사는 ICloneable 인터페이스 구현이나 직렬화/역직렬화 기법을 사용한다.
    • JavaScript: 객체 리터럴 복사는 Object.assign()이나 스프레드 연산자(...)를 통해 얕은 복사가 이루어진다. 깊은 복사는 재귀적인 함수 구현이나 외부 라이브러리(lodash.cloneDeep 등)를 사용한다.
  • 사용자 정의 복사

    • 객체의 복제 로직이 복잡한 경우, 개발자는 명시적으로 복사 메서드나 생성자를 정의하여 필요한 복사 방식을 구현한다.
    • 예를 들어, 복제 과정에서 리소스 해제, 식별자 재생성, 불변 객체 처리 등이 포함될 수 있다.

활용 사례

  • 불변 객체 생성: 기존 객체를 변형하지 않고 새로운 상태를 반영한 객체를 만들 때 복사를 이용한다.
  • 멀티스레드 환경: 공유 객체를 복제하여 각 스레드가 독립적인 데이터를 다루게 함으로써 동시성 문제를 회피한다.
  • 데이터 전송: 네트워크나 파일 I/O를 위해 객체를 직렬화하고 복제본을 전달한다.
  • 버전 관리: 변경 전후 상태를 보존하기 위해 객체 스냅샷을 복사한다.

주의 사항

  • 얕은 복사는 내부 참조 객체가 공유되기 때문에, 복제본을 수정할 경우 원본에도 영향을 줄 수 있다. 따라서 객체 구조와 의도한 복제 수준을 명확히 파악하고 적절한 복사 방식을 선택해야 한다.
  • 깊은 복사는 재귀적인 복제 작업을 수행하므로 메모리 사용량과 성능에 부하가 발생할 수 있다. 대량 데이터나 복잡한 객체 그래프에서는 복사 비용을 고려한 설계가 필요하다.
둘러보기

더 찾아볼 만한 주제

    전체 문서 보기