(Kotlin/코틀린) Data object 완전 정리 — equals/hashCode/toString 자동 생성


1. data object란?

Kotlin 1.9에서 정식 안정화된 키워드로, objectdata 수식어를 붙여 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

기본 objecttoString()클래스이름@해시코드 형태로 출력됩니다.
로그, 디버깅, 테스트 시 읽기 어렵습니다.


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. 정리



Related Posts