관리 메뉴

The Nirsa Way

[Kotlin] 데이터 클래스, 오브젝트 클래스(data class, object class) 본문

Development/Kotlin

[Kotlin] 데이터 클래스, 오브젝트 클래스(data class, object class)

KoreaNirsa 2025. 8. 22. 11:54
반응형
※ 해당 코틀린 포스트들은 기본적으로 자바를 알고 있다는 가정하에 간단히 예제만 제공하여 설명됩니다.

 

데이터 클래스, 오브젝트 클래스(data class, object class)

 

1. data class

코틀린의 데이터 클래스는 흔히 사용하는 DTO를 생각하시면 됩니다.

자바의 경우 getter, setter, equals, hashcode 등을 직접 생성하거나 롬복이라는 외부 라이브러리에 의존해야 했던 반면, 코틀린은 data class를 따로 제공하여 보다 간편하고 짧은 코드로 사용할 수 있습니다.

즉 아래와 같이 data class를 선언하고 주 생성자를 작성하여야 합니다. 데이터를 담는 클래스인만큼 주 생성자에 1개 이상의 필드가 존재해야 합니다.

data class User(
    val id: Int, 
    var name: String
)

fun main() {
    val user = User(1, "Nirsa")

    println(user.id)      // user 객체의 id 값 호출
    println(user.name)    // user 객체의 name 값 호출

    user.name = "홍길동"   // user 객체의 name 값 변경
    println(user.name)    // 홍길동 출력
}

데이터 클래스는 equals(), hashCode(), toString(), copy(), componentN()과 같은 메서드를 자동으로 생성되어 지원해주며 val(불변), var(가변)만 주의하여 사용하시면 됩니다.

위의 예시 코드에서 생성된 id 필드의 경우 val 이므로 불변이기 때문에 읽기 전용이며, name 필드의 경우 var 이므로 가변이기 때문에 읽기/쓰기가 모두 가능한 상태가 됩니다. 이러한 특성으로 인해 data class는 DTO에서 많이 사용됩니다.

만약 data class에 메서드를 작성해야 할 경우 뒤에 { } 블록을 열어서 메서드를 작성해주시면 됩니다.

data class User(
    val id: Int, 
    var name: String
) { 
    // 메서드 생성 블록
    fun introduce() {
        println("Hello, my name is $name and my id is $id")
    }
}

만약, 정적으로 사용하고 싶다면 companion object를 사용하여 자바의 static처럼 객체를 생성하지 않고 클래스명.메서드명() 으로 호출이 가능합니다.

data class User(
    val id: Int, 
    var name: String
) { 
    // 정적 멤버 정의
    companion object {
        // 문자열 파싱해서 User 생성
        fun parse(input: String): User {
            val (id, name) = input.split(",")
            return User(id.toInt(), name)
        }
    }
}

 

2. object class

object class는 단 하나의 인스턴스만 생성하는 싱글턴 객체이며 자바의 static class + 싱글턴과 유사합니다. 일반적으로 개발을 할 때 상수 정의 클래스(Constants)에서 많이 사용됩니다.

아래는 저가 사이드 프로젝트에서 사용하는 코드 중 일부입니다. 상수들의 모음(Constatns)의 경우 단 하나의 인스턴스(싱글턴)임을 보장받아야 하므로 object class를 사용한 것을 볼 수 있습니다.

object JwtConstants {
    const val REFRESH_PREFIX = "refresh:"
    const val BLACKLIST_PREFIX = "blacklist:"

    const val ACCESS_EXPIRATION_MS = 15 * 60 * 1000L 
    const val REFRESH_EXPIRATION_MS = 1000 * 60 * 60 * 24 * 7L 
    const val ACCESS_BLACKLIST_PREFIX = "blacklist:access:"  
}

또한 아래와 같이 object class의 객체를 conn1과 conn2로 담아 비교하였을 때 서로 동일한 인스턴스임을 확인해볼 수 있습니다.

package org.example

object DatabaseConnection {
    fun connect() = println("DB 연결")
}

fun main() {
    val conn1 = DatabaseConnection
    val conn2 = DatabaseConnection

    println(conn1 === conn2) // true → 동일 인스턴스
}
반응형