BACKEND/JAVA & SPRING

물리삭제 & 논리삭제

이-프 2023. 12. 19. 15:49

이전에 개발을 할 때, 상항에 따라 UPDATE를 할때도, DELETE를 할때도 있었다. 그 차이는 논리삭제와 물리삭제인데 그 차이점을 공부하고 앞으로의 개발상황에 적용하도록 할 것이다. 🌱

물리삭제 & 논리삭제 의 정의

물리삭제 (Hard Delete)

  • SQL의 Delete 명령어를 사용하여 직접 데이터를 삭제하는 방법

논리삭제 (Soft Delete)

  • SQL의 Update 명령어를 사용하여 삭제 여부를 알 수 있는 칼럼에 데이터가 삭제되었다는 값을 넣어서 표현

    ex) deleted_at이 null이면, 삭제x

    ex) deleted_at에 datetime이 있으면, 삭제 o

왜 서비스에서는 주로 논리삭제제를 사용할까 ?

서비스를 운영하는 사람 입장에서, 데이터를 유지할 경우 얻을 수 있는 이점이 많다.

  1. 데이터 분석사용자가 언제 어느 시점에 해당 데이터를 삭제하는가 ?
  1. 데이터 복원 사용자가 실수로 삭제했을 때, 복원이 가능하다.

⇒ 사용자들의 모든 행동이 서비스의 데이터로 쌓이고, 이를 분석하여 마케팅 및 기획 개발에 사용할 수 있다.

논리삭제에 단점은 없을까?

  1. DB에 데이터가 계속 남아있으므로, 용량이 부족할 수 있다.
  1. DB 스키마 구조에서 불필요한 칼럼 하나를 차지하게 되므로, 불필요한 검색조건을 추가해줘야한다.

⇒ 그러므로, 서비스의 성격에 맞춰 물리삭제, 논리삭제 방법을 선택해야한다.

물리삭제와 논리삭제 개발 방법

물리삭제

@DeleteMapping("/{commentId}")
public ResponseEntity<ResponseDTO<CommentDeleteResponseDTO>> softDeleteComment(
    @PathVariable long commentId) {
    return ResponseEntity.status(HttpStatus.OK).body(
        ResponseDTO.res(HttpStatus.OK, commentService.softDeleteComment(commentId),
            "댓글을 성공적으로 삭제했습니다."));
}
public CommentDeleteResponseDTO softDeleteComment(Long commentId) {
		Comment comment = commentRepository.findById(commentId)
		    .orElseThrow(CommentNotFoundException::new);
		commentRepository.delete(comment);
		return CommentDeleteResponseDTO.builder().commentId(commentId).build();
		}

논리삭제

@PatchMapping("/{replyId}")
    public ResponseEntity<ResponseDTO<CommentDeleteResponseDTO>> patchComment(
				@PathVariable long replyId) {
        return ResponseEntity.status(HttpStatus.OK).body(
            ResponseDTO.res(HttpStatus.OK, commentService.patchComment(replyId),
                "댓글을 성공적으로 삭제했습니다."));
    }
public CommentDeleteResponseDTO softDeleteComment(Long commentId) {
		Comment comment = commentRepository.findById(commentId)
		    .orElseThrow(CommentNotFoundException::new);
		comment.delete(LocalDateTime.now());
		return CommentDeleteResponseDTO.builder().commentId(comment.getId()).build();
		}
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Entity
public class Comment extends BaseTimeEntity {

 ' ' '
    @Override
    public void delete(LocalDateTime currentTime) {
        super.delete(currentTime);
    }
}

└ BaseTimeEntity를 적용하여, deletedAt칼럼에 삭제 시간이 적히도록 한다.

@Getter
@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
public abstract class BaseTimeEntity {

' ' '
    @Column(insertable = false)
    private LocalDateTime deletedAt;

    protected void delete(LocalDateTime currentTime) {
        if (deletedAt == null) {
            deletedAt = currentTime;
        }
    }

    public boolean isDeleted() {
        return deletedAt != null;
    }

    protected void restore() {
        deletedAt = null;
    }
}

🔗 참고 URL

https://velog.io/@taeha7b/hard-delete-softdelete


Uploaded by N2T