Soft delete

SexyWoong·2023년 11월 30일
1

spring

목록 보기
4/11

데이터를 삭제하는 방법에는 두가지 방법이 있다.

  • Hard delete : DB의 데이터를 삭제
  • Soft delete : 실제 DB의 데이터를 삭제하지 않고 deleted와 같은 컬럼을 true로 update

Hard delete의 경우 'Delete from member where id = 1'와 같은 쿼리를 날려서 데이터를 삭제하는것이고 Soft delete의 경우에는 'Update member set deleted = true where id = 1'을 통해 실제로 데이터를 삭제하지 않지만 deleted 컬럼을 true로 업데이트 해줌으로써 삭제되었다고 표시하는 것이다.

먼저 Soft delete를 왜 사용하는지에 대해서 알아보자.

Soft delete를 왜 사용하는가

  1. 데이터 복구 용이성
  • 실제로 데이터를 삭제하는것이 아니기 때문에 삭제되었음을 나타내는 컬럼의 값을 변경함으로써 복구가 가능하다.
  1. 데이터 무결성 유지
  • 데이터베이스에는 종종 서로 연관된 데이터가 존재한다. hard delete를 하게 되면 관련 데이터간의 무결성이 깨질 수 있다. soft delete는 이러한 문제를 방지한다.
  1. 역사적 데이터 유지
  • 분야에 따라 과거의 데이터가 중요한 의미를 갖는 경우가 있다. soft delete를 사용하면 필요할 때 과거의 데이터를 조회할 수 있다.
  • 개인적으로 데이터는 굉장히 중요하다고 생각하고 과거의 데이터를 유지하기 위함이 soft delete를 사용하는 가장 큰 목적이 아닐까하는 생각이 든다.
  1. 성능 개선
  • 대규모 데이터베이스에서 실제로 데이터를 삭제하는 것은 시간이 많이 걸리고 리소스를 많이 사용할 수 있다. 소프트 삭제는 단순히 플래그를 변경하는 것이므로, 성능에 덜 부담을 준다.

개인적인 의견이지만 Soft delete를 통해서 데이터를 삭제할때 update 쿼리를 사용하면 코드의 가독성이 떨어지고 직관적이지 못하는것같다.

Hibernate의 기능

JPA의 구현체인 Hibernate에는 2가지 기능이 존재한다.

  • @SQLDelete를 활용하여 삭제시 delete쿼리 대신 사용자 정의 쿼리가 실행
  • @Where를 활용하여 해당 엔티티를 조회할 경우 where조건을 추가해주는 기능
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Entity
@SQLDelete(sql = "UPDATE couple SET deleted = true, deleted_date = CURRENT_DATE, couple_status = 'BREAKUP' WHERE id = ? and version = ?")
@Where(clause = "deleted = false")
public class Couple extends BaseTimeEntity {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name = "boy_id")
    private Long boyId;

    @Column(name = "girl_id")
    private Long girlId;

    @Column(name = "meet_day")
    private LocalDate meetDay;

    @Column(name = "invitation_code")
    private String invitationCode;

    @Column(name = "temperature")
    private Float temperature;

    @Version
    private Long version;

    @Column(name = "deleted")
    private boolean deleted = Boolean.FALSE;

    @Column(name = "deleted_date")
    private LocalDate deletedDate;

    @Column(name = "couple_status")
    @Enumerated(value = EnumType.STRING)
    private CoupleStatus coupleStatus;

    @Column(name = "re_couple_requester_id")
    private Long reCoupleRequesterId;
}

위 코드는 우이삭 프로젝트의 couple엔티티의 일부이다.

delete flag

@Column(name = "deleted")
    private boolean deleted = Boolean.FALSE;

couple엔티티에서 삭제 여부를 나타내는 필드는 deleted로 하였고, couple엔티티를 생성하면 기본값은 FALSE이다. 이는 삭제되지 않은 상태를 나타낸다.

@SQLDelete

@SQLDelete(sql = "UPDATE couple SET deleted = true, deleted_date = CURRENT_DATE, couple_status = 'BREAKUP' WHERE id = ? and version = ?")

이다. 이는 엔티티를 삭제할 경우 위에 지정해준 쿼리가 날라가는것을 확인할 수 있다.
데이터를 삭제할 경우 실제 날라간 쿼리를 확인해보았다.

11-30 23:35:34 [http-nio-8080-exec-9] INFO  c.l.b.c.l.PrepareStatementInspector - sql=UPDATE couple SET deleted = true, deleted_date = CURRENT_DATE, couple_status = 'BREAKUP' WHERE id = ? and version = ? 

update쿼리가 날라간것을 로그에서 확인할 수 있다.

@Where

@Where(clause = "deleted = false")

couple 엔티티 관련해서 조회를 할 경우 select 구문 뒤에 where delete = false가 자동으로 추가되어 조회한다.
이는 soft delete되지 않은 데이터들을 조회하는것을 의미한다.

profile
함께 있고 싶은 사람, 함께 일하고 싶은 개발자

0개의 댓글