1. cascade = CascadeType.REMOVE란?
CascadeType.REMOVE는 JPA에서 사용되는 영속성 관리 옵션 중 하나로, 엔티티 간의 관계에서 부모 엔티티가 삭제될 때, 자식 엔티티도 자동으로 삭제되도록 설정하는 방식이다. 쉽게 말해서 부모-자식 관계가 있는 경우, 부모가 삭제되면 자식도 함께 삭제되는 효과를 주는 옵션이다.
@Entity
public class Order {
@OneToMany(mappedBy = "order", cascade = CascadeType.REMOVE)
private List<OrderItem> orderItems;
// getters, setters, etc.
}
부모 엔티티가 Order이고 자식 엔티티가 OrderItem이라고 하자. Order에 CascadeType.REMOVE를 설정하면 Order가 삭제될 때 OrderItem도 함께 삭제된다.
2. CascadeType.REMOVE 사용하면 왜 위험한가?
1) 데이터 무결성 문제
CascadeType.REMOVE를 사용하면 자식 엔티티가 의도치 않게 삭제될 수 있다. 이는 데이터 무결성에 큰 문제를 일으킬 수 있다. 예를 들어, 자식 엔티티가 다른 곳에서도 참조되고 있을 경우, 이 자식 엔티티가 필요 이상으로 삭제될 수 있어 시스템의 다른 부분에서 오류가 발생할 수 있다.
2) 복잡한 엔티티 관계
실무에서는 엔티티 간의 관계가 매우 복잡한 경우가 많다. 부모-자식 관계가 단순하지 않고 여러 엔티티와 연결되어 있을 수 있는데, 이때 CascadeType.REMOVE를 사용하면 삭제 연산이 예상치 못한 엔티티들로 전파될 수 있다. 이는 복잡한 비즈니스 로직에서 예상치 못한 문제를 유발할 수 있다.
3) 성능 문제
삭제 연산이 일어날 때, JPA는 연관된 자식 엔티티들에 대해서도 삭제 처리를 진행한다. 엔티티가 많아질수록, 이 과정에서 성능 문제가 발생할 수 있다. 많은 양의 데이터가 관련되어 있다면, 하나의 삭제 연산이 여러 자식 엔티티들의 삭제를 트리거하기 때문에 성능 저하가 발생할 수 있다.
4) 예상치 못한 삭제 위험
실수로 부모 엔티티를 삭제하는 경우, 관련된 자식 엔티티들이 모두 삭제될 위험이 있다. 이를 되돌릴 수 있는 방법이 마땅하지 않기 때문에 매우 신중하게 다뤄야 한다. 실무에서 이런 실수는 치명적일 수 있다.
3. 그럼 언제 사용해야 할까?
CascadeType.REMOVE는 정말 부모-자식 관계가 명확하고, 부모가 삭제되면 자식도 함께 삭제되는 것이 무조건적으로 맞는 경우에만 사용해야 한다. 예를 들어, 부모 엔티티와 자식 엔티티가 완전하게 종속적인 관계일 때, 예를 들어 블로그 게시물과 댓글 같은 경우에는 사용할 수 있다.
그러나 이런 경우도 충분히 주의해야 한다. 자식 엔티티가 다른 엔티티에 의해 참조되거나 독립적으로 존재할 수 있는 상황에서는 절대 사용해서는 안 된다.
4. CascadeType.REMOVE 대신 사용할 수 있는 방법은?
CascadeType.REMOVE를 사용하지 않고, 삭제 로직을 명시적으로 처리하는 방법이 더 권장된다. 부모와 자식 엔티티의 삭제를 분리하여, 부모 엔티티를 삭제할 때 자식 엔티티의 상태를 따로 관리하는 것이 더 안전하다.
예를 들어, 부모 엔티티가 삭제될 때 자식 엔티티를 DELETE 쿼리로 명시적으로 삭제하거나, 비즈니스 로직에서 자식 엔티티들의 삭제 여부를 결정할 수 있다.
public void deleteOrder(Long orderId) {
Order order = orderRepository.findById(orderId).orElseThrow();
// 자식 엔티티를 명시적으로 삭제
orderItemRepository.deleteByOrder(order);
// 부모 엔티티 삭제
orderRepository.delete(order);
}
이 방법은 더 많은 코드가 필요할 수 있지만, 의도치 않은 데이터 삭제를 방지하고 비즈니스 로직을 더 명확하게 관리할 수 있다는 장점이 있다.
결론
CascadeType.REMOVE는 매우 주의 깊게 사용해야 하며, 실무에서는 가능한 명시적으로 삭제 로직을 처리하는 것이 권장된다. 데이터 무결성, 성능, 복잡한 관계 등을 고려할 때, 위험 요소가 많기 때문에 사용에 신중을 기할 필요가 있다.
'SPRING&BOOT > JPA' 카테고리의 다른 글
@Query 어노테이션 기본 설명 (0) | 2024.10.04 |
---|---|
중간 테이블을 사용하는 이유 (0) | 2024.09.02 |
JWT란? (0) | 2024.08.30 |
관계형 데이터베이스에서 중간 테이블의 중요성과 활용 방법 (0) | 2024.08.27 |
JPA 지연 로딩(Lazy Loading) (0) | 2024.08.27 |