인프런 커뮤니티 질문&답변

dionisos198님의 프로필 이미지
dionisos198

작성한 질문수

자바 ORM 표준 JPA 프로그래밍 - 기본편

영속성 전이(CASCADE)와 고아 객체

어떤 경우 cascade 를 적용해도 되는지 이해가 되지 않습니다.

작성

·

302

0


[질문 템플릿]
1. 강의 내용과 관련된 질문인가요? (예
2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예
3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예
[질문 내용]
스프링 cascade 활용도 측면에서 궁금한 것이 있습니다. 영한님 - 인프런 (inflearn.com)

이 질문을 남겼었던 수강생입니다!

잠깐 상황을 요약하면

Program 과 Review 그리고 User 가 다대 1 1대 다

로 묶여 있는 상황입니다. program 에서 program.addReview 메서드를 활용하기 위해 cascade type 을 적용하였었습니다.

하지만 영한 님은 이부분의 코드는 별로 좋은 코드가 아니다!

cascade 옵션 질문 - 인프런 (inflearn.com)

를 참고해서 보아라.

 

라고 하셨습니다.

위 질문의 요약은 강의에서 Order 는 OrderItem 을 개인 소유 하나, Order 와 Delivery 는 Delivery 가 여러 곳에서 참조할 수 있으므로 개인 소유 하지 않는다. 라고 읽었습니다. 참조 하는 것과 Cascade Type .all 이 무슨 관계가 있는지 모르겠습니다.

 

6줄요약하면:

 

Delivery 와 Review 는 여러 곳에서 참조할 수 있으므로 CascadeType all 을 붙이지 말라고 하신 것 같은데

여러 곳에서 참조가능성이 있으면 CascadeType all 을 왜 붙이지 말아야 하는지 궁금합니다.

단순히 계속 코드를 보며 추적해야 하는 것 때문인가요??

이 부분이 와닿지 않습니다. 혹시 실제 예를 들어 설명해주실수 있나요??

 

 

 

답변 2

3

김영한님의 프로필 이미지
김영한
지식공유자

안녕하세요. dionisos198님

CascadeType.ALL을 사용할 때는 주의해야 합니다. 특히 여러 곳에서 참조되는 엔티티에 CascadeType.ALL을 적용하면 예상치 못한 문제가 발생할 수 있습니다.

예를 들어, Delivery 엔티티가 여러 Order 엔티티에서 참조된다고 가정해보겠습니다. 이때 Order와 Delivery 간에 CascadeType.ALL이 설정되어 있다면, 어떤 Order를 삭제할 때 해당 Order와 연관된 Delivery도 함께 삭제됩니다.

그런데 만약 삭제된 Delivery가 다른 Order에서도 참조되고 있었다면, 그 Order는 더 이상 유효하지 않은 Delivery를 참조하게 됩니다. 이는 데이터 무결성을 해치는 문제를 야기할 수 있습니다.

CascadeType.ALL은 편리하지만 남용하면 역효과를 낳을 수 있으므로, 실제 비즈니스 로직과 엔티티 간의 관계를 면밀히 분석한 후 신중하게 사용해야 합니다.

개인 소유의 경우에는 이런 문제가 발생하지 않기 때문에 사용하셔도 괜찮습니다.

감사합니다.

dionisos198님의 프로필 이미지
dionisos198
질문자

죄송하지만 아직 잘 이해가 가지 않습니다.

저는 이전 예제에서 멤버 <-> 리뷰 <-> 프로그램 (다대다의 중간테이블로 리뷰를 활용)

에서 멤버에서 리뷰에 대한 1대 다 CascadeType. all 을 설정한 경험이 있고 그 부분에 대해서 영한님은 프로그램에서도 참조될 수 있으므로 쓰지말라고 하셨었습니다. 개인 소유 또한 아니고요!

 


이 예제를 위에 영한님이 설명해주신 예시에 대입해보면

 

질문1) 멤버에서 리뷰에 대한 cascadeType .all 로 인해 멤버가 삭제되면 리뷰도 삭제된다. 그러면 프로그램은 더이상 유효하지 않은 리뷰를 참조하게 된다?? -> 이게 맞나요??

 

질문 2) 유효하지 않은 리뷰를 참조한다는게 무슨 말씀인가요?

