원래는 백엔드 카테고리에 넣을려다가
그냥 Spring 카테고리로 넣게되었다
프로젝트를 진행하다가 멀티플랫폼 환경에서 개발을 하게 되었는데
공통로직을 작성하는 common 이라는 모듈이 존재한다.
이때 common에서 Request, Response를 위한 Domain(모델)을 작성하는데
문제가 하나 발생을 하였다.
// common/domain/User
@Serializable
data class User(
val id : Long,
val name : String,
val age : Int
)
// backend/domain/User
@Entity
@Data
public class User{
@Id
@GeneratedValue
Long id;
String name;
int age;
}
위에 코드가 존재한다고 할때
저는 처음에 당연히 공통로직에 포함되있는 User를 상속을 하거나 끌어다 써서
JPA를 사용해 DB에 반영을 하려고 했습니다.
하지만 상속을 받자니 각각의 프로퍼티에 어노테이션 처리를 못해줄 뿐만 아니라
필요없는 어노테이션까지 상속이 되는 문제가 생기고
그대로 common에 있는 User를 쓰자니 Entity로 등록이 안되있어 JPA로 관리를 못해주게 되는 문제가 발생하였습니다.
그렇다고 common에 있는 User에 @Entity
처리를 하자니 다른플랫폼에서 사용할때 쓸모없는 기능이 확장이 되어버려 매핑이 안되고....
그래서 구글링을 엄청나게 하다가 발견한 사실인데
위와 같은 상황이 발생한 이유는 바로 제가 DTO랑 Entity랑 동일시 하고있어서 발생한 문제였습니다.
저는 지금까지 당연히 Model을 정의하게 되면 Model이 DTO 역할까지 동시에 하는줄 알았는데
잘못알았던것같습니다.
자 그러면 이런현상을 어떻게 해결해야하고
그 기술이 어떤것인지 한번 공부해보려고 합니다.
Entity란?
DTO란?
자 이렇게 Entity와 DTO의 정의를 보고 나니까
제가 잘못 이해했단것이 한번더 깨닫게 되었습니다!
둘의 역할부터가 다른데
Entity는 DB 테이블과 1대1로 대응 되는 객체이고
DTO는 계층간 교환을 위해 순수한 데이터 객체입니다.
제가 깨달은것이 바로 관심사의 분리 라고 합니다!!
왜 분리를 해야하는가?
Entity의 값이 변하면 Repository 클래스의 Entity Manager의 flush가 호출될 때 DB에 값이 반영되고, 이는 다른 로직들에도 영향 미친다.
View와 통신하면서 필연적으로 데이터의 변경이 많은 DTO클래스를 분리해주어야 한다.
도메인 설계가 아무리 잘 되있다 해도 Getter만을 이용해서 원하는 데이터를 표시하기 어려운 경우가 발생할 수 있는데, 이 경우에 Entity와 DTO가 분리되어 있지 않다면 Entity안에 Presentation을 위한 필드나 로직이 추가되게 되어 객체 설계를 망가뜨리게 된다. 때문에 이런 경우에는 분리한 DTO에 Presentation로직 정도를 추가해서 사용하고, Entity에는 추가하지 않아서 도메인 모델링을 깨뜨리지 않는다.
관심사의분리가 가장 중요한 내용인것같아서 자세히 설명을 하였습니다.
해결방안은 되게 심플하다.
제가 그냥 Entity와 DTO를 헷갈렸기 때문에 일어난 불참사라서
common/domain/User
: DTO이기 때문에 Request, Response 처리할때 사용을 해주면 되고backend/domain/User
: 실제 DB와 상호작용을 할때는 Entity객체를 사용을 하면 됩니다!공부하고 나니 제가 바보같이 느껴지네여
가장 기초적인걸 몰랐다니....
그래도 바보같은 삽질로
공통모듈에 대한 공부를 조금이나마 한게 위로가 됩니다.
https://velog.io/@syi9595/Entity-DTO%EB%8A%94-%EC%99%9C-%EB%B6%84%EB%A6%AC%ED%95%A0%EA%B9%8C