IT/Spring

JPA에서 deleteAll() vs deleteAllInBatch()의 차이와 주의할 점

iamhyeon 2025. 7. 19. 16:32

Spring Data JPA를 사용하다 보면 전체 데이터를 삭제해야 할 때 deleteAll()과 deleteAllInBatch() 두 가지 메서드 중 무엇을 써야 할지 고민하게 된다

두 메서드는 이름만 보면 비슷해 보이지만, 동작 방식, 성능, 주의사항 모두 다르기 때문에 잘 구분해서 사용해야 한다

 

1️⃣ deleteAll() — 하나씩 순회하며 삭제

userRepository.deleteAll();
  • 내부적으로는 findAll()로 모든 데이터를 조회한 뒤,
  • for 루프로 한 건씩 EntityManager.remove() 호출
  • 즉, n개의 delete 쿼리가 실행된다

✅ 특징

  • JPA가 영속성 컨텍스트를 유지한 채 개별 엔티티를 추적
  • 엔티티 리스너, 연관된 Cascade, orphanRemoval 등 모두 동작

❗ 단점

  • 성능이 매우 떨어짐 (대량 삭제 시 n개의 DELETE 발생)
  • 영속성 컨텍스트에 부하가 큼 → OutOfMemory 가능성

 

2️⃣ deleteAllInBatch() — 한 줄로 삭제

userRepository.deleteAllInBatch();
  • 조회 없이 삭제하는 쿼리를 직접 실행
  • 내부적으로 QueryUtils.DELETE_ALL_QUERY_STRING 상수를 이용해 다음과 같은 SQL이 실행된다:
delete from user;
  • EntityManager.remove() 없이 직접 쿼리 실행 → 성능 우수

✅ 장점

  • 단 한 번의 쿼리로 모든 데이터 삭제
  • flush()를 자동으로 호출하므로 즉시 DB에 반영
  • 테스트 teardown 또는 초기화 스크립트 등에 매우 유용

❗ 주의할 점

  • 엔티티 리스너, Cascade 설정, orphanRemoval 등 동작 안함
  • 영속성 컨텍스트에 있는 객체와 불일치 발생 가능성
    → 따라서 deleteAllInBatch() 전에 flush() + clear() 또는 read-only 트랜잭션에서 사용 권장

 

📉 성능 비교

쿼리 수 n개 (DELETE FROM ... WHERE id=...) 1개 (DELETE FROM ...)
조회 여부 필요 (findAll()) 없음
성능 느림 매우 빠름
Cascade, 리스너 작동함 작동 안함
영속성 컨텍스트 동기화 유지 깨질 수 있음

 

 

✅ 언제 어떤 걸 써야 하는가

소량 데이터 삭제 deleteAll()
많은 데이터 삭제 deleteAllInBatch()
엔티티 리스너/Cascade 고려 deleteAll()
테스트 초기화, 마이그레이션 deleteAllInBatch()
연관 엔티티 FK 제약 존재 deleteAll() or 삭제 순서 조절 필요

 

반응형