Spring 7기 프로젝트/일정관리 프로젝트
Spring [트러블슈팅] 부모(User) 삭제 시 자식(Schedule) 엔티티 함께 삭제하기 (CascadeType.REMOVE, orphanRemoval)
JuNo_12
2025. 5. 21. 11:06
validation을 사용하여 dto에 여러 검증 기능을 넣어주었다.
그 후에 실행을 해주고, 유저 삭제 요청을 포스트맨으로 보냈는데, 에러가 났다.
그 에러를 해석해보니 오류 메시지는 "부모 행(=User)을 삭제·수정하려 했지만, 해당 user를 참조하는 자식 Schedule 레코드가 남아 있기 때문에 삭제/수정이 거부됐다"는 뜻이었다.
원인
- 데이터베이스에서 User를 삭제하려고 할 때
해당 사용자가 등록한 Schedule(일정)들이 DB에 남아 있어서,
schedule.user_id가 외래키(FK)로 User를 참조하고 있기 때문
해결 방법: JPA 연관관계에 Cascade 옵션 적용
User 엔티티에 아래처럼 수정이 필요
@OneToMany(mappedBy = "user", cascade = CascadeType.REMOVE, orphanRemoval = true)
private List<Schedule> schedules = new ArrayList<>();
1. @OneToMany(mappedBy = "user", ...)
- @OneToMany:
- 이 필드는 1:N 관계를 의미. 즉, 한 명의 유저(User)는 여러 개의 스케줄(Schedule)을 가질 수 있다는 뜻
- mappedBy = "user":
- 이는 양방향 관계에서 주 테이블이 아닌 쪽(즉, 외래 키를 가지지 않는 쪽)이라는 표시
- "user"는 Schedule 클래스 안에서 @ManyToOne 관계를 맺고 있는 필드 이름을 의미
@ManyToOne
private User user;
2. cascade = CascadeType.REMOVE
- User가 삭제될 때, 이 User가 가진 schedules도 함께 삭제되도록 한다.
- 즉, 연관된 Schedule 엔티티들도 자동으로 삭제됩니다. 수동으로 삭제하지 않아도 된다.
3. orphanRemoval = true
- schedules 리스트에서 어떤 Schedule 객체가 제거되면, 해당 Schedule도 DB에서 삭제된다.
- 즉, 부모 엔티티인 User와의 연관 관계가 끊어진 "고아 객체" 를 자동으로 제거하는 기능
이렇게 하면 User 삭제 시, 관련 Schedule들이 모두 자동 삭제된다.
DB도 ON DELETE CASCADE 없이 JPA가 알아서 처리한다.
정리
- User → Schedule OneToMany 관계에 Cascade.REMOVE, orphanRemoval = true 세팅
- User 삭제 시, 해당 Schedule이 모두 같이 삭제됨
- 컨트롤러·서비스 코드 변동 없다. 똑같이 @RequestBody 앞에 @Valid 넣어주면 된다.
- Schedule 엔티티의 @ManyToOne에는 cascade 옵션 넣지 말자! (ManyToOne에는 cascade 거의 쓰지 않는다.)
- 이제 UserRepository에서 deleteById(id) 또는 delete(user) 호출 시, 해당 유저의 스케줄도 자동 삭제!