면접 질문 목록으로 가기
면접 질문실전 질문꼬리 질문

구조적 동등성과 참조적 동등성

skydovesJaewoong Eum (skydoves)||7분 소요

구조적 동등성과 참조적 동등성

코틀린은 객체를 비교할 때 두 가지 연산자를 제공합니다. 구조적 동등성(structural equality)을 검사하는 == 연산자와, 참조적 동등성(referential equality)을 검사하는 === 연산자가 바로 그것입니다. 구조적 동등성은 두 객체의 내용이 동일한지 비교하는 것이고, 참조적 동등성은 두 참조가 메모리상 완전히 같은 인스턴스를 가리키는지 비교하는 것입니다. 컬렉션 연산, 캐싱, 그리고 객체 정체성(identity) 검사에서 어떤 비교 방식을 사용해야 하는지 정확히 이해하는 것은 올바른 코드 작성에 필수적입니다. 면접에서도 이 두 개념의 차이를 명확히 설명하고, 각각의 적용 시나리오를 구체적으로 제시할 수 있어야 좋은 평가를 받을 수 있습니다.

이번 면접 질문을 통하여 아래 내용들을 학습하실 수 있습니다.

  • 구조적 동등성과 참조적 동등성의 차이를 설명할 수 있습니다.
  • == 연산자가 내부적으로 equals() 메서드에 위임하는 방식을 이해할 수 있습니다.
  • 구조적 동등성 대신 참조적 동등성을 사용해야 하는 상황을 식별할 수 있습니다.
  • data classequals()hashCode()를 자동으로 생성하는 원리를 설명할 수 있습니다.

==를 사용한 구조적 동등성

코틀린에서 == 연산자는 내부적으로 equals() 메서드 호출로 변환됩니다. 좌측 피연산자가 null인 경우에는 equals()를 호출하지 않고, 우측 피연산자 역시 null일 때만 true를 반환합니다. 그 외의 경우에는 left.equals(right)를 호출하여 결과를 판단합니다.

data class Person(val name: String, val age: Int)

val person1 = Person("skydoves", 30)
val person2 = Person("skydoves", 30)

println(person1 == person2)  // true

Persondata class이므로, 컴파일러가 주 생성자에 선언된 모든 프로퍼티를 비교하는 equals() 구현을 자동으로 생성합니다. 따라서 동일한 nameage를 가진 두 Person 인스턴스는 메모리상 별개의 객체이더라도 구조적으로 동등하다고 판정됩니다.

equals()를 오버라이드하지 않은 일반 클래스의 경우, Any로부터 상속받은 기본 구현이 참조적 동등성으로 폴백(fallback)합니다. 즉, equals()를 직접 정의하지 않은 클래스에서는 =====가 동일하게 동작합니다. 면접에서 이 점을 명확히 구분하여 설명할 수 있으면 좋은 인상을 줄 수 있습니다.

===를 사용한 참조적 동등성

=== 연산자는 두 참조가 메모리상 동일한 객체를 가리키는지 검사합니다. 어떤 메서드도 호출하지 않으며, 오버라이드할 수도 없습니다.

val person1 = Person("skydoves", 30)
val person2 = Person("skydoves", 30)
val person3 = person1

println(person1 === person2) // false
println(person1 === person3) // true

person1person2는 내용이 동일하지만 서로 다른 인스턴스이므로 ===false를 반환합니다. 반면 person3에는 person1과 동일한 참조가 할당되었으므로 ===true를 반환합니다.

참조적 동등성은 내용이 아닌 **정체성(identity)**을 확인해야 할 때 유용합니다. 가령, 이전에 등록한 콜백 람다와 동일한 인스턴스인지 검사하거나, 캐시에 저장된 객체가 교체되지 않았는지 확인하는 경우에 활용할 수 있습니다.

이 면접 질문은 구독자 전용입니다

Dove Letter를 구독하시면 안드로이드, 코틀린 개발 관련 독점 면접 질문의 전체 내용을 볼 수 있습니다.

구독하기
면접 질문 목록으로 가기