지침


연관관계 보다는 필드 참조 방식을 채택하는 것을 전제로 깔고간다.

<aside>

생명주기가 완전히 같은 경우에는 연관관계를 활용하는 걸 고민한다.

고민후,

<aside>

  1. 단방향 ManyToOne 건다.

    ⇒ 여기서 생명주기는 리뷰에 대해서 이미지가 무조건 있어야하나? 와 같은 관점

  2. OneToOne 은 다음 조건을 고려한다.

    주종관계가 명확할 때만 JPA 지연로딩과 편의성을 위해 단방향으로 사용하자.

    ⇒ 단방향을 쓸 땐, join이 빈번해 fetch join으로 최적화 되는지 체크한다.

    ⇒ 양방향이 꼭 필요하다면, 본래 주인 테이블의 PK를 필드로 참조하는 방식을 고려한다.

</aside>

실무에서도 서비스가 확장되고 연관관계가 늘어남으로써 증가하는 외래키에 대한 유지보수와 로직의 복잡성이 늘어난다고 한다. 처음부터 보수적으로 연관관계를 접근하면 느슨하게 관계를 설정할 수 있고, 필요한 경우 확장은 상대적으로 쉽다.

class Review {
		private Long id;
		private Long userId;
		private String content;
}

class ReviewImage {
		private Long id;
		private Long reviewId;
		...
}

Why?


엔티티는 개념, 의미 단위로 순수하게 존재하는 것이 좋다.

<aside>

class Review {
		private Long id;
		private Long userId;
		private String content;
		private List<ReviewTag> tags;
		private List<ReviewImage> images;
}

enum class ReviewTag {
		AAA, BBB, CCC, DDD
}

class ReviewImage {
		private int imageOrder;
		private String imageUrl;
}

</aside>

양방향 매핑으로 인한 순환참조 발생

<aside>

순환 참조는 두 개 이상의 객체나 컴포넌트가 서로를 참조함으로써 의존 관계에 사이클이 생기는 상황을 의미합니다. 예를 들어, 객체 A가 객체 B를 참조하고, 객체 B가 객체 A를 참조하는 양방향 참조는 대표적인 순환 참조의 예입니다.

JPA 양방향 관계는 순환 참조입니다. 순환 참조가 발생하다는 것은 서로에게 강하게 의존한다는 의미입니다. 사실상 하나의 컴포넌트라는 의미이며, 책임이 제대로 구분돼 있지 않다는 의미입니다. 또한 로직에 따라 무한 루프가 발생할 가능성이 높아집니다.

결과적으로, 순환 참조가 있으면 어떤 객체에 접근할 수 있는 접근 경로가 너무 많아집니다.

‘접근 경로가 많다’라는 말은 소프트웨어 설계에서는 그렇게 좋은 의미가 아닙니다. 경로가 많다는 것은 의존 관계가 복잡하게 얽혀 있다는 의미이기 때문입니다. 이는 어떤 객체를 수정할 때 개발자들이 만들어낸 온갖 접근 경로를 모두 고려해야만 한다는 뜻입니다. 따라서 접근 경로가 많아진다는 것은 복잡도가 높아지는 원인이 됩니다. 그러므로 가능한 한 도메인 모델들에 단일 진입점을 만들어서 필요한 객체가 있을 때 단방향으로 접근하도록 만드는 것이 좋습니다.

</aside>