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 삭제 순서 조절 필요 |
반응형
'IT > Spring' 카테고리의 다른 글
Spring Boot에서 @Valid와 @ExceptionHandler로 유효성 검사 에러 처리 (2) | 2025.08.05 |
---|---|
Spring Data JPA 페이지네이션(Pagination) 처리 (1) | 2025.07.30 |
스프링 어노테이션 (0) | 2025.07.15 |
HikariCP (1) | 2025.07.12 |
RestTemplate WebClient RestClient (2) | 2025.01.23 |