사이드 프로젝트 리펙토링(5) - 왜 Cascade를 쓰는지 알고 사용하자

김정훈·2024년 7월 18일
0

계기

이제까지 무분별하게 Cascade 설정을 해왔는데 리펙토링을 하며 Cascade를 할 때 객체의 설계 방식에 맞게 설정해줘야 한다는 것을 깨닫게 되어 포스팅 하게 됐습니다.

설명

Member : 사이트의 회원
SummonerInfo : 게임 플레이어 정보
Match : 경기 정보
Member는 회원의 아아디, 비밀번호 등의 회원정보를 관리하는 객체, SummonerInfo는 회원이 생성한 게임 플레이어이며 전적 통계등을 관리하는 객체, Match는 Summoner가 플레이한 경기의 정보이다.

Member : SummonerInfo

다대일 관계이다. 하지만 SummonerInfo는 Member를 참조할 일이 없고, Summoner를 검색하기만 해도 객체를 생성하기 때문에 Member에 필수적으로 의존하지 않아 단방향으로 설계했다.
Cascade 설정을 하지 않았다.

SummonerInfo : Match

일대다 관계이다. Match가 주인이지만 SummonerInfo를 생성하기 위해선 Match의 정보가 필요하기 때문에 SummonerInfo에서 연관관계 매핑을 한다.
SummonerInfo에 Cascade 설정을 하여 SummonerInfo와 Match의 무결성을 강화함.

CreateMember

createMember()는 1. Member 기본 정보 매핑 -> 2. SummonerInfo 기본 정보 매핑 -> 3. MatchList 생성 -> 4. MatchList를 통해 SummonerInfo에 경기 통계 정보 매핑 -> 5. Match와 SummonerInfo 연관관계 매핑 -> 6. Member에 SummonerInfo 매핑 순으로 진행된다.

원래 게획

Cascade

Cascade 설정을 하면 해당 엔티티의 작업을 연관 엔티티에 전파할 수 있다. cascadeType.ALL이라는 가정하에 SummonerInfo를 저장 하면 Match 역시 저장된다. 그렇기 때문에 Member에 Cascade 설정을 하여 Member.save() 한 번으로 Member.save -> Summoner.save -> Match.save가 가능하게 하려고 했다.

왜 Cascade 설정을 하지 않았나?

Member와 SummonerInfo는 단방향 관계

보통 Cascade는 ManyToOne 관계 중 One에서 사용한다. 왜냐하면 특정 Summoner와 관련된 Member들 중 하나에 의해 Summoner가 영향을 받으면 다른 Member에게 문제가 생기기 때문이다.
ex) cascadeType.REMOVE : Member.delete() -> Summoner.delete() -> 다른 Member의 Summoner 역시 delete()
하지만 우리는 Member만 SummonerInfo를 참조하는 단방향 관계이기 때문에 Cascade를 써야 한다면 Many인 Member에서 쓸 수 밖에 없다.

CreateSummonerInfo 메서드

만약 Member 측에서 SummonerInfo에 cascadeType.PERSIST, cascadeType.MERGE 설정을 하게 된다면 Member.save()를 할 때 SummonerInfo가 자동으로 save() 되기 때문에 CreateSummonerInfo()에 SummonerInfo.save()를 직접 작성할 필요가 없어진다.
하지만 CreateSummonerInfo()는 Member.Create() 때만 사용되는게 아니라 검색할 때도 정보를 저장하기 위해 사용되기 때문에 SummonerInfo.save()를 작성해야만 한다.

결론

Cascade가 편한 도구지만 그만큼 위험하기 때문에 자신이 설계한 구조에 따라 신중하게 설정해야 한다.
예를 들어 SummonerInfo의 주인이 Member 이외에 또 있는 경우에는 cascade를 더 신중하게 고려해야 한다. (즉 주인이 유일하지 않은 경우)
(주인 B에 의해 SummonerInfo이 delete된 경우 Member와 SummonerInfo의 일관성이 침해된다)

profile
백엔드 개발자

0개의 댓글