본문 바로가기

JAVA/JPA

JPA(1) - 도메인 설계

728x90

1. 관계

일대일, 일대다, 다대일 관계를 많이 사용한다.

 

그러나, 실무에서는 다대다 관계를 쓰면 안된다. => 다대다 관계면

중간 엔티티(매핑 테이블)를 만들고 일 대 다( 1:*), 다 대 일(*:1) 로  매핑하여 표현해야 한다.

 

 

Why? 다대다는 실무에 한계가 있다. 예를 들어 회원이 상품을 주문하면 연결 테이블에 회원 아이디와 상품 아이디만 담고 끝나지 않는다. 보통 주문 수량 칼럼이나 주문한 날짜 같은 칼럼이 더 필요하다. 이런 칼럼을 추가하면 더는 다대다(ManyToMany)를 사용할 수 없다. 왜냐하면 주문 엔티티나 상품 엔티티에 추가한 컬럼들을 매핑할 수 없기 때문이다. 즉, 중간 테이블에 값을 넣을 수 없기에, 결국 다대다를 일대다, 다대일 관계로 풀어야 한다.

 

2. 연관관계

가급적 양방향이 아닌 단방향으로 쓰는 게 좋다.

 

Why? 연관관계 주인도 정해야 하고, 로직도 잘 관리하기 때문에 양방향 매핑은 복잡하다. 장점이라곤 그래프 탐색 기능이 추가된 것뿐. 

 

만약 일대다, 다대일 양방향 관계면 연관관계의 주인을 정해야 하는데, 외래 키가 있는 엔티티를 연관관계의 주인으로 정하는 게 좋다. 

 

why? 연관관계 주인은 외래 키를 누가 관리하는지 문제. 비즈니스상 우위에 있다고 주인으로 정하면 안된다.

 

예시로 자전거와 바퀴가 있다면, 우위에 있다고 여겨지는 자전거를 주인으로 정하면, 자전거가 관리하지 않는 바퀴 테이블의 외래 키 값이 업데이트 되므로 관리와 유지보수가 어렵고, 별도의 업데이트 쿼리가 발생하는 성능 문제도 있다.

 

3. 엔티티 설계

(1) 실무에서는 가급적 Getter를 열어두고, Setter는 필요한 경우에만 사용하는 것을 추천.

 

why? Setter를 막 열어두면 왜 변경하는지 추적하기 점점 힘들다. 엔티티를 변경할 때는 Setter 대신에 변경 지점이 명확하도록 비즈니스 메서드를 별도로 제공해야 한다. (유지보수성이 확 올라감.)

 

(2) 모든 연관관계는 지연로딩으로 설정(★)

 - 즉시로딩(EAGER)은 예측이 어렵고, 어떤 SQL이 실행될지 추적하기 어렵다.

 - 실무에서 모든 연관관계는 지연로딩(LAZY)로 설정해야 한다.

 - 연관된 엔티티를 함께 DB에 조회하면, fetch join 또는 엔티티 그래프 기능 사용.

 - XToOne(OneToOne, ManyToOne)은 기본이 EAGER라서, FetchType을 LAZY로 바꿔야 한다.

 

(3) 컬렉션은 필드에서 초기화.

 - null 문제에서 안전해짐.

 - 필드레벨에서 생성하는 것이 가장 안전하고, 코드도 간결하다.

 

728x90