(Kotlin/코틀린) Data object 완전 정리 — equals/hashCode/toString 자동 생성
1. data object란?
Kotlin 1.9에서 정식 안정화된 키워드로, object에 data 수식어를 붙여 toString(), equals(), hashCode()를 자동으로 생성합니다.
data object Loading
data object Success
data object Failure
data class처럼 의미 있는 문자열 표현과 동등성 비교가 가능합니다.
2. 일반 object의 문제
object Loading
object Success
println(Loading) // Loading@1b6d3586 ← 기본 toString()이 메모리 주소 포함
println(Loading == Loading) // true (같은 인스턴스이므로)
println(Loading.toString()) // Loading@1b6d3586
기본 object는 toString()이 클래스이름@해시코드 형태로 출력됩니다.
로그, 디버깅, 테스트 시 읽기 어렵습니다.
3. data object 적용 후
data object Loading
data object Success
data object Failure
println(Loading) // Loading ← 깔끔한 이름만 출력
println(Loading == Loading) // true
println(Loading.toString()) // "Loading"
// 직렬화 후 역직렬화해도 동일 인스턴스 보장
data object는 싱글턴이므로 copy(), componentN() 함수는 생성되지 않습니다. (data class와의 차이)
4. data class vs data object 비교
| 구분 | data class | data object |
|---|---|---|
| 인스턴스 수 | 여러 개 생성 가능 | 싱글턴 (1개) |
| 프로퍼티 | 있음 | 없음 |
toString() |
자동 생성 (프로퍼티 포함) | 자동 생성 (이름만) |
equals() |
자동 생성 | 자동 생성 |
hashCode() |
자동 생성 | 자동 생성 |
copy() |
있음 | 없음 |
componentN() |
있음 | 없음 |
5. sealed 계층에서의 활용
가장 대표적인 사용 패턴입니다. 프로퍼티가 없는 상태를 data object로, 프로퍼티가 있는 상태를 data class로 정의합니다.
sealed interface UiState {
data object Loading : UiState
data object Empty : UiState
data class Success(val items: List<Item>) : UiState
data class Error(val message: String) : UiState
}
// when 표현식에서 활용
fun render(state: UiState) = when (state) {
is UiState.Loading -> showLoading()
is UiState.Empty -> showEmptyView()
is UiState.Success -> showItems(state.items)
is UiState.Error -> showError(state.message)
}
// 로그 출력이 명확함
println(UiState.Loading) // Loading
println(UiState.Error("오류")) // Error(message=오류)
6. 직렬화(Serialization) 지원
kotlinx.serialization과 함께 사용할 때 data object는 직렬화 후 역직렬화 시 동일 싱글턴 인스턴스를 반환합니다.
@Serializable
sealed interface ApiResult {
@Serializable
data object Loading : ApiResult
@Serializable
data class Success(val data: String) : ApiResult
@Serializable
data class Error(val code: Int) : ApiResult
}
일반 object와 달리 data object는 역직렬화 시 항상 같은 인스턴스를 가리키도록 처리됩니다.
7. object vs data object 선택 기준
| 상황 | 권장 |
|---|---|
| 싱글턴 유틸 객체 (메서드만 있음) | object |
| 상태를 나타내는 싱글턴 값 | data object |
| 로그/테스트에서 의미 있는 출력 필요 | data object |
| sealed 계층의 상태 노드 (프로퍼티 없음) | data object |
// object: 유틸성 싱글턴
object MathUtils {
fun add(a: Int, b: Int) = a + b
}
// data object: 값으로서의 싱글턴
data object None // 프로퍼티 없는 상태 표현
8. 정리
data object는 Kotlin 1.9 정식 안정화,object에toString/equals/hashCode자동 추가copy()와componentN()은 싱글턴 특성상 제공되지 않음sealed interface/sealed class의 프로퍼티 없는 상태 노드에 가장 적합- 직렬화 후 역직렬화 시에도 동일 인스턴스 보장