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) 호출 시, 해당 유저의 스케줄도 자동 삭제!