Spring Boot

[Spring Boot] Soft Delete 적용

Happy._. 2024. 6. 20. 22:12

Soft Delete

  • 논리적 삭제(물리적인 데이터는 DB에 그대로 유지)
  • 데이터 복구와 이력 추적 등에 용이
    • 실수로 삭제한 데이터를 복원해야 하는 경우
    • 데이터가 유지되어야 하는 경우

Hard Delete

  • 물리적 삭제(실제로 DB에서 데이터를 삭제)

Hard Delete & Soft Delete 쿼리문

-- 물리적 삭제(실제 DB에서 삭제)
DELETE FROM todo WHERE id = ?

-- 논리적 삭제(삭제 여부를 나타내는 컬럼 사용)
UPDATE todo SET is_deleted = true WHERE id = ?

 

Soft Delete를 적용하기 위해 Entity 클래스에 어노테이션을 다음과 같이 추가한다.

@Entity
@SQLRestriction("is_deleted = false") // org.hibernate.annotations.SQLRestriction
@SQLDelete(sql = "UPDATE todo SET is_deleted = true WHERE id = ?") // delete 쿼리 실행 시 update로 처리
class Todo private constructor(

    // ...

) : BaseEntity() {

    // ...

    @Column(name = "is_deleted")
    var isDeleted: Boolean = false

    // ...
}
  • @SQLRestriction: 특정 Entity를 조회하는 모든 쿼리에 Where 조건을 추가해주는 어노테이션
  • @SQLDelete: Repository의 Delete 메서드를 실행했을 때 대신 정의된 SQL 구문을 실행시켜주는 어노테이션

위와 같이 어노테이션을 추가 후 기존 삭제 요청 쿼리와 변경된 쿼리를 비교하면 다음과 같다.

-- 기존 쿼리
delete from todo where id=?

-- 어노테이션 적용으로 변경된 쿼리
UPDATE todo SET is_deleted = true WHERE id = ?

 

다음은 삭제 요청 시 Delete 대신 Update가 실행되는 결과 화면이다.

 

논리적 삭제가 적용되면서 데이터 조회 시 수행되는 쿼리도 다음과 같이 변경되었다.

-- 기존 쿼리
select t1_0.id,t1_0.completed,t1_0.content,t1_0.created_at,t1_0.is_deleted,t1_0.title,t1_0.user_id,t1_0.writer from todo t1_0 where t1_0.id=?

-- 어노테이션 적용으로 변경된 쿼리
select t1_0.id,t1_0.completed,t1_0.content,t1_0.created_at,t1_0.is_deleted,t1_0.title,t1_0.user_id,t1_0.writer from todo t1_0 where t1_0.id=? and (t1_0.is_deleted = false)

 

다음은 데이터 조회 결과 화면으로 DB에는 데이터가 존재하지만 어노테이션으로 조건을 추가했기 때문에 응답으로는 데이터가 존재하지 않는 것처럼 보이게 된다.