![[Spring] Soft Delete(@SQLDelete, @SQLRestriction)](https://img1.daumcdn.net/thumb/R750x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdna%2FboWLKW%2FbtsPre8nyUj%2FAAAAAAAAAAAAAAAAAAAAAJV140OUUofdmS-ejVyoA-G__Utn-zNgmkJVvbHA4--O%2Fimg.png%3Fcredential%3DyqXZFxpELC7KVnFOS48ylbz2pIh7yKj8%26expires%3D1753973999%26allow_ip%3D%26allow_referer%3D%26signature%3DJ%252Br3ZOddupJNMJrB%252Fr6MaEdxz%252B8%253D)
Soft Delete VS Hard Delete
Soft Delete와 Hard Delete는 데이터 삭제 방식을 구분하는 개념이다.
- Soft Delete: 데이터를 물리적으로 삭제하지 않고, 삭제 여부를 나타내는 플래그(예: is_deleted, deleted)로 표시만 하는 방식
- Hard Delete: 데이터를 DB에서 완전히 제거(DELETE) 하여 복구 불가능하게 만드는 방식
Soft Delete
Soft delete는 삭제 여부를 판단할 수 있는 컬럼을 추가해 데이터가 삭제되었는지, 아닌지에 대한 값을 넣어서 표시한다.
삭제 할 데이터가 추후에 조회해야 하거나, 실수로 삭제했을 시 복원 가능해야 하는 중요한 도메인일 경우에 사용한다.
UPDATE Users SET deleted = true WHERE id = ?
삭제 시간으로 soft delete를 구현하는 방법
UPDATE Board SET deleted_at = {삭제된_날짜_시간} WHERE id = ?
장점
- 데이터를 실제로 삭제하지 않기 때문에 실수나 요청에 따라 복원할 수 있다.
- 다른 테이블과 관계가 맺어진 경우에도 외래키 무결성을 해치지 않는다.
- 삭제된 데이터도 데이터 분석 대상에 포함할 수 있다.
단점
- 실제 삭제가 아니므로 DB에 계속 남아 공간을 차지한다.
- 해당 데이터를 조회할 때, WHERE is_deleted = false 등 필수이다.
- 삭제 데이터를 포함해 레코드 수가 계속 누적되어 쿼리 성능이 저하될 수 있다.
Hard Delete
Hard delete는 DELETE 쿼리를 날려 실제 데이터베이스의 데이터를 삭제하는 방법이다.
삭제 할 데이터가 추후에 필요가 없는 경우 사용한다.
DELETE FROM Users WHERE id = ?;
장점
- 불필요한 데이터를 제거함으로써 저장 공간을 효율적으로 관리할 수 있다.
- 조건 없이 조회/처리가 가능하므로 단순하고 빠른 쿼리를 작성할 수 있다.
- 민감한 데이터 삭제 시 실제 데이터가 사라지므로 정보 유출 위험이 줄어든다.
단점
- 삭제 즉시 데이터가 사라지므로 복원할 수 없다 (백업 없을 경우 치명적).
- 외래키 제약이 있는 경우 먼저 참조를 끊지 않으면 오류 발생.
- 삭제된 데이터에 대한 히스토리나 로그가 없으므로 분석, 감시, 감사가 어렵다.
@SQLDelete, @SQLRestriction
@SQLDelete
- @SQLDelete는 Hibernate의 기능으로, JPA 엔티티에 Soft Delete를 적용하기 위해 삭제 시 실행될 SQL을 커스터마이징하는 애노테이션이다.
- 이 애노테이션을 붙이면 JpaRepository.delete(entity)를 호출해도 DELETE FROM ...이 실행되지 않고, 지정한 SQL로 대체된다.
- 즉, 삭제 요청을 특정 update 쿼리로 대체 할 수 있다.
@Entity
@SQLDelete(sql = "UPDATE users SET is_delete = true WHERE id = ?")
public class User {
@Id
private Long id;
@Enumerated(EnumType.STRING)
@Column(nullable = false)
private UserStatus status;
// 기타 필드 ...
}
이렇게 엔티티에 해당 애노테이션을 붙히면 userRepository.delete(user)를 호출했을때
"UPDATE users SET is_delete = true WHERE id = ?" 이 쿼리가 나가는 것이다.
@SQLRestriction 와 함께 사용하면 is_delete - true인 데이터가 조회되지 않도록 할 수도 있다.
@SQLRestriction
- @SQLRestriction은 Hibernate 6부터 도입된 애노테이션으로, 엔티티 조회 시 SQL 수준에서 조건절(WHERE 절)을 강제하는 기능이다.
- 기존에 @Where 이라는 애노테이션의 단점을 보완하는 최근에 생긴 애노테이션이다.
- @Where은 곧 지원되지 않을 예정이다.
@Entity
@SQLRestriction("is_delete = false")
public class User {
@Id
private Long id;
@Enumerated(EnumType.STRING)
private UserStatus status;
// 기타 필드...
}
이렇게 하면 해당 엔티티를 조회하는 모든 SQL문에 'WHERE is_delete=true'이 자동으로 추가된다.
즉, 논리적으로 삭제되지 않은 엔티티만 조회할 수 있도록 된다.
@Where와의 차이점
- @Where은 native query, raw SQL, EntityManager.createNativeQuery(), Querydsl 에는 적용되지 않음
- @SQLRestriction은 Hibernate가 SQL을 생성할 때 직접 테이블 alias에 조건을 붙이기 때문에 native query, Querydsl, fetch join, 서브쿼리, 복잡한 쿼리에도 자동 적용됨
@SQLRestriction을 적용하면 삭제된 엔티티를 조회하고 싶을때 우회가 불가능하거나 매우 힘들기 때문에 도입은 신중해야한다.
@SQLDelete, @SQLRestriction를 함께 사용해서 soft delete를 구현하고, 삭제된 엔티티에 대해서는 DB에서만 조회할 수도 있다.
@Entity
@SQLRestriction("is_delete = false")
@SQLDelete(sql = "UPDATE users SET is_delete = true WHERE id = ?")
public class User {
@Id
private Long id;
@Enumerated(EnumType.STRING)
private UserStatus status;
// 기타 필드...
}
참고: https://velog.io/@o_z/Soft-Delete-%EC%A0%81%EC%9A%A9%ED%95%98%EA%B8%B0
'Back-End > Spring' 카테고리의 다른 글
[Spring Security] @Secured,@PreAuthorize, @PostAuthorize (0) | 2025.07.18 |
---|---|
[Spring] CQRS 패턴 (0) | 2025.06.07 |
[Spring Boot 핵심원리와 활용] 사용자 정의 메트릭 (0) | 2025.05.11 |
[Spring Boot 핵심원리와 활용] 마이크로미터, 프로메테우스, 그라파나 (0) | 2025.05.10 |
[Spring Boot 핵심원리와 활용] 액츄에이터(Actuator) (0) | 2025.05.09 |