깊은 복사와 얕은 복사

객체는 다른 객체를 참조할 수 있는데 이럴 경우에 객체의 복사본을 핸들링 할 경우 깊은 복사인가, 얕은 복사인가에 따라 결과값이 달라질 수 있으니 주의해서 다루어야 합니다.


복사를 한다는 것은 기존 객체와 같은 값을 가진 새로운 객체로 만든다는 것입니다.

객체들은 멤버를 가지고 있고 그 멤버들은 값일 수도 있고 참조 형식일 수도 있습니다.

- 바로 이 객체들이 가진 값 형식과 참조 형식의 복제 방식에 따라 얕은 복사와 깊은 복사의 개념이 나누어지게 됩니다.



얕은 복사(Shallow Copy)

얕은 복사는 객체가 가진 멤버들의 값을 새로운 객체로 복사하는데 만약 객체가 참조타입의 멤버를 가지고 있다면 참조값만 복사가 됩니다.


아래의 예제를 보면,,


main의

Person B = A;

라는 구문이 있습니다.

Person B(A); 

와 같은 뜻으로 동작합니다.

이것이 바로 복사 생성자로 같은 클래스의 A객체를 이용하여 B객체로 초기화 하는 것입니다.

- 자기 자신과 같은 형태의 객체를 받는 것을 복사 생성자라 합니다.


현재 코드에서는 name은 포인터 형태로 메모리의 주소값을 참조하여 실제 값을 담는 변수입니다.

이렇게 되면 값을 참조하기 때문에 복사를 하더라도 참조했던 값은 그대로 같은 참조를 하게 됩니다.

따라서, 현재 객체를 복사하고 새로운 값을 넣었음에도 불구하고 "wonjayk"라는 이름은 그대로 참조되게 되는 것입니다.

그림으로 설명드리면



이런식으로 같은 참조 값을 가지게 되는 것입니다.

포인터로 참조하지 않는 age의 경우에는 변경된 값이 출력되고, 참조값으로 설정된 문자열 name은 같은 메모리 공간을 참조하게 되어 나중에 변경된 값이 들어가게 되는 것입니다.


얕은 복사는 참조는 복사되지만 참조되는 객체가 복사되지 않기 때문에 이런 현상이 일어나는 것입니다.



깊은 복사 (Deep Copy)

깊은 복사는 전체 복사라고도 합니다.

얕은 복사와는 달리 객체가 가진 모든 멤버(값과 참조형식 모두)를 복사하는 것을 말합니다.

객체가 참조 타입의 멤버를 포함할 경우 참조값의 복사가 아닌 참조된 객체 자체가 복사되는 것을 깊은 복사라 합니다.


아래의 예제를 보면..


name 객체가 참조형이기 때문에 새로운 공간을 만든 후 값을 넣고 있습니다.

따라서 복사본과 원본의 메모리 참조 공간 자체가 다르기 때문에 얕은 복사처럼 같은 값을 참조하는 것이 아니고 각자의 값을 참조하게 됩니다.


역시 그림으로 설명드리면


이러한 형태를 띄게 됩니다.



객체를 복사하게 될 때 참조값을 포함하는지, 아닌지를 꼭 확인해서 얕은 복사, 깊은 복사를 적용해주어야 오류가 없을 것입니다.

Posted by 긍정왕오킹