Computer >> 컴퓨터 >  >> 프로그래밍 >> Java

Java 깊은 복사(Deep Copy)와 얕은 복사(Shallow Copy) 차이 완벽 정리

Java에서 깊은 복사(Deep Copy)얕은 복사(Shallow Copy)는 모두 주어진 객체를 복제한다는 공통점이 있지만, 복사하는 방식과 그 결과에서 중요한 차이가 있습니다. 두 방식의 개념과 동작 차이를 예제 코드와 함께 살펴보겠습니다.

얕은 복사(Shallow Copy)란?

얕은 복사는 객체의 새 인스턴스를 생성한 뒤, 원본 객체의 필드 값을 그대로 새 인스턴스에 복사하는 방식입니다. 이때 배열이나 객체처럼 참조 타입인 필드는 값 자체가 아니라 참조(주소)만 복사되기 때문에, 원본과 복사본이 동일한 내부 객체를 공유하게 됩니다. 따라서 원본 데이터가 변경되면 복사본에도 그 변경이 그대로 반영됩니다. 얕은 복사는 '얕은 클로닝(shallow cloning)'이라고도 불리며, 복사된 인스턴스를 사용할 때는 원본 객체 타입으로 명시적으로 형 변환(casting)해야 하는 경우도 있습니다.

예제 코드

import java.util.* ;
class Demo{
    private int[] my_data;
    public Demo(int[] my_vals){
        my_data = my_vals;
    }
    public void display_data(){
        System.out.println(Arrays.toString(my_data) );
    }
}
public class Use_Demo{
    public static void main(String[] args){
        int[] my_vals = {56, 89, 91};
        Demo my_inst = new Demo(my_vals);
        my_inst.display_data();
        my_vals[0] = 65;
        my_inst.display_data();
    }
}

실행 결과

[56, 89, 91]
[65, 89, 91]

위 예제의 Demo 클래스는 int 배열을 저장하는 변수와, 전달받은 배열의 참조를 그대로 할당하는 생성자로 구성되어 있습니다. display_data 메서드는 배열의 내용을 출력합니다. main 메서드에서 인스턴스를 생성한 뒤 원본 배열 my_vals의 첫 번째 요소를 65로 변경하면, 객체를 통해 출력한 결과에도 동일한 변경이 나타납니다. 이는 얕은 복사 시 배열 자체가 아닌 배열의 참조만 복사되었기 때문입니다.

깊은 복사(Deep Copy)란?

깊은 복사는 원본과 완전히 독립적인 복사본이 필요할 때 사용합니다. 객체 내부의 참조 타입 필드까지 새롭게 생성하여 값을 하나씩 복사하기 때문에, 원본이 변경되어도 복사본에는 어떠한 영향도 주지 않습니다. Java에서 깊은 복사를 구현하려면 클래스가 Cloneable 인터페이스를 구현하고 clone() 메서드를 재정의하거나, 아래 예제처럼 생성자에서 참조 대상의 내용을 직접 복사하는 방식을 사용할 수 있습니다.

예제 코드

import java.util.*;
class Demo{
    private int[] my_data;
    public Demo(int[] my_vals){
        my_data = new int[my_vals.length];
        for (int i = 0; i < my_data.length; i++){
            my_data[i] = my_vals[i];
        }
    }
    public void display_data(){
        System.out.println(Arrays.toString(my_data));
    }
}
public class Use_Demo{
    public static void main(String[] args){
        int[] my_vals = {56, 89, 91};
        Demo my_inst = new Demo(my_vals);
        my_inst.display_data();
        my_vals[0] = 65;
        my_inst.display_data();
    }
}

실행 결과

[56, 89, 91]
[56, 89, 91]

이번 Demo 클래스의 생성자는 전달받은 배열과 같은 크기의 새 배열을 생성한 뒤, 반복문을 통해 각 요소의 값을 하나씩 복사합니다. 따라서 main 메서드에서 원본 배열의 첫 번째 요소를 65로 변경해도, 객체 내부의 배열은 별개의 배열이므로 출력 결과가 [56, 89, 91]로 그대로 유지됩니다.

얕은 복사 vs 깊은 복사 비교

구분얕은 복사깊은 복사
복사 수준필드 값(참조 포함)만 복사참조 대상의 실제 값까지 복사
내부 객체 공유원본과 복사본이 공유완전히 독립적
원본 변경 시 영향복사본에도 그대로 반영됨영향 없음
특징빠르고 간단함비용이 더 들지만 안전함

마무리

얕은 복사는 불변(immutable) 객체나 읽기 전용 데이터를 다룰 때 간편하게 활용할 수 있지만, 가변(mutable) 상태를 공유하면 의도치 않은 부작용이 발생할 수 있습니다. 반면 깊은 복사는 복사에 드는 비용이 더 크지만 데이터의 독립성을 보장하므로, 원본 보호가 중요한 상황에서 안전하게 사용할 수 있습니다. 객체의 특성과 용도에 맞게 두 복사 방식을 적절히 선택하는 것이 좋습니다.