
soft-delete 적용 이유?
실제 서비스를 운영하는 프로젝트 개발하면서 사용자가 테러 이후 회원 탈퇴 처리를 해서 아무런 정보를 확인할 수 없다거나, 사용자가 게시글 같은 자료를 잘못 삭제한 경우에 대해 운영자 측에서 복구해 줄 수도 있게 soft-delete를 사용했다.
soft-delete를 사용하면서 unique 필드에 대한 처리를 어떻게 하는지 좋을까 에 대한 고민이 생겼다.
어떤 문제냐면..

주로 Spring에서 soft-delete 처리는 이런 느낌으로 자동화를 시켜놓는다.
2줄의 코드는 delete 처리 대신 is_delete 필드의 값을 true로 바꾸는 처리와, 매 검색마다 is_delete 필드의 값이 false인 값만 검색하는 where 조건을 붙이는 처리이다.
unique 필드는 DB에 유일하게 존재하는데, soft-delete를 사용하면 삭제되지 않고, 남아있게 된다.
이때, 값을 추가하는 로직에서 @SQLRestriction 어노테이션으로 is_delete is false 처리를 하기에 당연하게 soft-delete 된 필드를 인식하지 못해 insert 를 하다가 오류가 나게되는 것이다.
여기에는 3가지 해결 방법이 있다.
@SQLRestriction 어노테이션을 통해 soft-delete 처리되지 않은 값들에 대해 중복 확인 후, 삽입.추가
- 기존 unique 컬럼의 레코드 값을 삭제할 때 deleted_~ 이런식으로 수정해주는 방법도 사용해볼만 할 것 같다.
1번은 어떠한 이유에서든 중복 값이 삽입된다면 후 처리해주는게 쉽지 않을 것이고, unique 설정을 하지 않아 전체 탐색에 있어서 속도가 느려질 것이기에 포기.
2번은 unique 설정을 하고, 전체 탐색을 진행하려면 @SQLRestriction 을 제거하고, 기존 사용 메서드에 모두 where id=? 를 추가해줘야 하며, 전체 탐색을 위한 jpa 메서드가 하나 더 필요하다. 복잡해짐..
다중 컬럼 unique는 다음처럼
참고 블로그 : https://oraange.tistory.com/26
즉, 2개의 필드를 함께 unique 제약조건으로 확인하는 것이다.
ALTER TABLE users
ADD not_archived BOOLEAN
GENERATED ALWAYS AS (IF(deleted_at IS NULL, 1, NULL)) VIRTUAL;
not_archived 라는 virtual 컬럼을 만든다. 이는 deleted_at이 null 이면 1이 들어가고, 존재하면 null이 된다.
ALTER TABLE users
ADD CONSTRAINT UNIQUE (nickname, not_archived);
그리고, 기존 unique 컬럼과 묶어서 관리하며, 기존에 nickname의 CONSTRAINT는 제거해야 한다.
soft-delete 가 마냥 좋은걸까..?
확실히 복잡도가 증가한다.
현 프로젝트에서는 좋아요 같은 기능에 대해서는 soft-delete를 적용하고 있지 않고, 복구가 필요할 것 같거나 완전 삭제보단 데이터를 남기는게 좋다고 생각한 테이블에 대해서는 soft-delete를 적용하고 있다.
또한 추후 백오피스 기능을 개발해야 할 때, 삭제된 사용자에 대해서도 확인할 api가 필요할 텐데.. 관리자용 조회 메서드를 별도로 추가해야 할 것 같다.
EntityManager를 직접 사용하면 @SQLRestriction으로 인해 자동으로 조건절이 추가되는 것을 우회할 수 있다고 한다.
여튼 soft-delete를 사용하면서 편해지는 부분도 존재하고, 오히려 더 복잡해지는 부분도 존재하는 trade-off 의 영역이라 잘 고민하고 꼭 필요한 부분에만 적용해야 할 것 같다.