[4] 스프링 부트와 JPA 활용 (2) - 도메인 & 테이블 설계 / Entity 설계 순서 & 주의점

도메인 분석 설계
[ 목차 ]
[ 요구사항 분석 ]

- 기능에 필요한각 엔티티를 간략화된 그림으로 나타냄
- 기능 목록
- 회원 기능
- 상품 기능
- 주문 기능
- 기타 요구사항
- 상품은 재고관리가 필요
- 상품의 종류는 도서 / 음반 / 영화
- 상품을 카테고리로 구분할 수 있음
- 상품 주문시 배송 정보를 입력할 수 있음
[ 도메인 모델 설계 ]

Address는 임베디드 값 타입
OrderStatus는 Enum 타입으로 (ORDER / CANCEL) 을 가짐
DeliveryStatus는 Enum 타입으로 (READY / COMP) 를 가짐
Item은 (Album / Book / Movie)라는 자식 객체를 가진다 --> 상속관계
Category에 있는 parent와 child는 셀프 참조를 한다
[ 테이블 설계 ]

Item과 그 하위 Album / Book / Movie은 SINGLE_TALBE 전략으로 테이블 구성
Category와 Item은 N:M관계로 테이블로 분리됨
Entity와 구분을 위해 대문자로 작성했지만, 실제 개발에는 소문자+언더스코어(_) 스타일을 적용
Entity 설계
[ Entity 설계 순서 ]
Entity 생성 & Entity간 연관관계 설정
: 양방향 연관관계 설정시 연관관계 주인 설정
fetch strategy를 LAZY로 설정
: @ManyToOne / @OneToOne은 기본이 EAGER이니까 수동으로 지정해야함
영속성 전이 옵션 설정(CASCADE)
: 영속성 전이는 주로 양방향 연관관계에서 주 테이블에 해당하는 쪽에 작성함
- 연관관계 편의 메서드 작성
: 연관관계 주인과 상관 없이 자주 사용되는 주 테이블 기준으로 작성
[ Entity 설계 주의점 ]
Entity에는 가급적 Setter를 사용하지 X
Setter가 열려있으면 변경 포인트가 많아져서 유지보수가 어려움
-
Setter를 만들지 않거나 만들고 private으로 사용
모든 연관관계는 지연로딩(LAZY)으로 설정
N+1문제를 예방하기 위해 모든 연관관계를 LAZY로 설정
- 참조 객체 정보를
바로 조회해야 한다면 fetch join 사용
컬렉션은 필드에서 초기화 하자
List<>같은 컬렉션은 선언과 함께 초기화를 해주자
- 그래야
null문제에서 안전
Hibernate가 제공하는 내장 컬렉션으로 변경되어도 매커니즘이 꼬이지 X
(만약 new로 나중에 또 java컬렉션으로 바뀌면 로직에 문제가 생길 수 있음)
@ManyToMany는 절대 사용하지 X
- 절대 사용하지말고,
별도의 Entity를 생성해서 1:N / M:1 연관관계를 설정
값 타입은 항상 불변 객체로 만들자
값이 공유되는 일을 막기 위해 Setter를 제거해야 한다
값이 변경된다면 new 키워드를 통해 새로 생성하면서 일부 값을 변경 해야 함
기본 생성자를 반드시 꼭 만들어주자 (public 보다는 protected로!)
--> JPA 구현 라이브러리가 객체를 생성할 때 리플렉션 같은 기술을 사용할 수 있도록 있어야 하기 때문