프로그래밍Kotlin 개발자

Kotlin에서 데이터 객체(data object)는 어떻게 작동하며, 그 용도와 equals/hashCode/toString 구현 방식, 일반 객체(object) 및 데이터 클래스(data class)와의 차이점은 무엇인가요?

Hintsage AI 어시스턴트로 면접 통과

답변.

문제의 역사:

Kotlin 1.9 이전에는 object 객체가 data일 수 없어, 자동으로 equals, hashCode, toString을 받고 있는 싱글턴 객체를 만들 수 없었습니다. data object가 도입되면서 이 제한이 해제되었습니다. 이제는 값(value) 및 열거형(enum)과 유사한 패턴에 적합한 자동으로 생성된 메서드를 가지는 싱글턴 객체를 만들 수 있습니다.

문제:

이전에는 싱글턴 객체들조차도 올바른 equals(), hashCode(), toString()을 얻기 위해 수동으로 구현하거나 다른 트릭을 사용해야 했습니다. 이는 보일러플레이트 코드 증가와 오류 가능성을 높였습니다.

해결책:

데이터 객체(data object)는 인스턴스가 고유하며, 컬렉션, 직렬화, 비교 및 디버깅용으로 표준적인 equals/hashCode/toString 동작이 필요한 객체를 위해 사용하세요.

코드 예시:

data object NotAvailable fun checkStatus(status: Any) = when (status) { NotAvailable -> "데이터가 없습니다" else -> "다른 상태" } val set = setOf(NotAvailable) println(NotAvailable in set) // true println(NotAvailable.toString()) // NotAvailable

주요 특징:

  • 데이터 객체는 data class의 계약에 따라 equals/hashCode/toString을 구현합니다.
  • 이는 싱글턴 객체(유일한 인스턴스)입니다.
  • 데이터가 없는 값(value)과 유사하거나 열거형(enum)과 유사한 패턴에 적합합니다.

함정 질문.

데이터 객체가 속성을 가질 수 있나요?

가질 수 있지만, backing field 없이 val 속성만 가능합니다(싱글턴에는 저장되는 것이 없어야 함).

data object Loading { val status: String get() = "로딩 중..." }

데이터 객체가 일반 객체와 equals 측면에서 어떻게 다릅니까?

일반 객체의 equals는 참조 동등성만 확인하지만, 데이터 객체는 데이터 계약을 비교합니다. 그러나 싱글턴의 경우 항상 동일한 객체입니다. 그럼에도 불구하고 재정의된 equals/hashCode가 컬렉션에 더 유용합니다.

데이터 객체로부터 상속할 수 있나요?

아니요, 데이터 객체는 최종적이며(모든 객체가 그렇듯) 상속할 수 없습니다.

일반적인 오류 및 안티 패턴

  • 여러 객체가 있을 때 enum 대신 데이터 객체를 사용
  • 데이터를 저장하려고 하면서 데이터 객체를 사용 — 허용되지 않음
  • 동등성이 항상 참조 기반임을 간과하더라도, 컬렉션에서는 값 기반으로 처리됨

실제 사례

부정적인 사례

모든 상태에 대해 enum 대신 다양한 데이터 객체를 사용했습니다. 1년 후 문자열별 직렬화가 필요하게 되었고, 객체 이름과 유형을 수동으로 매칭해야 했습니다.

장점:

  • 간편한 초기화

단점:

  • 문자열 직렬화에 쓸데없는 추가 작업, 매칭 오류

긍정적인 사례

네트워크 요청의 반환 값으로 데이터 객체를 사용하여 특별한 상태: Loading, Empty, Error를 사용했습니다. 코드가 컴팩트하고 equals, hashCode, toString이 자동으로 지원됩니다.

장점:

  • 컬렉션에서 확인하기 편리함
  • 아름다운 로깅

단점:

  • 변수 속성을 추가할 수 없음, val-lazy만 가능