삽질의 현장/- .NET

#046_닷넷(.NET)_.Net Framework 기본 - 얕은 복사와 깊은 복사의 필요성

shovelman 2015. 10. 30. 16:35


안녕하세요 삽잡이입니다.


이번 시간에는 복사에 대해서 알아보려고합니다.

깊은 복사, 얕은 복사 모두 다 다루려고 했지만,

글이 길어지면 여러분도 지루해하실터이니... 

(맞습니다... 원래 맨날 길죠...)

이번 시간은 Shallow Copy와 Deep Copy의 필요성에 대해서 중점적으로 다루려고 합니다.


시작해보겠습니다.


Shallow Copy, Deep Copy 모두 다 복사입니다.

그런데 만약, 복사할 대상이 Class형 참조자라면, 이를 논할 수 없습니다.

단지 참조를 복사한 것일 뿐이지요...

하지만, struct형 객체일 경우 Shallow Copy, Deep Copy를 논할 수 있습니다.


무슨 말인지 감이 안잡히시지요? 

지금부터 시작하겠습니다.


Shallow Copy, Deep Copy는 사실 이름만 거창할 뿐

얕은 복사, 깊은 복사를 말하는 것으로 

이미 C++을 배우신 분이라면 한번쯤은 겪어보셨을 복사입니다.


두 용어는 모두 '객체 복사'에서 나오는 것입니다.

객체를 복사할 때에는

'어떻게 객체를 복사할 것인가'가 전제로 깔립니다.

이 전제에 의해 Shallow Copy일지, Deep Copy일지 나뉘어지는 것입니다.

정말 중요합니다. Shallow Copy, Deep Copy는 객체가 복사될 때 논할 수 있는 용어입니다.



과연 이 문장은 얕은 복사일까요, 깊은 복사일까요?


사실 이 문장은 객체 복사가 아닙니다.

얕은 복사, 깊은 복사는 아까도 말했듯이 객체가 복사될 때 논할 수 있다고 했습니다.

우리는 Point 타입을 struct로 정의했는지, class로 정의했는지 모릅니다.



만약, Point 타입이 class 형식으로 만들어져있다면,

pt는 참조자입니다. 따라서 pt2에 pt를 대입한다고 해도 이는 '참조 복사'이지

얕은 복사, 깊은 복사를 논할 거리가 못됩니다. 

단지 참조를 복사한 것 뿐이니깐요...



하지만, 만약 

pt가 struct형식이라면 얘기가 달라집니다.

pt는 stack 영역에 값이 초기화 되어있는 객체입니다.

pt는 객체이기 때문에 이때서는 비로소 Shallow Copy, Deep Copy를 논할 수 있게 됩니다.

객체를 복사하는 것이기 때문이지요.


다시한번 말씀드리지만,

'객체를 복사할 때' 라는 전제가 붙지 않는다면 깊은 복사와 얕은 복사는 성립하지 않습니다.



얕은 복사란, '멤버 대 멤버' 복사라고도 부릅니다.

비트 메모리 복사라고도 부르지요.

객체가 가지고 있는 모든 멤버들을 그대로 멤버에다가 복사하기 때문입니다.

필드 값을 그대로 복사하게 되니 얕은 복사라고 하지요.

위의 예제처럼 struct만을 복사할 경우 

모든 필드가 제대로 복사가 되니 완벽한 객체를 복사할 수 있군요.


Point라는 객체는 얕은 복사로도 완벽하게 복사가 수행될 수 있기 때문에

(멤버 대 멤버 복사를 정확하게 했죠...)

여기서는 깊은 복사, 얕은 복사를 논할 필요가 없습니다.

또 다시한번 말씀드리지만.. 지금 상태에서 class 복사는 참조 복사입니다!


struct는 값 객체입니다.

값으로만 이루어진 객체이기때문에 그냥 아무 생각없이 복사를 해도 잘 수행합니다.


하지만, 문제는 여기서부터 나옵니다...

깊은 복사, 얕은 복사는 객체에 대해서만 해당되는데,

객체가 참조를 가지고 있게 되면 문제가 생기는 것이죠.

즉, 기존 값 복사의 경우

사를 하더라도 컴파일러가 제공하는 복사기능을 통해 

아무 문제가 발생하지 않았다 이겁니다.


이런 코드가 있다고 해봅시다.



이처럼 class Rect에 class Point를 담고 있는 구조의 형식이 있습니다.

이때 똑같은 Rect형 타입의 참조자에 기존의 rt를 복사했습니다.

어떻게 될까요?

정답부터 말씀드리자면, 객체 내 참조를 가지기 때문에 문제가 생깁니다.

에러가 난다는 소리가 아닙니다.

객체가 참조를 가지고 있는데 이 객체를 복사하는 경우에는 

얕은 복사가 안된다 이겁니다.



이렇게 하나의 객체를 같이 참조하고 있는 꼴이 됬습니다.


이럴 때서야 비로소 깊은 복사가 필요하게 됬습니다.

깊은 복사는 그런데 뭘까요?

바로 '참조가 가지고 있는 값 까지도 따로 참조할 수 있도록하는 것'을 말합니다.

아하... 깊은 복사는 멤버의 참조가 가지는 값까지 복사하니 

확실히 값까지 복사할 수 있겠군요.


따라서 객체가 아니면 이런 용어를 쓸 수 없다고 하는 것입니다.

정의가 이렇기 때문입니다.


얕은 복사가 무조건 나쁜 것이 아닙니다.

사실 웃기지요... 좋고 나쁜것이 어디있겠습니까?

하지만, 얕은 복사를 하는 경우 객체가 참조를 가지고 있다면,

이 객체의 멤버 변수가 참조를 가지기 때문에 문제가 생길 수 있다는 소리이지요.


계속 반복하지만 객체 내부의 참조가 있나/ 없나에 의해

Shallow Copy와 Deep Copy의 출동 여부가 갈립니다.


다음시간에 C#에서 struct, class일 경우를 나누어 비교해보며 

더욱더 알차게 공부해보도록 하겠습니다.


이상 삽잡이였습니다!