데이터베이스에서 회원탈퇴와 같은 일이 일어났을 때 userStatus를 탈퇴상태로 바꿀 건지, 회원의 정보를 모두 삭제할지 고민하곤 합니다.
hard delete와 soft delete에 대해 알아보고, 어떤 장단점이 있는지 알아보고자 합니다.
논리적으로만 삭제하는 방법입니다.
사용자가 한때 접근할 수 있었지만 더 이상 접근할 수 없는 데이터로 만들어 사용할 수 없게 만드는 프로세스입니다.
회원상태만 변경하여 해당 데이터는 DB에 그대로 남아있게 됩니다.
UPDATE 쿼리가 발생합니다.
데이터베이스에서 영구적으로 데이터를 삭제하는 일입니다.
DELETE 쿼리가 발생합니다.
Soft Delete의 경우에는 where 조건에 delete_falg = "0" 조건을 추가하는 것을 까먹었을 때 문제가 발생할 가능성이 있습니다.
반면 Hard Delete는 삭제된 데이터를 조회될 가능성이 없습니다.
Hard Delete👍
update가 delete보다 microseconds 만큼 빠릅니다.
감사 테이블의 삽입까지 생각해보거나 인덱스의 재배열까지 고려하면 update가 훨씬 빠릅니다.
Soft Delete👍
soft delete의 경우에는 ON Delete Cascading을 사용할 수 없습니다.
대안은 delete_flag의 UPDATE Trigger를 생성하는 것입니다.
Hard Delete👍
Hard Delete의 경우에는 audit(history) 테이블에 데이터를 복사해 놓는 경우 복구를 진행할 수 있습니다.
하지만 Soft Delete의 경우에는 열만 Update만 진행하면 됩니다.
Soft Delete👍
soft delete를 위해선 query에 조건이 필요하고 join을 수행할 때 이런 조건이 여러 개 있을 수 있습니다.
조건이 많은 것보다 적은 것이 빠르기 때문에 성능상으로 Hard Delete에 이점이 있습니다.
또한 테이블 크기가 계속 증가하기 때문에 테이블 크기가 증가하면 쿼리 속도가 느려질 수 있습니다.
Hard Delete👍
어떤 데이터를 삭제하느냐에 따라 다르겠지만 일반적으로는 soft delete가 더 좋을 것 같습니다.
유저들이 서비스를 사용하면서 쌓고 있는 많은 데이터들이 범법 행위가 아닌 경우에는 마케팅이나 사업적인 방향에 활용할 수 있습니다.
먼저, 사용자 테이블에 삭제 여부를 나타내는 플래그를 추가합니다.
model Users {
userId Int @id @default(autoincrement()) @map("userId")
username String @map("username")
email String @map("email")
deleted Boolean @default(false) @map("deleted")
// ... 다른 필드들
@@map("Users")
}
회원 탈퇴 시, 실제로 테이블에서 삭제하지 않고, 대신 deleted 플래그를 true로 설정합니다.
// 사용자를 소프트 삭제하는 함수
async function softDeleteUser(userId) {
await prisma.user.update({
where: { id: userId },
data: { deleted: true },
});
}
애플리케이션에서 사용자 데이터를 검색할 때, 삭제된 사용자는 제외하도록 쿼리를 수정합니다.
// 삭제되지 않은 사용자만 검색하는 함수
async function getActiveUsers() {
return await prisma.user.findMany({
where: { deleted: false },
});
}
삭제된 사용자를 복구하려면 deleted 플래그를 false로 설정하는 로직을 추가합니다.
// 사용자를 복구하는 로직
await prisma.users.update({
where: {
email,
deleted: true,
},
data: {
deleted: false,
},
});
이러한 방식으로 Soft delete를 구현하면 데이터를 완전히 삭제하지 않으면서도 삭제된 상태의 데이터를 표시 및 관리할 수 있습니다.