-
도메인 모델에 kotlin의 data class가 적합할까?📖 개발 공부/kotlin 2023. 12. 10. 12:00
회사 프로젝트에서 비즈니스 로직이 담긴 도메인 모델을 만들 때 kotlin의 data class를 사용하고 있다.
언제 class를 사용하고, 또 언제 data class를 사용하는 게 적합한지 제대로 숙지하지 못하고 무분별하게 쓰고 있는 것 같아 이번 기회에 공부해보려고 한다!
코틀린의 공식 문서를 보자 👀Data classes in Kotlin are classes whose main purpose is to hold data.
데이터 클래스(Data class)는 데이터 보관 목적으로 만든 클래스를 말한다.
데이터 보관을 목적으로 만들었다라.. 뭔가 DTO의 역할을 말해주고 있는 것 같다. (데이터 전달)
도메인 모델은 데이터 보관 역할을 넘어서 비즈니스 로직을 구현하고 도메인의 행위를 정의하는 역할을 갖고 있어서, data class의 목적 이상의 목적을 갖고있는 듯하다 🧐
The compiler automatically derives the following members from all properties declared in the primary constructor: .equals()/hashCode() pair
data class는 equals와 hashCode를 자동으로 제공해준다. 단, 주생성자에 선언된 모든 프로퍼티를 기준으로
예시를 들어보겠당.
다음과 같은 데이터 클래스가 있다고 해보자data class Person( val id: Int, val name: String, var age: Int ) { fun updateAge(age: Int) { this.age = age } }
위의 클래스 기반으로, 두 객체를 비교하는 코드를 작성해보았다.val ayong1 = Person(id = 1, name = "문애용", age = 24) val ayong2 = Person(id = 1, name = "문애용", age = 24) println(ayong1 == ayong2)
기본 생성자의 프로퍼티인 id, name, age와의 값 비교를 할테니, 당연히 true가 나올 것이다.
그렇다면 다음은 어떨까?val ayong1 = Person(id = 1, name = "문애용", age = 24) val ayong2 = Person(id = 1, name = "문애용", age = 24) ayong2.updateAge(25) println(ayong1 == ayong2)
앞의 코드와 모두 같고, updateAge()라는 메서드를 호출하여 나이만 수정했을 뿐인데..
false가 출력된다.
의도한 동작과는 다르게 흘러간다.
age가 수정되어도 ayong1과 ayong2를 같은 객체로 간주하기 위해서는 equals, hashCode를 재정의해야한다.
ChatGPT에게 물어보니data class는 기본적으로 모든 프로퍼티를 포함한 equals와 hashCode, 그리고 toString 메서드를 자동으로 생성하도록 설계되었습니다. 이 기본 동작을 재정의하면 data class의 기본 목적과 다소 어긋나게 되며, 코드의 가독성과 유지보수성을 해칠 수 있습니다.
라고 한다.
data class는 도메인 객체의 동일성 판단 오류 가능성이 있어, class를 쓰는 것이 더 적합하다고 생각이 든다.
그래서 나는!
(AS-IS) 이렇게 작성했던 코드를data class Person( val id: Int, val name: String, var age: Int ) { fun updateAge(age: Int) { this.age = age } }
(TO-BE) 이렇게 equals, hashcode 를 재정의하여 바꿔보려고 한다.!!class Person( val id: Int, val name: String, var age: Int ) { override fun equals(other: Any?): Boolean { if (other == null) { return false } if (this::class != other::class) { return false } return id == (other as Person).id } override fun hashCode(): Int { return id.hashCode() } fun updateAge(age: Int) { this.age = age } }
이제 다음 코드도 true가 출력될 것이다!val ayong1 = Person(id = 1, name = "문애용", age = 24) val ayong2 = Person(id = 1, name = "문애용", age = 24) ayong2.updateAge(25) println(ayong1 == ayong2)
나의 결론은
data class는 주로 데이터 전달/보관에 적합하고, 복잡한 도메인 모델에는 일반 class가 더 적합하다고 생각한다.
위와 같은 동일성 판단 문제에 있어서도 그렇고 data class의 본래 목적과도 일치하지 않다고 생각해서이다. 도메인 모델은 단순 데이터 보관뿐 아니라 비즈니스 로직 구현을 위해서 더 풍부하게 쓰여질텐데, data class는 이 요구사항들을 충족시키기엔 한계가 있어보인다!
끝.반응형'📖 개발 공부 > kotlin' 카테고리의 다른 글
Spring AOP를 Kotlin으로 개선해보기! (feat. 카카오페이 테크블로그) (0) 2024.03.17 Kotest 예제와 함께 테스트 코드 살펴보기 (0) 2024.02.04 [Kotlin] @Synchronized 어노테이션 동작 방식 (0) 2023.08.03 [Kotlin] toBoolean(), toBooleanStrict() (0) 2023.07.26 [Kotlin] sortedBy와 sortedWith의 차이점 (0) 2023.04.09