[Kotlin] 동등성과 동일성
컴퓨터공학에는 동등성(Equality)과 동일성(Identity)이라는 개념이 존재합니다. 보통 일상생활에서 사용하는 "동등하다"와 "동일하다"라는 표현은 서로 비슷한 의미여서 두 표현의 의미를 명확히 분리해 쓰지는 않을 것 같은데요, 하지만 컴퓨터공학에서 이 두 표현은 명백히 다른 의미를 가지고 있고, 구분해서 사용해야 합니다.
이번 포스팅에서는 코틀린에서 동등성과 동일성이 어떻게 다른지 살펴보겠습니다!
1. 동등성, 동일성이 무슨 용어지?
동등성, 동일성은 객체나 데이터를 비교할 때 같은지를 판단하는 개념입니다. 그리고 어떻게 같은지에 따라서 같다고 하더라도 동등하거나 동일한 것으로 나뉘게 됩니다.
2. 동등성이란?
먼저 동등성은 두 데이터가 같은 내용(값)을 가지고 있음을 의미합니다. 다음 코드를 봅시다.
fun main() {
val a: Int = 3
val b: Int = 3
println(a == b) // Output: true
}
위 코드에서 저는 변수 a
와 b
를 선언했고 같은 값인 3
을 가지고 있습니다.
그리고 a==b
를 통해 동등성을 비교하고 있는데요, ==
연산자는 동등성 비교 연산자입니다. 즉 a
와 b
의 동등성을 비교한 코드이고, 같은 내용을 가지고 있기 때문에 두 데이터는 동등합니다.
3. 동일성이란?
동일성이란 두 데이터가 같은 메모리 주소를 가리키고 있음을 의미합니다. 다음 코드를 보죠!
class MyNumber(val num: Int)
fun main() {
val a = MyNumber(3)
val b = MyNumber(3)
println(a === b) // Output: false
}
이번에는 클래스의 두 인스턴스 a
, b
를 생성했는데요, 같은 프로퍼티를 가지고 있습니다.
그리고 ===
연산자를 통해 동일성을 비교하고 있습니다. 앞에서 ==
는 동등성 비교 연산자였죠? ===
는 동일성 비교 연산자입니다. a
와 b
의 동일성을 비교한 것인데, false가 출력됩니다. 왜일까요? a
와 b
는 다른 주소를 가리키고 있기 때문입니다.
그림으로 표현하면 이렇게 됩니다. (주소값 0x01, 0x41등은 예시의 값이니 참고만 해주세요!)
a
와 b
가 서로 다른 주소값 0x41, 0x42를 참조하고 있죠? 두 주소값의 메모리 공간에는 둘 다 MyNumber(num=3)
이 들어있지만, 서로 다른 메모리 주소를 가리키고 있기 때문에 동일성 비교의 결과는 false가 됩니다.
class MyNumber(val num: Int)
fun main() {
val a = MyNumber(3)
val b = a
println(a === b) // Output: true
}
반면 위와 같은 경우라면 a
와 b
는 같은 주소를 가리키고 있기 때문에 동일성 비교가 true가 됩니다.
요런 상황이 되죠! 동등성과 동일성의 차이가 이해가 되실까요? ㅎㅎ
하나 더! 두 데이터가 동일하다면 반드시 동등하답니다. 같은 주소를 가리키고 있으니 내용도 당연히 같아야겠죠? 즉 동일성은 동등성의 충분조건이라는 점도 알고 계시면 좋을 것 같네요~
4. 심화 - 객체끼리 동등성을 비교하려면?
동일성, 동등성을 처음 공부해 보시는 분들이라면 여기서부터는 읽지 않아도 괜찮습니다. 주제를 살짝 벗어난 내용이라서요!
동일성을 알아보면서 MyNumber
라는 클래스를 정의하고 그 인스턴스를 만들어 동일성을 비교했죠? 그런데 인스턴스끼리 동등성을 비교하려면 어떻게 해야 할까요?
class MyNumber(val num: Int)
fun main() {
val a = MyNumber(3)
val b = MyNumber(3)
println(a == b) // Output: false
}
위 코드에서 a
와 b
가 동일하지 않다는 것은 위에서 다뤘죠? 그런데 동등성은 어떨까요? 동등한 걸까요? 동등하지 않은 걸까요?
a == b
가 false인 것으로 보아 동등하지 않군요.. 그런데 언뜻 생각해보면 같은 내용(3)을 가지고 있으니 동등해야 하는 것 아닐까요?
왜 이런 결과가 도출되냐면, 객체의 동등성 비교는 기본적으로 메모리주소의 동등성을 비교하기 때문입니다. 뭐야? 그럼 객체의 동등성 비교는 동일성 비교와 다른 것이 없지 않냐! 라고 생각이 되실 겁니다. 이런 불편함을 해소하기 위해 Data class라고 하는 특별한 클래스가 존재합니다.
data class MyNumber(val num: Int)
fun main() {
val a = MyNumber(3)
val b = MyNumber(3)
println(a == b) // Output: true
}
Data class를 쓰게 되면 동등성 비교가 메모리주소를 기준으로 비교하지 않고, 프로퍼티를 기준으로 비교하게 됩니다. 자세한 것은 제가 쓴 Data class 알아보기 포스팅을 참고하시면 좋을거예요! 😊