강의

멘토링

로드맵

인프런 커뮤니티 질문&답변

HAHA님의 프로필 이미지
HAHA

작성한 질문수

멀티 모듈 아키텍처로 구현하는 은행 서버 핵심 기능 [ Kotlin & Spring ]

Entity & DTO 데이터 모델

jpa entity 질문

해결된 질문

작성

·

19

0

안녕하세요.

 

Entity 선언 시 data class vs class 질문드리려고 합니다.

아래 질문은 data class를 기반으로 했지만 사실 궁금증 시작은 "class가 엔티티에 더 맞지 않나?" 라는 생각에 질문드립니다.

 

질문 1. data class 선언시 프록시 질문

제가 알기로 ManyToOne lazy loading할 때 프록시 기능을 사용한다고 알고 있습니다.

data class가 자바 record와 마찬가지 final인 것으로 아는데 그렇다면 지연 로딩이 정상적으로 동작하지 않다고 생각됩니다.

혹시 여기서는 지연 로딩을 사용하지 않아서 data class를 사용하신 것인지 궁금합니다.

 

질문 2. data class 사용이 맞다면 equals & hashCode 질문

결궁 두 값 동일성을 비교할 때 id를 기반으로 하는 것이 성능에 좋을 것 같다고 생각됩니다.

혹시 실무에서 data class 나 class 사용하실 때 id기반으로 equals와 hashCode를 오버라이딩 하지 않고 전체 필드로 하시는지 궁금합니다.

 

질문 3. data class 목적

제가 알기로는 data class는 response와 같이 불변 데이터에 많이 쓰이는걸로 알고 있습니다.

그래서 copy와 같은 메서드를 제공하는 것으로 알고 있습니다.

data class를 사용할 때 물론 copy를 사용하시진 않겠지만 영속성 컨텍스트 같은 기능을 쓰려면 직접 변경해야 합니다.

불변 클래스 목적과 jpa entity와 잘 맞지 않는 것 같아서 질문드립니다.

 

질문 4. equlas 질문

만약 양방향 참조가 있는 entity라면 무한 루프에 빠질 가능성이 없는지 궁금합니다.

이와 같은 이유로 2번을 질문 드렸는데 질문 2번에서 내용이 빠진 것 같아서 따로 한 번 더 질문 드립니다.

 

제가 실무에서 써보지 않았고 코틀린 관련해서는 경험이 부족해서 잘못된 질문이 있다면 알려주시면 다시 질문 남기겠습니다.

 

좋은 강의 감사합니다.

감사합니다.

답변 1

1

Hong님의 프로필 이미지
Hong
지식공유자

안녕하세요 HAHA님 핵심을 잘 찌르는 질문 주셔서 감사합니다.

사실 이 주제는 저도 아니만 같이 강의를 만드시는 분들 입장에서도 꽤나 주제가 많이 갈리는 주제였습니다.

개발의 편의성이 중요하냐, 아니면 기본적인 규칙을 맞추는것이 중요하냐의 문제로 논쟁거리가 많았던 주제이기도 합니다. 하지만 상황에 따라서 조금 달라 질 수 있는 부분이 존재 할 꺼 같아요.

 

  1. data class 선언시 프록시 질문

맞습니다. 지연로딩이라는 것이 프록시를 통하고 불변 객체를 통해 구동이 된다면, 정상 동작하지 않을 수 있죠. 그래서 일반적인 class가 권장됩니다. 하지만 상황에 따라서 kotlin-allopen 플러그인을 사용한다면, @Entity가 붙은 객체를 open 상태로 변경해주는 기능도 동작 가능합니다. 이런 플러그인도 고려해 보시면 좋지 않을까 싶어요.

이 부분에서 많이 갈리는게, 프로젝트를 data class로만 구성하고 싶어하시는 분들이 많습니다. 저도 어느정도 공감하는 부분도 많아서... class나 data class냐는 꽤나 논쟁거리가 있는거 같아요.

 

  1. Data class 사용 시 equals & hashCode

이 부분도 질문해 주신 부분이 맞죠. 기본적인 id만을 비교 하는것이 성능과 안정성 면에서 좋습니다.

