Soft Delete

HEUKWU·2023년 11월 16일
0

지금껏 데이터 베이스에서 데이터를 삭제할 때는 항상 soft delete를 적용해 왔다.
그냥 간단하게 테이블에 deleted 컬럼을 추가하고 헤당 엔티티에 삭제하는 메서드를 따로 만들어서 deleted의 값을 true로 바꿔주는 방법을 사용했다.

@Entity
public class Post {
	//...
    
    private Boolean deleted = Boolean.FALSE;
    
    // 삭제 메서드
    public void delete() {
    	this.deleted = true;
    }
}
@Service
@RequiredArgsConstructor
public class PostService {

	private final PostRepository postRepository;

	@Transactional
	public void deletePost(Long postId) {
    	    Post post = postRepository.findByIdAndDeletedIsFalse(postId).orElseThrow(NotFoundPostException::new);
	        post.delete();
    }
}

이렇게 했을때 불편한 점이 있었는데 엔티티를 조회할 때 삭제 처리되지 않은 데이터들만 불러와야 해서 repository에 메서드를 따로 만들어야 했다.

public interface PostRepository extends JpaRepository<Post, Long>, CustomPostRepository {
    Optional<Post> findByIdAndDeletedIsFalse(Long postId);
}

그러다 검색을 통해서 새로운 방법을 알게 되었는데 바로 @SqlDelete와 @Where를 사용하는 방법이다.

@SqlDelete는 Hibernate에서 제공하는 어노테이션으로 soft delete를 쉽게 구현할 수 있다.

Hibernate는 엔티티 삭제에 'DELETE'쿼리를 사용하지만 @SqlDelete를 사용하면 사용자가 이 기본 설정을 변경할 수 있다.

@Entity
@SQLDelete(sql = "UPDATE post SET deleted=true WHERE id = ?")
public class Post {
	//...
}

'DELETE'쿼리 대신 'UPDATE'쿼리를 사용하도록 변경했다. 그리고 'deleted'컬럼을 'true'로 업데이트 하면서 soft delete를 쉽게 구현할 수 있다.

@Where 어노테이션 또한 Hibernate에서 제공하는 기능으로, 엔티티 조회에 조건을 추가할 수 있다.

@Entity
@SQLDelete(sql = "UPDATE post SET deleted=true WHERE id = ?")
@Where(clause = "deleted = false")
public class Post {
	//...
}

이렇게 하면 'deleted'컬럼이 'false'인 경우에만 조회하도록 할 수 있다.

아까 직접 메서드를 만들었을 때 불편한 점이 삭제 처리 되지 않은 엔티티를 조회하는 메서드를 따로 만들어야 하는 문제였는데 @Where 어노테이션을 쓰면 해결되는 문제였다.

그런데 혹시 무조건 @SqlDelete와 같이 써야만 @Where 어노테이션이 적용되는 것인가 싶어 확인을 해보았다.

@Where 어노테이션만 남긴채 원래 코드로 되돌리고 테스트를 해보았다.

@Entity
@Where(clause = "deleted = false")
public class Post {
	//...
    
    //삭제 메서드
    public void delete() {
        this.deleted = true;
    }
}
@Service
@RequiredArgsConstructor
public class PostService {

	private final PostRepository postRepository;
    
    @Transactional
    public void deletePost(Long postId) {
        Post post = postRepository.findById(postId).orElseThrow(IllegalArgumentException::new);
        post.delete();
    }
}

실험결과, 삭제 처리 되지 않은 데이터들만 알맞게 조회가 되었다.

그렇다면 @SqlDelete를 사용한 soft delete와 직접 삭제 메서드를 사용한 soft delete 두가지 방법이 있는건데 어떤 방법을 사용하는것이 더 나을까?

일단 나는 @SqlDelete를 사용해야 된다고 생각했다.
무엇보다 Hibernate에서 직접 지원하는 soft delete 기능이라는 것이 가장 큰 이유이고 Sql쿼리를 직접 수정할 수 있어서 유연성이 뛰어나다는 생각을 했다.

물론 실무에서 사용해야하는 상황이라면 생각해야 하는 것들이 훨씬 더 많을 것이다.

예를 들어서 삭제된 데이터들 즉, soft delete 처리된 데이터들만 따로 조회해야 하는 경우에는 @Where 어노테이션을 쓰면 안될 것이다.

따라서 실무에서는 프로젝트 특성, 비즈니스 특성, 개발자 팀원들의 선호도 등을 모두 따져서 더욱 신중히 선택해야 할 것이다.

참고 - https://www.baeldung.com/spring-jpa-soft-delete

0개의 댓글

관련 채용 정보