이전에 개발을 할 때, 상항에 따라 UPDATE
를 할때도, DELETE
를 할때도 있었다. 그 차이는 논리삭제와 물리삭제인데 그 차이점을 공부하고 앞으로의 개발상황에 적용하도록 할 것이다. 🌱
물리삭제 & 논리삭제 의 정의
물리삭제 (Hard Delete)
- SQL의 Delete 명령어를 사용하여 직접 데이터를 삭제하는 방법
논리삭제 (Soft Delete)
- SQL의 Update 명령어를 사용하여 삭제 여부를 알 수 있는 칼럼에 데이터가 삭제되었다는 값을 넣어서 표현
ex) deleted_at이 null이면, 삭제x
ex) deleted_at에 datetime이 있으면, 삭제 o
왜 서비스에서는 주로 논리삭제제를 사용할까 ?
서비스를 운영하는 사람 입장에서, 데이터를 유지할 경우 얻을 수 있는 이점이 많다.
데이터 분석
사용자가 언제 어느 시점에 해당 데이터를 삭제하는가 ?
데이터 복원
사용자가 실수로 삭제했을 때, 복원이 가능하다.
⇒ 사용자들의 모든 행동이 서비스의 데이터로 쌓이고, 이를 분석하여 마케팅 및 기획 개발에 사용할 수 있다.
논리삭제에 단점은 없을까?
- DB에 데이터가 계속 남아있으므로, 용량이 부족할 수 있다.
- 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