이론 정리/Spring boot

Soft Delete와 Hard Delete의 차이와 @SQLDelete

철매존 2022. 4. 23. 02:20
728x90

DB의 삭제 구현 방법은 두가지가 있다.

  • Soft Delete
    • 데이터를 실제로 삭제하지 않고, 삭제 flag를 변경하는 방법이다.
  • Hard Delete
    • 실제로 데이터를 삭제하는 방법이다.

실제로 서비스를 구현할 때에는 Soft Delete를 자주 사용한다.
하지만 Spring Data JPA에서 이 Soft Delete를 구현할 때에는 주의해야 할 점이 다수 있다.

만약에 한꺼번에 많은 데이터를 삭제하는 경우가 생긴다면 어떨까??
이러한 Bulk연산에서 Soft Delete를 사용할 때에 여러 번의 쿼링이 진행되게 될 것이다.

이를 해결하기 위해서 @SQLDelete어노테이션과 JPA에서 제공하는 deleteAllInBatch를 사용할 수 있다.

@SQLDelete

JPA에서 기본으로 삭제는 Hard Delete로 되어 있다.
그 삭제 방식을 이 @SQLDelete에서 미리 작성해 두면, delete가 호출될 때에 방식을 변경 가능하다.

만약 게시글의 삭제를 구현하려고 한다면

 

 

먼저 이런 식으로 Soft Delete 확인을 위한 isDelete 인자를 갖는 게시글 Entity를 생성한다.

 

 

 

 

게시글의 작성과 삭제를 각각 구현하고, 이를 확인해 볼 것이다.

 

 

저장은 뭐 별거 없다.

그런데 삭제의 경우는 본래 이런 식으로 진행해야 Soft Delete가 될 것이다.

@SQLDelete를 사용하지 않는 경우

 

 

해당 방식은 Dirty Checking을 통하여 영속성 컨텍스트 내에서 영속화된 데이터를 변경해주는 것이다.
참고로 Dirty Checking 이거 모르면 안된다. 무조건 알아야되는 방식이다.

아무튼 이렇게 해야 isDeleted가 true가 되어 삭제가 구현이 될텐데…이를 더 편하게 해줄 수 있다.

@SQLDelete 사용하기

 

 

해당 Entity에서 어노테이션을 이용한 SQLDelete쿼리를 바로 적용해 준다.
이를 사용하면 Spring Data JPA에서 delete메소드를 호출할 때에 삭제 대신 미리 정의된 쿼리를 호출시켜 준다.
그러면 service에서 굳이 어렵게 다른 로직을 쓸 필요도 없을 것이다.

 

 

이렇게 바로 삭제를 해주면 이게 가능해질 것이다.
한번 확인해 보자

 

 

삭제에 관한 기본적인 테스트를 구현해 보았다.
내용을 보면 알겠지만 모든 board는 Delete flag가 true로 되어 있기 때문에 테스트는 통과되고, 삭제가 진행된 15L의 delete flag는 true, 삭제되지 않은 5L의 delete flag는 false로 출력될 것이다.

 

 

 

 

이런 식으로 잘 나왔다.

@Where

그런데… 실제로 서비스를 할 때에는 당연히 삭제된 글을 찾을 수 없게끔 해야 할 것이다.

@Where을 사용하지 않는 경우

 


 

이런 식으로, 해당하는 조건을 찾아서 처리해주면

 

 

삭제된 글을 읽어오지 않을 수 있다.
그런데 알다시피 이런거 하나하나 해주는건 귀찮기도 하고, 어디선가 잘못되면 찾는것도 힘들것이다.

@Where을 사용하는 경우

그래서 Entity 자체에서 검색에 관한 filter를 걸어줄 수도 있다.

 


 

Entity에서 Where조건에 isDeleted에 관한 조건을 걸었다.
이제 어디선가 관련 쿼링을 진행할 때에 조건을 탈 것이다.

 

 

이렇게 없는 내용은 출력 자체가 되지 않는다.
그리고 코드도 굉장히 깔끔해 진 것을 확인 가능하다.