글을 작성한 이유

Member Entity의 삭제처리(del_dt)를 SOFT_DELETE을 사용하여 처리할려고 합니다.

이때, 찾아보면 편리한 많은 기능들이 존재하는데 해당 기능들을 사용할려고했으나, 생각해보니 사용하지 않는것이 나을 것같다는 결론을 내린 과정들에 대해 정리해보려고 합니다. (물론, 제가 진행하는 프로젝트에 한해서입니다.)

 

 

SOFT_DELETE을 개발하려고 고민한 방안들

첫번째, @SQLDelete 를 통하여 DELETE 호출시 자동으로 SOFT_DELETE 처리

1. @SQLDelete 어노테이션 : JPA의 구현체인 Hibernate에서 제공하는 기능으로, Delete를 호출 시 자동으로 del_dt를 업데이트 시켜주는 어노테이션입니다.

@SQLDelete(sql = "UPDATE member SET del_dt = CURRENT_TIMESTAMP WHERE member_no=?")

적용예시로는, 

 

MemberEntity에 SQLDelete 어노테이션을 추가해주면 끝입니다.

@Entity
@SQLDelete(sql = "UPDATE member SET del_dt = CURRENT_TIMESTAMP WHERE member_no=?")
@Where(clause = "del_dt is null")
public class Member extends BaseEntity{

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

    @Column(length = 100, nullable = false, unique = true, name = "member_id")
    private String member_id;

    @Column(length = 100, nullable = false)
    private String member_password;

    @Column(length = 100, nullable = true)
    private String member_nickname;

    @Column(nullable = false)
    private boolean member_from_social;
    
    @Column(name = "del_dt")
    private LocalDateTime del_dt;

}

이렇게 적용시키면, Jpa를 extends 하고 있는 MemberRepository 의 기본메서드인 delete를 호출할시 자동으로 SQLDelete에 있는 쿼리문이 대신 실행됩니다.

public interface MemberRepository extends JpaRepository<Member, Long> {

}

위의 2개 코드만 작성하면 올바르게 작성이 됩니다.

 

두번째, @Where 를 통하여 DEL_DT 의 NULL 체크를 통하여 값 가져오기

Where 어노테이션 입니다.

@Where(clause = "del_dt is null")

 

@Entity
@SQLDelete(sql = "UPDATE member SET del_dt = CURRENT_TIMESTAMP WHERE member_no=?")
@Where(clause = "del_dt is null")
public class Member extends BaseEntity{

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

    @Column(length = 100, nullable = false, unique = true, name = "member_id")
    private String member_id;

    @Column(length = 100, nullable = false)
    private String member_password;

    @Column(length = 100, nullable = true)
    private String member_nickname;

    @Column(nullable = false)
    private boolean member_from_social;
    
    @Column(name = "del_dt")
    private LocalDateTime del_dt;

}

이 Member Entity에 해당 어노테이션이 붙여짐으로써, SELECT 를 통하여 Member를 호출할시 항상 Member의 where문에 삭제가 되지 않은 값들만 가져오게 처리가 됩니다.

 

세번째, BaseEntity에 del_dt 추가하여 공통으로 관리할까?

BaseEntity의 정보들은 단순히 매핑 역할을 위한 정보이므로, del_dt는 BaseEntity가 아닌 Member Entity에 추가하는것이 나아보입니다. 만약에 Repository의 반환형이 MemberDTO로 설정하여 BaseEntity의 컬럼들을 모두 가져와서 사용하면 가능하겠지만, Repository는 일반적으로 Entity를 생성/수정하기에 Entity를 반환하므로 삭제여부를 알기위할때는 한계가 존재합니다.

( 추가로, inst_dt와 updt_dt같은경우 @CreatedDate 와 @LastModifiedDate 처럼 Spring Boot에서 제공하는 Annotation이 있지만, del_dt 같은경우 그러한 어노테이션이 존재하지 않습니다.

    @Column(name = "del_dt")
    private LocalDateTime del_dt;

 

https://passionfruit200.tistory.com/389 (이전에 BaseEntity를 활용하여 inst_dt와 updt_dt를 추가한 글)

 

[Spring Boot][Seminar-hub] BaseEntity란, @EntityListeners로 엔티티의 변화를 감지하는 방법, Persistence Context란

글을 쓰는 이유 Member Entity 클래스를 생성할때, inst_dt ( 데이터 삽입 날짜 ), updt_dt ( 데이터 수정 날짜) 와 같은 날짜들은 모든 Entity가 기본적으로 가지고 있는 컬럼입니다. 해당 컬럼들을 하나의 E

passionfruit200.tistory.com

 

 

실제로 위의 방안들을 적용했을까?

우선 결론적으로 말하자면, 위의 3가지 경우 모두 사용하지 않았습니다.

이유를 정리해보면, 

@SQLDelete을 사용함으로써 발생할 수 있는 문제

예시로, 어떤 Member가 delete처리를 하여 고정된 SQLDelete가 실행되었는데, 그떄 Member가 영구탈퇴인지 혹은 일시탈퇴인지에 따라서 del_dt만 업데이트 되는것이 아닌 추가로 다른 컬럼들도 업데이트가 되어야할 필요가 있을텐데 그러한 조건들을 처리하기에 힘들어보여, 사용하지 않는것이 낫다고 판단했습니다.

@Where을 사용함으로써 발생할 수 있는 문제

예시로, 관리자단에서 삭제된 데이터를 조회를 하거나, 삭제된 데이터를 여러 조건에 따라서 작업이 필요할떄가 있을 것입니다. 이때, 이러한 조건들이 다른 개발을 진행하는데 있어서 제약조건을 준다고 생각하여 사용하지 않는 것이 낫다고 판단했습니다. ( 이떄, @Filter, @FilterDef 와 같은 어노테이션을 통해 조건을 조절할 수 있습니다. )

 

BaseEntity에 del_dt를 추가하지 않은 이유

del_dt의 값을 정확하게 알기 위해서는 BaseEntity가 아닌 Member Entity에 있어야 가능합니다. ( 저는 Repository가 Entity를 반환하고 있습니다. )

 

구현하면서 느낀점

SOFT_DEL에 대해 알아보면서, JPA에서 제공하는 SOFT_DEL 전략과 해당 전략들을 내 프로젝트나 대규모 프로젝트에 적용했을때 발생할 수 있는 Side Effect를 생각해보게 되었습니다. 또한, 개발을 할시 특정 기술에 대한 의존성이 존재하지 않아, 개발자가 자유롭게 개발을 할 수 있게 하는것이 더욱 중요하다는 생각이 들게 되었습니다. 

 

 

 

[도움받은 글들]

How to Implement a Soft Delete with Spring JPA, stackoverflow 

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

 

JPA에서 soft_delete 쉽게처리하기 (@sqldelete, @where 사용방법과 테스트까지)

https://lahezy.tistory.com/100

 

BaseEntity에서 삭제기록 사용안하는 이유

https://okky.kr/questions/1321520

 

실무에서 사용하는 예시중 하나

https://www.inflearn.com/questions/304378/baseentity%EC%99%80-softdelete-%EC%A7%88%EB%AC%B8

 

+ Recent posts