JPA에서 Soft Delete 구현하기

sojukang·2022년 7월 29일
0
post-custom-banner

Soft Delete란?

우리가 사용하는 서비스에서 특정 데이터를 삭제하고 싶습니다. 그런데 이 데이터를 완전히 삭제하는 게 아니라 DB에는 삭제됨이나 활상화 상태를 플래그로 남겨두고 외부에는 데이터를 지운 척 하여 삭제를 구현할 수도 있습니다. 이를 Soft Delete라고 합니다.

예시

잘못하여 계정 삭제를 했을 경우, 어떻게 복구할 수 있을까요? 실제 DB에서 삭제하고 백업된 DB에서 복구할 수도 있겠지만, Soft Delete를 활용하여 지운 척 DB에 남겨두었다가 상태를 바꾸어 손쉽게 다시 복구할 수 있습니다.

JPA가 제공하는 Soft Delete

우리는 Soft Delete 플래그를 위해 isActive라는 필드를 선언해주었습니다.

@Column(nullable = false)
private final boolean isActive = true;

JPA(Hibernate)에서는 @SQLDelete@Where의 조합을 통하여 Repository, Service등 다른 코드의 수정 없이 Entity에 관련 코드를 추가만 하여 Soft Delete를 쉽게 구현할 수 있습니다.

@SQLDelete(sql = "UPDATE table_name SET is_active = false WHERE id=?")
@Where(clause = "is_active=true")

@SQLDelete는 JPA 상에서 Entity를 삭제할 때 데이터를 완전히 삭제하지 않고 정의한 Update 쿼리를 실행하여 Soft Delete를 수행합니다.
@Where는 엔티티를 조회할 때 항상 정의한 Where 조건을 붙이도록 합니다. 즉 is_active 속성의 값이 true인 경우에만 불러오도록 합니다.

위 코드만 추가해주면 다른 계층에서는 일반적인 Delete를 하여도 Soft Delete로 동작하고, 일반적인 조회를 하여도 의하여 삭제되지 않은 상태에서만 조회할 수 있습니다.

이제 다른 객체에서 Soft Delete된 객체를 참조하려고 해도 영속화가 불가능하여 어플리케이션 수준에서는 Hard Delete 된 것과 동일하게 엔티티를 취급하게 됩니다. 억지로 가져올 수는 있으나 상대적으로 많은 코드 추가가 필요하여 한눈에 객체를 파악하기도 어려웠습니다.

위 방식의 한계

회고덕 팀은 구글 폼과 같은 회고 폼을 만들고 팀원들이 이 회고 폼에 참여하여 회고를 남겼을 때, 회고 폼 생성자가 회고 폼을 삭제하여도 팀원들이 작성한 회고는 개개인이 조회할 수 있도록 하기를 원했습니다.
그러나 회고는 회고 폼을 참조하고 있었기 때문에 회고 폼을 삭제할 경우 온전하게 회고를 조회할 수 없게 되는 문제가 있었습니다.

그래서 저희는 회고 폼 삭제를 Soft Delete로 구현하여 회고 폼과 연관된 회고들은 회고 폼의 정보들을 참조할 수 있고, 회고 폼의 조회는 불가능하도록 구현하였습니다.

직접 Soft Delete 구현

@Column(nullable = false)
private boolean isActive = true;

필드는 동일하게 선언 해주었지만

public void delete() {
        this.isActive = false;
    }

삭제 플래그의 상태를 변경하여 Dirty Checking을 통해 업데이트 해주는 방식을 사용했습니다.

@Query("select r from ReviewForm r where r.code = :code and r.isActive = true")
Optional<ReviewForm> findByCode(String code);

그리고 Spring Data JPA를 사용하여 JpaRepository를 상속한 Repository에 isActive 값이 true인 경우에만 조회하도록 Repository에 JPQL 쿼리를 정의해주었습니다.

이제 Soft Delete된 객체는 조회할 수 없지만 이미 참조 관계를 맺은 객체들에서는 정보를 조회할 수 있게 되었습니다.

참고

How to Implement a Soft Delete with Spring JPA

profile
기계공학과 개발어린이
post-custom-banner

0개의 댓글