본문 바로가기
Back-End/도메인 주도 개발 시작하기

[DDD] 도메인 주도 개발 시작하기_Ch4

by ChaSso 2023. 3. 17.

Chapter 4 리포지터리와 모델 구현

4.1 JPA를 이용한 리포지터리 구현

∘ 자바의 ORM 표준인 JPA를 이용해서 리포지터리와 애그리거트를 구현하는 방법

 

4.1.1 모듈 위치

∘ 리포지터리 인터페이스는 애그리거트와 같이 도메인 영역에 속함

∘ 리포지터리를 구현한 클래스는 인프라스트럭처 영역에 속함

 

4.1.2 리포지터리 기본 기능 구현

∘ 리포지터리가 제공하는 기본 기능

  - ID로 애그리거트 조회하기 : findBy프로퍼티이름(프로퍼티 값)

  - 애그리거트 저장하기 : save()

∘ JPA는 트랙잭션 범위에서 변경한 데이터를 자동으로 DB에 반영

∘ 애그리거트를 삭제하는 기능을 만들 수 있음

 

4.2 스프링 데이터 JPA를 이용한 리포지터리 구현

∘ 스프링 데이터 JPA는 지정한 규칙에 맞게 리포지터리 인터페이스를 정의하면 리포지터리를 구현한 객체를 자동으로 만∘ 들어 스프링 빈으로 등록함 (다음 규칙을 따르는 인터페이스)

  - org.srpingframework.data.repository.Repository<T,ID> 인터페이스 상속

  - T는 엔티티 타입을 지정하고 ID는 식별자 타입을 지정

 

∘ 스프링 데이터 JPA 규칙에 맞는 메서드

  - 리포지터리를 기준으로 저장하는 메서드

  - 특정 프로퍼티를 이용해서 엔티티 조회

  - 중첩 프로퍼티

 

4.3 매핑 구현

4.3.1 엔티티와 밸류 기본 매핑 구현

∘ 애그리거트 루트는 엔티티이므로 @Entity로 매핑 설정

∘ 한 테이블에 엔티티와 밸류 데이터가 같이 있으면 밸류는 @Embeddable, 밸류 타입 프로퍼티는 @Embedded로 매핑 설정

∘ @AttributeOverride 애너테이션으로 칼럼 이름 변경

 

4.3.2 기본 생성자

∘ 엔티티와 밸류의 생성자는 객체를 생성할 때 필요한 것을 전달받음

∘ JPA에서 @Entity@Embeddable로 클래스를 매핑하려면 기본 생성자를 제공해야 함

∘ 기본 생성자는 JPA 프로바이더가 객체를 생성할 때만 사용

 

4.3.3 필드 접근 방식 사용

∘ set 메서드는 내부 데이터를 외부에서 변경할 수 있게 하므로 캡슐화를 깰 위험이 있음

∘ 객체가 제공할 기능 중심으로 엔티티를 구현하도록 만들려면 JPA 매핑 처리를 프로퍼티 방식이 아닌 필드 방식으로 선택∘ 해서 불필요한 get/set 메서드를 구현하지 말아야 함

 

4.3.4 AttributeComverter를 이용한 밸류 매핑 처리

∘ 두 개 이상의 프로퍼티를 가진 밸류 타입을 한 개 칼럼에 매핑 할 때 AttributeConverter 사용

∘ convertToDatabaseColumn() : 밸류 타입을 DB 칼럼 값으로 변환

∘ convertToEntityAttribute() : DB 칼럽 값을 밸류로 변환

∘ AttributeConverter 인터페이스를 구현한 클래스는 @Converter 애너테이션 표시

 

4.3.5 밸류 컬렉션:별도 테이블 매핑

∘ 밸류 컬렉션을 별도 테이블로 매핑할 때는 @ElementCollection, @CollectionTable을 사용

 

4.3.6 밸류 컬렉션:한 개 칼럼 매핑

∘ 밸류 컬렉션을 별도 테이블이 아닌 한 개 칼럼에 저장해야 할 때 AttributeConverter를 이용

∘ AttributeConverter를 사용하려면 밸류 컬렉션을 표현하는 새로운 밸류 타입을 추가해야 함

 

4.3.7 밸류를 이용한 ID 매핑

∘ 밸류 타입을 식별자로 매핑하면 @Id 대신 @EmbeddedId 애너테이션 사용

 

4.3.8 별도 테이블에 저장하는 밸류 매핑

∘ 애그리거트에서 루트 엔티티를 뺀 나머지 구성요소는 대부분 밸류

∘ 애그리거트에 속한 객체가 고유 식별자를 갖는지를 확인해서 밸류인지 엔티티인지 구분

∘ 매핑되는 테이블의 식별자를 애그리거트 구성요소의 식별자와 혼동하면 안 됨

 

4.3.9 밸류 컬렉션을 @Entity로 매핑하기

∘ 개념적으로 밸류이지만 @Entity로 매핑해야 될 때 있음

∘ JPA@Embeddable 타입의 클래스 상속 매핑을 지원하지 않으므로 상속 구조를 갖는 밸류 타입을 사용하려면 @Entity를 이용해서 상속 매핑으로 처리해야 함

 

4.3.10 ID 참조와 조인 테이블을 이용한 단방향 M-N 매핑

∘ 애그리거트 간 집합 연관을 사용해야 한다면 ID 참조를 이용한 단방향 집합 연관 적용할 수 있음

 

4.4 애그리거트 로딩 전략

∘ 애그리거트 루트를 로딩하면 루트에 속한 모든 객체가 완전한 상태여야 함

∘ 조회 시점에 애그리거트를 완전한 상태가 되도록 하려면 애그리거트 루트에서 연관 매핑의 조회 방식을 즉시 로딩으로 설정

∘ 컬렉션에 대한 로딩 전략을 FechType.EAGER로 설정하면 즉시 로딩 방식이 문제가 될 수 있음

∘ 일반적인 애플리ㅔ이션은 조회 기능 실행 빈도가 높으므로 상태 변경을 위한 지연 로딩으로 인한 실행 속도 저하는 큰 문제가 아님 -> 애그리거트 내의 모든 연관을 즉시 로딩으로 설정할 필요 없음

 

4.5 애그리거트의 영속성 전파

∘ 애그리거트는 저장하거나 삭제할 때도 하나로 처리되어야 함

 

4.6 식별자 생성 기능

∘ 식별자 생성 방식

  - 사용자가 직접 생성 ex. 이메일

  - 도메인 로직으로 생성

  - DB를 이용한 일련번호 사용

 

∘ DB 자동 증가 칼럼을 식별자로 사용할 때 식별자 매핑에서 @GeneratedValue 사용

∘ JPA의 식별자 생성 기능을 사용하면 저장 시점에 식별자 생성됨

 

4.7 도메인 구현과 DIP

∘ 완전히 순순한 도메인 모델을 만드는 것보다 특정 기술에 적당히 의존하는 도메인 모델을 만드는 것이 바람직함