Kotlin data class의 copy() 메소드를 알아보며 얕은 복사(shallow copy)와 깊은 복사(deep copy)에 대해 정리해보았다.
얕은 복사는 메모리 주소 값을 복사한다는 의미로, 참조하고 있는 실제 객체는 같다.
data class Person(val name: String, var age: Int)
fun main() {
val original = Person("John", 20)
val copy = original
copy.age = 10
println(original === copy) // true
println(original.age) // 10
}
위와 같이 얕은 복사를 하면, 같은 객체를 참조하고 있기 때문에 original === copy가 true로 된다. 그리고 복사한 copy의 age를 10으로 변경하면 original.age도 10으로 변경된다. 같은 객체를 참조하고 있기 때문에, copy.age를 변경하는 것은 사실상 original.age를 변경하는 것과 동일한 것이다.
깊은 복사는 실제 객체를 새로운 메모리 공간에 복사한다는 의미로, 독립적인 다른 객체가 생성되기 때문에 참조하고 있는 실제 객체가 다르다. 내부의 값은 같을 수 있지만 객체가 서로 다른 것이 깊은 복사이다.
data class Person(val name: String, val age: Int)
fun main() {
val original = Person("John", 20)
val copy = original.copy()
println(original === copy) // false
}
위와 같이 data class의 copy() 함수로 복사하면 다른 객체를 참조하게 되어 original === copy가 false가 된다.

위와 같이 실제로 디버깅을 해보면 둘이 다른 객체라는 것을 확연히 알 수 있다.
++추가) 좀더 검색해보니 data class의 copy() 메소드는 깊은 복사가 아니라 얕은 복사라고 한다. 이부분에 대해서는 추후 블로그 글을 수정 예정이다.
그래서 코드를 작성할 때 얕은 복사보다는 깊은 복사를 하는 것을 더 권장한다. 얕은 복사를 하고 복사한 값을 수정하면, 개발자 입장에서는 복사한 값을 수정했다고 생각할 수 있다. 하지만 실제로는 원본 값과 복사한 값이 동일한 객체의 값이기 때문에 원본 값도 수정된다. 이는 예기치 못한 문제를 야기할 수 있다.