얕은 복사(Shallow Copy)와 깊은 복사(Deep Copy)는 프로그래밍 언어에서 사용되는 개념입니다.
목차는 다음과 같습니다.
3가지 방법으로 이해를 나눴기 때문에 3가지 방법 중 가장 쉽게 이해할 수 있다 생각되는 곳으로 가셔서 참조하시면 좋을 것 같습니다.
- 얕은 복사와 깊은 복사
- 그림으로 이해하기
- 코드로 이해하기
얕은 복사와 깊은 복사
얕은 복사(Shallow Copy)
복사하려는 원본 객체에 대해서 새로운 단일 객체 또는 새로운 복합 객체를 만들고 원본 객체를 참조한다. 즉, 다양한 복합 멤버 변수를 갖고 있는 객체가 인스턴스가 생성될 때 인스턴스화 되면서 메모리에 할당된 주소의 값을 참조한다. 또한 얕은 복사는 복사 객체가 원본 객체에 종속적이다.
얕은 복사는 주소에 의한 참조 즉, call-by-reference와 유사한 개념이 된다.
깊은 복사(Deep Copy)
복사하려는 원본 객체에 대해서 새로운 단일 객체 또는 새로운 복합 객체를 만들고 원본 객체를 대상으로 인스턴스화할 수 있는 클래스 내부의 클래스 변수(static)와 메서드(static)뿐 아니라 인스턴스 값 모두를 복사하여 원본 객체로부터 독립적인 객체를 생성한다.
깊은 복사는 새로운 객체가 원본 객체 자체를 Copy 하는 것이다. 즉, call-by-values와 유사한 개념이 된다.
얕은 복사 | 깊은 복사 | |
장점 | 빠르고 간결하다. | 객체 자체를 복사하기 때문에 독립된 새로운 객체로 다형성을 부여하여 사용하거나 재정의할 수 있다. |
단점 | 바로 위의 다형성의 장점이 존재하지만 값을 참조하는 것이므로 원본 객체에 종속적인 단점도 존재한다. 원본 객체가 수정되는 경우 복사 객체가 원본 객체와 동일하게 변동이 생긴다. |
모든 인스턴스 값을 갖고 오기 때문에 얕은 복사에 비해서 상대적으로 느리고 복잡하다. |
얕은 복사와 깊은 복사를 정리하면 다음과 같다.
- 새로운 B객체를 생성 후 원본 A객체를 메모리 영역을 참조해서 원본에 종속된 객체를 생성하는 것이 얕은 복사이다.
- 새로운 B객체를 생성 후 원본 A객체를 통째로 복사해서 독립적인 새로운 객체를 메모리 영역에 생성하는 것이 깊은 복사이다.
그림으로 이해하기
위 그림은 다양한 멤버 변수 값들을 갖는 클래스 Box이다.
인스턴스화하는 과정을 간단하게 설명하면 Box라는 컴퓨터로 구현할 개념을 객체로 본다. 이 객체를 설계한 것이 클래스이며, 클래스를 실제로 컴퓨터에 메모리에 값에 할당하는 것이 인스턴스 화이다.
얕은 복사(Shallow Copy)
인스턴스화하여 객체를 메모리에 할당했을 때이다. 얕은 복사는 원본 객체 A와 복사 객체 B가 하나의 할당받은 영역을 지정하여 원본 객체 A가 변경되는 경우 B도 똑같은 메모리 상의 영역을 참조하고 있기 때문에 값이 종속적으로 변경된다. 이것이 얕은 복사이다.
깊은 복사(Deep Copy)
위 그림은 좌측은 원본 객체 A이며, 우측은 복사 객체 B이다. 위의 화살표는 A 객체의 있는 내용들을 모두 복사해서 새로운 메모리 영역에 있는 B객체를 할당해 준 것이다. 이때 A와 B는 컴퓨터로부터 각각 다른 메모리 영역을 배정받았으므로 A객체를 수정하거나 B객체를 수정해도 값에 변화가 없는 것이 깊은 복사이다.
코드로 이해하기
얕은 복사와 깊은 복사를 나타내는 소스코드는 매우 많다. 하지만 본인이 작성한 코드로 이해하기에서는 자바에서 제공되는 메서드와 각각의 복사 방법을 스스로 정의한다. 그리고 예시를 들어서 설명 진행을 한다.
자바에서 복사를 위한 메소드는 arraycopy(), clone(), copyObject 등 많은 복사 방법들이 존재한다.
복사 메소드에 대해서는 필요시 다음의 링크에 들어가서 함수를 찾아보는 방법도 존재한다.
https://docs.oracle.com/javase/8/docs/api/
위 사이트에서 전체적인 자바에 사용되는 메서드나 패키지 등을 확인할 수 있으므로 본인이 자바에서 찾는 기능을 찾을 수 없을 때 메서드를 찾거나 OVERVIEW에서 패키지를 찾아서 누르면 패키지에 종속된 메서드들이 나오는데 그 메서드들을 읽어보고 찾는 것도 좋은 방법이 된다.
[배열] Shallow copy code
1
2
3
4
5
6
7
8
9
|
public class Shallow_array {
public static void main(String[] args) {
int arr1[] = {1, 2, 3, 4, 5};
int arr2[] = arr1;
System.out.println(arr1.toString());
System.out.println(arr2.toString());
}
}
|
위 소스 코드는 arr1과 arr2의 주소의 위치를 확인하는 소스 코드이다.
소스코드를 실행하면 다음과 같다.
단순히 정수형 배열 arr2이 arr1을 참조하여 값을 갖고 왔기 때문에 본인이 메모리 영역을 받지 못한 것이다.
이러한 경우 지도상 아파트 위치를 아는 것일 뿐 위치에 있는 아파트가 본인 매매(본인만의 메모리 영역)로 인한 집이 아닌 놀러 가는 경우나 전세나 월세와 같이 본인의 소유가 아닌 타인의 소유를 잠시 빌리는 의미다.
(메모리 값은 컴퓨터에서 자동으로 할당해주는 것이므로 매번 실행 결과가 다를 수 있습니다.)
[배열] Deep copy code
1
2
3
4
5
6
7
8
9
|
public class Deep_array {
public static void main(String[] args) {
int arr1[] = {5, 4, 3, 2, 1};
int arr2[] = arr1.clone();
System.out.println(arr1.toString());
System.out.println(arr2.toString());
}
}
|
위 객체는 clone()이라는 메소드를 이용하여 원본 객체를 복사 객체로 깊은 복사한 코드이다.
주소 값의 참조가 아닌 값을 통째로 복사하는 깊은 복사이다.
깊은 복사는 위에 얕은 복사의 아파트 주소를 알아서 본인 소유가 아닌 것과 다르게 같은 동 아파트(새로운 메모리 영역)를 통째로 매매하여 복사 객체 본인의 소유가 되는 것으로 이해하면 쉽다.
예전에 받았던 조언으로 생각나서 정리하는 차원에서 포스팅을 진행했습니다.
'Java ☕ > Java' 카테고리의 다른 글
[Java] Call by Value와 Call by Reference 정리. (값 호출과 참조 호출.) (0) | 2023.05.24 |
---|---|
[Java] 메소드 오버로딩과 오버라이딩 (with 아삭 한입 정리하기) (0) | 2023.05.23 |
[Java] 변수(Variable)와 상수(constant) (1) | 2021.11.30 |
Java의 장단점 (0) | 2021.11.10 |
객체, 클래스, 인스턴스의 개념 (0) | 2021.01.02 |