물리삭제(hard delete) vs 논리삭제(soft delete)

강우엉·2023년 11월 6일
0

study

목록 보기
27/44

💡 예외 발생

프로젝트 진행 중 스타일 delete를 테스트중에 외래키 제약 조건 위반 예외가 발생하였다.(java.sql.SQLIntegrityConstraintViolationException)

해당 스타일이 댓글을 가지고 있으므로 가지고있는 댓글들에 있어서 처리할 방법을 몰라 예외가 발생했다고 생각하면 된다.

해결 방법은 여러가지 있겠지만 나는 스타일을 물리삭제 대신에 논리삭제를 하는 해결방법을 선택하였다.

이제 물리삭제와 논리삭제에 대해서 알아보자.

💡 물리 삭제

물리삭제는 SQL의 DELETE 명령어를 사용하여 직접 데이터를 삭제하는 방법이다.

아래와 같은 데이터가 있다고 가정해보자.

3번 데이터를 물리삭제 한다면 아래 사진처럼 될 것이다.

이처럼 삭제 대상의 데이터가 추후에 필요가 없을때 사용한다.

💡 논리 삭제

논리 삭제는 SQL의 UPDATE 명령어를 사용하여 삭제 여부를 알리는 컬럼에 값을 넣어 표시하는 방법이다.

위에서 봤던 데이터를 이번에는 논리삭제해보자.
UPDATE 명령어를 이용하여 삭제 여부의 컬럼을 True로 바꿔준다.

삭제를 했다지만 컬럼에 삭제 여부를 표시만한거와 마찬가지기에 데이터를 그대로 보관할 수 있다.

💡 코드 변경

먼저 Style 테이블에 is_deleted 라는 컬럼을 추가하고 is_deleted 컬럼을 변경하는(삭제하는) deleteStyle 메서드를 생성한다.

※ 수정사항

  • 삭제 여부를 구분하는 컬럼을 boolean 타입으로하면 여부만 식별 가능
  • LocalDateTime으로 삭제 여부와 삭제 시간을 확인 가능
@Entity
@Getter
@NoArgsConstructor
public class Style extends BaseEntity{

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "member_id")
    @NotNull
    private Member member;

    @NotNull
    private String styleImages;

    @Enumerated(EnumType.STRING)
    @Column(length = 20)
    @NotNull
    private Gender gender;

    @NotNull
    private Integer minHeight;

    @NotNull
    private Integer maxHeight;

    @Column(length = 50)
    @NotNull
    private String styleCategory;

    @NotNull
    private String content;

    @NotNull
    private Integer viewCount;

    @NotNull
    private Long styleRank;

    private LocalDateTime deleteDateTime;
    
    public void deleteStyle(LocalDateTime deleteDateTime) {
        this.deleteDateTime = deleteDateTime;
    }
 }

StyleService
서비스 코드에서 해당 컬럼을 변경해주는 로직을 작성한다.

    @Transactional
    public void delete(Long styleId) {
        Style style = styleRepository.findById(styleId)
                .orElseThrow(() -> new SmLogicException(ReturnCode.STYLE_NOT_FOUND));


        style.deleteStyle(LocalDateTime.now());

    }

StyleController

    @DeleteMapping("/api/v1/styles/{styleId}")
    public ApiResponse<?> delete(@PathVariable Long styleId) {
        styleService.delete(styleId);

        return ApiResponse.of(ReturnCode.SUCCESS);
    }

postman으로 테스트시 삭제가 성공하는걸 확인할 수 있다.

profile
우엉이의 코딩 성장일기💻

0개의 댓글