CH04 리포지터리와 모델 구현
Last updated
Last updated
스프링 데이터 JPA 를 활용하지 않은 경우를 이야기하며 핵심 정리 포인트는 DIP 에서 살펴본 바와 같이 도메인 계층에 추상화된 리포지터리가 있고 인프라스트럭처 계층에서 이를 실제 구현해야한다는 것이다.(아래 그림 참고)
위 'JPA를 이용한 리포지터리 구현'에서 살펴본 바와 같이 모듈의 위치는 DDD 원칙을 그대로 따른다. 이 부분에서 책에서는 일반적으로 스프링 데이터 JPA 가 제공하는 메소드들의 시그니처와 기능에 대해서 살펴보았는데 스프링 데이터 JPA에 관한 일반적인 내용이므로 따로 정리하지 않는다.
애그리거트 내에서 엔티티와 밸류의 매핑을 어떻게 처리할 것인지 JPA 를 사용한다는 가정에서 여러 경우들에 대한 예시들을 살펴보았다. JPA 에서 제공해주는 여러 어노테이션(@Embbeded, @Embeddable, @ElementCollection, @CollectionTable, @SecondaryTable)으로 여러 경우를 소화해낼 수 있다. 각 케이스에 대한 정리는 JPA 기술에 관한 내용과도 같아서 따로 하지 않는다.
내가 기억해두면 좋을 내용들은 아래와 같다.
별도의 테이블을 사용한다고 해서 엔티티인 것은 아니다. 별도의 테이블을 사용해도 VALUE 로 구분될 수 있다. (똑같은 언급을 계속 하지만 높은 확률로 하나의 애그리거트는 하나의 엔티티를 가진다)
VALUE 이지만 @Entity 로 매핑해서 처리할 수 있다.(편의 목적 혹은 팀 표준 등의 이유)
그런데 VALUE 를 1번처럼 별도 테이블로 관리하되 ENTITY 로 만들지 않는 경우 성능상 문제가 있는 경우가 있다. 예를 들어서 1:N 관계에서 N의 정보 하나만 변경해도 모든 N을 삭제하고 다시 삽입하는 식으로 성능성 비효율이 발생한다.
그래서 개인적으로 VALUE 이지만 @Entity 로 설정해주고 관리해주되 Cascade 옵션을 잘 활용하는 방식이 더 좋을 것 같다. 따로 커스텀 어노테이션을 만들어서 VALUE 임을 명시적으로 드러내주는 것도 좋을 것 같다.
난 지금껏 VALUE 이지만 @Entity 로 설정하고 구현해왔는데, 이 방식을 그대로 사용하는 것이 좋겠다. 다만, 커스텀 어노테이션을 만들어서 루트 엔티티와 VALUE 를 분명히 구분해주면 좋을 것 같다. 결론적으로 나는 아래와 같은 방식을 취할 것이다.
VALUE 라고 해도 @Entity 로 관리한다.
커스텀 어노테이션을 만들어서 루트 엔티티와 VALUE 를 명시적으로 구분해준다.
@Entity 와 DDD 에서 말하는 Entity 를 구분해야 위의 개념들이 혼란스럽지 않다.
너무 당연한 이야기인데 당연히 애그리거트를 전체 로딩할 필요가 없다. 조회 시점에는 조회에 필요한 데이터만 맞게 다 가져오면 될 것이고 수정 역시 필요한 데이터만 로딩해오면 된다. 기본적으로 지연로딩을 적극 활용해서 성능을 높히는게 맞다. 이러한 맥락에서의 내용이어서 따로 정리는 하지 않는다.
애그리거트가 완전한 상태여야 한다는 것은 저장과 삭제에 한해서 인지하자. 조회 로직에 이 원칙을 적용하면 바로 위에서 본 '애그리거트 로딩 전략'의 내용을 참고하자.
애그리거트를 저장할 때에는 루트 엔티티만 저장해서는 안되고 완전한 애그리거트 전체(루트 엔티티를 포함한 모든 객체)를 저장해야한다.
애그리거트를 삭제할 때에도 마찬가지로 애그리거트에 속한 객체를 삭제해야한다. 말 그대로 완전한 애그리거트 전체를 삭제해야 하는 것이다.
Cascase 옵션을 적절하게 잘 활용해야한다.
앞에서 살펴 보았듯이 DIP를 사용하는 이유중 하나가 도메인 계층이 특정 기술에 의존하는 것을 막기 위함이다. 하지만 JPA 를 사용할 경우 도메인 계층에 생성되는 여러 객체(엔티티와 VALUE) 들이 JPA의 자원인 @Entity 를 비롯한 여러 어노테이션들을 사용하게 된다. 도메인 계층이 특정 기술인 JPA에 의존하게 되는 것이다.
하지만 JPA 로 시스템 전체를 구현해놨는데 JPA를 싹다 거둬내고 다른 것으로 갈아 탈 일이 현실적으로 없을 가능성이 크다. 그런데 원칙을 지키느라고 DIP를 완벽하게 지키고자 하면 개발 효율성이 크게 떨어질 것이다.
따라서 개발의 편의성과 실용성을 위해서 어느정도 이러한 부분은 타협하는 것이 좋을 것이며 책에서도 이러한 맥락으로 설명하고 있다.