어차피 DB에서 리뷰가 삭제되면 program 에서도 리뷰를 찾을 때 DB에서 조회해서 리뷰를 찾을 텐데 이러면 상관이 없는 것 아닌가요??

 

 

김영한님의 프로필 이미지
김영한
지식공유자

안녕하세요. dionisos198님

좀 더 쉽게 예시로 풀어서 설명을 드릴게요.

멤버를 삭제할 때 멤버가 작성한 모든 리뷰를 지우는 것이 맞고 비즈니스 상황에 문제가 없다면 cascade를 사용하셔도 괜찮습니다.

생각하신 것 처럼 멤버를 삭제하면 멤버와 연관된 모든 리뷰를 지워도, 어차피 이후에 프로그램에서 데이터베이스를 조회하면 프로그램에서 삭제된 리뷰를 조회하지 않을 것이기 때문입니다.

참고로 지금의 예는 리뷰가 중간 테이블이고, 리뷰가 프로그램의 PK를 참조하고 있습니다. 따라서 cascade를 사용하더라도 크게 문제가 되지 않습니다.

하지만 지금과 같은 단순한 상황이 아니라 이 리뷰라는 것을 다른 곳에서 참조하고 특히 다른 곳에서 리뷰의 PK 값을 가지고 사용하고 있다면 어떻게 될까요?

예를 들어서 고객의 정보를 삭제해도 해당 리뷰들이 남아있어야 하는 상황이라면 어떻게 될까요?

아마 해당 리뷰를 사용하는 여러 엔티티들에서 사라진 리뷰를 참조하게 될 것입니다

도움이 되셨길 바래요. 감사합니다.

0

안녕하세요, 인프런 AI 인턴입니다.

dionisos198님, 강의 내용과 관련된 부분에서 cascade 옵션의 사용에 대해 갖고 계신 궁금증을 잘 읽었습니다. 영한님의 답변과 관련해서, 제가 찾아본 김영한 강사님의 기존 답변들을 바탕으로 해결할 수 있을 것 같습니다.

Cascade 옵션의 주된 목적은 연관된 엔티티들에 대해 특정 엔티티의 생명 주기(lifecycle) 이벤트를 자동으로 전파하는 것입니다. CascadeType.ALL은 모든 생명 주기 이벤트(PERSIST, REMOVE, REFRESH, MERGE, DETACH)가 전파된다는 의미입니다.

예를 들어, 엔티티 A에 CascadeType.ALL을 설정하고 엔티티 A가 엔티티 B를 참조하는 경우, 엔티티 A를 persist할 때 자동으로 엔티티 B도 persist됩니다. 마찬가지로, 엔티티 A를 삭제할 때 B도 자동으로 삭제됩니다.

실제로 김영한 강사님은 cascade를 사용하는 일반적인 기준으로, 완전한 개인 소유가 되는 경우에 한해 이를 권장하고 있습니다. 즉, 해당 엔티티가 다른 어떤 엔티티와도 공유되지 않고 오직 한 엔티티에만 의존하는 경우에 cascade 옵션을 사용하는 것이 적절하다는 겁니다.

링크된 답변 URL에서 강사님은 다음과 같이 조언하셨습니다:

cascade 옵션 질문” - 복잡한 도메인 모델에서 cascade 옵션을 맹목적으로 사용할 경우 예상치 못한 사이드 이펙트가 발생할 수 있습니다. 단일 소유 관계가 아닌 다른 곳에서도 참조될 수 있는 엔티티에는 특히 주의가 필요합니다.

다른 곳에서 참조될 가능성이 있는 엔티티를 skip하는 이유는, 일방적인 생명 주기 관리로 인해 데이터의 일관성을 해칠 수 있기 때문입니다. 예를 들어, Delivery가 여러 Order에 참조될 경우, 한 Order 객체의 상태 변화가 Delivery 객체에도 영향을 미치고 이는 다른 Order와 연관된 문제를 일으킬 수 있습니다.

해당 이슈가 왜 문제가 되는지 더 깊이 이해하고 싶으시면, 실제 서버 어플리케이션에서 데이터를 어떻게 관리하고, 엔티티 간의 상태 변화가 전파될 때 어떤 문제가 발생할 수 있는지에 대한 추가적인 예시나 사례를 고려해 보시면 좋을 것 같습니다.

저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다.
현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏
추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.

dionisos198님의 프로필 이미지
dionisos198

작성한 질문수

질문하기