Framework/Spring

[Spring] Hibernate @Where로 인한 논리 삭제 데이터 조회 문제 트러블 슈팅

leonie. 2025. 2. 8. 17:25

 

 

문제 상황

논리 삭제된 데이터가 조회되지 않음

 

Spring Boot와 JPA를 사용해 논리 삭제(Soft Delete) 기능을 구현하던 중 예상치 못한 이슈가 발생했습니다.

`isDeleted = true` 조건으로 논리 삭제된 데이터를 조회하려 했으나,

Hibernate의 `@Where` 애노테이션모든 조회 쿼리에 `isDeleted = false` 조건을 강제 적용하면서

원하는 데이터를 가져오지 못하는 상황이 발생했습니다.

 

SQL 로그 확인 결과

SELECT * FROM user u WHERE u.is_deleted = false;

쿼리를 `isDeleted = true` 조건으로 작성했음에도 `is_deleted = false` 조건이 추가되어 논리 삭제된 사용자를 조회할 수 없었습니다.

 

 

 

 

문제 원인 분석

이 문제는 Hibernate의 `@Where` 애노테이션JPQL의 기본 필터 조건 적용 방식의 충돌로 발생했습니다.

 

1️⃣ @Where 애노테이션

`@Where(clause = "is_deleted = false")`모든 JPQL 및 기본 조회 쿼리에 자동으로 적용됩니다.

`findAllByIsDeletedTrue()` 메서드에서도 `is_deleted = false` 조건이 우선 적용되어 원하는 데이터를 조회할 수 없습니다.

2️⃣ Boolean 필드 매핑 이슈

Boolean 타입 필드가 데이터베이스의 `TINYINT(0, 1)`로 매핑되며 필터링 조건이 부정확하게 적용될 수 있습니다.

 

 

 


 

 

 

해결 방법

1️⃣ Native Query 사용

`@Where` 애노테이션이 모든 JPQL 조회에 기본 필터를 적용하기 때문에,

특정 상황에서는 `isDeleted = true` 조건으로 논리 삭제된 데이터를 조회하는 데 어려움이 발생합니다.

 

이때 Native SQL Query를 사용하면 `@Where` 필터 조건을 우회하여 정확한 데이터를 조회할 수 있습니다.

 

 

(1) Repository 클래스 수정

// 삭제 요청된 사용자 조회
@Query(value = "SELECT * FROM user WHERE is_deleted = true", nativeQuery = true)
List<User> findAllByIsDeletedTrue();

 

 

 

2️⃣ UserService 코드 수정

UserService에서 findAllSoftDeletedUsers() 메서드를 호출해 DTO로 변환합니다.

 

 

(2) Service 클래스 수정

// 논리 삭제된 사용자 조회
public List<UserResponseDto> getDeletedUsers() {
    return userRepository.findAllByIsDeletedTrue().stream()
            .map(UserResponseDto::toDto)
            .toList();
}

 

 

 


 

 

 

Spring Boot와 Hibernate의 논리 삭제 기능을 구현할 때,

`@Where` 애노테이션과 JPQL 필터 조건 충돌을 주의해야 합니다.

 

일반 조회에는 @Where로 필터링을 유지하고,

논리 삭제된 데이터를 조회할 때는 Native Query를 사용해 조건을 명확히 지정하는 것이 가장 안전합니다.

 

이러한 트러블슈팅 경험을 통해 데이터 무결성을 유지하면서도 효율적으로 데이터를 관리할 수 있는 시스템을 설계할 수 있습니다.

 

 

 

728x90