왜냐하면 Entity가 영속되지 않은 상태(transient)일 때나, 지연 로딩된 필드가 로드되지 않았을 때 전체 필드로 비교하면 오동작할 수 있다는 문제가 있기 떄문입니다.

그래서 class를 사용하는것이 더 유리하기도 합니다면.. data class를 사용하는 경우에 대해서는 오버라이딩 하는 표현식이 필요합니다.

  • 저는 그냥 이런 부분까지는 고려를 잘 안하는 스타일이라서... 그냥 작성을 하기는 했습니다.

data class User(@Id val id: Long, var name: String) {
    override fun equals(other: Any?): Boolean {
        if (this === other) return true
        if (javaClass != other?.javaClass) return false
        other as User
        return id == other.id
    }

    override fun hashCode(): Int = id.hashCode()
}

간단하게 작성해보았는데, 이런 형태이지 않을까 싶습니다.

 

  1. data class 목적

사실 저는 data class라는 표현을 사용하는것을 좋아해서 해당 형태로 모두 구현한 부분이기는 합니다. 당연하게도 정석적인 코어 레벨로 구현을 한다면, class가 좀 더 entity에 어울리는것은 사실이기도 하고요. 하지만 kotlin의 문법을 최대한 알려드리고 싶어서 data class로 모두 사용을 하였고, 일반적으로는 response에만 많이 사용하거나, 중간 DTO 모델 정도에만 많이 사용되는것이 data class의 사용처이죠

하지만 일부 Entity에도 사용 할 수 있어요. 누군가에게는 그렇게 권장하지 않는 형태라고도 할 수 있겠지만, 저는 그렇게 규격에 얽메이는 것을 싫어해서... 예를들면 val대신 var로 구성 함으로써 내부 변수를 수정 가능한 형태로 구성하는 것이죠.

 

  1. equlas 질문

말씀해 주신 부분이 맞죠. 예를들어 이런 형태가 있다고 가정해 볼게요.

class Team(
    val members: List<Member>
)

class Member(
    val team: Team
)

그러면 자동 생성된 함수들에 대해서는 양방향 참조가 발생 가능합니다.

그래서 이런 형태에서는 ID만을 통해 검증을 하던가, ToString.Exclude, @EqualsAndHashCode.Exclude 이라는 형태도 사용하기는 합니다. 이 부분도 알아가시면 좋은데, 이렇게 처리하는것은 사실 떔빵?? 한다는 느낌에 가까워서 기본적으로는 구현체 함수를 오버라이딩 하는것이 편하실 겁니다.

 

결론적으로 말씀드리자면, 전체적으로 class가 Entity에 더 맞지 않냐?? 라는 생각은 맞습니다. 틀린 생각은 아니에요. 개인적으로 data class가 더 편하다고 생각하여 구성을 하였고, JPA와 호환성을 위해서는 플러그인이나 추가적인 오버라이딩이 필요하죠.

 

그래서 만약 불변을 강조하거나 간단한 프로젝트 이 강의와 같이 간단한 형태라면, data class가 구현하기에는 더 편하실 겁니다. 하지만 뭔가 복잡한 관계가 주어지는 프로젝트라면 일반적인 class를 추천 드리고 싶어요. 이런 내용도 강의에 녹아 드렸어야 했는데, 너무 제가 제 스타일로만 알려드리고 작성한거 같아서 너무 부끄러워지는 주제였던거 같습니다. 이렇게 정성스럽게 질문 주셔서 너무 감사드립니다.

HAHA님의 프로필 이미지
HAHA
질문자

정성스럽게 답변해주셔서 정말 감사드립니다.

해당 내용 공부하면서 혼란스러웠던 부분도 많았는데, 이렇게 실제 경험을 바탕으로 자세히 설명해주셔서 큰 도움 됐습니다.

특히 프로젝트 특성과 목적에 맞게 선택하는게 좋다는 말씀에 깊이 공감했습니다.

바쁘신 와중에도 자세하게 답변해주셔서 진심으로 감사드립니다!

HAHA님의 프로필 이미지
HAHA

작성한 질문수

질문하기