728x90
유저 탈퇴 처리: 7일 보류 후 완전 삭제까지
1. 도입
유저 탈퇴는 단순히 User 엔티티의 삭제로 끝나지 않는다.
데이터 보존 기간, 탈퇴 후 복구 기회, 법적 보관 의무 등 다양한 현실적 이유로 인해,
즉시 삭제가 아닌 보류 후 삭제 방식이 필요하다.
우리 서비스에서는 탈퇴 요청이 들어오면 UserWithdraw 테이블에 기록하고,
7일이 지난 후 해당 유저 데이터를 완전히 삭제한다.
2. 설계 목표
- 유저의 탈퇴 요청 시
즉시 삭제가 아닌7일 보류 처리 - 보류 요청은
UserWithdraw테이블에 기록 - 하루에 한 번 스케줄러가 보류 만료된 유저를 삭제
- 삭제 시 연관된 권한 정보(UserRole 등)도 함께 제거
3. 설계 고려사항
| 고려 항목 | 설명 |
|---|---|
| 언제 실제 삭제할 것인가? | 탈퇴 요청일 기준 7일 이후 |
| 탈퇴 요청은 어디 저장하는가? | UserWithdraw 테이블 |
| 유저 데이터를 완전히 삭제하는가? | User, UserRole 등 직접 삭제 |
| 삭제는 어떻게 트리거되는가? | @Scheduled 어노테이션 기반 cron 작업 |
| 성능 이슈 고려했는가? | withdrawDate에 인덱스 설정 예정 |
4. 구현 설명
4.1 UserWithdraw 테이블
@Entity
@Table(name = "user_withdraw", indexes = {
@Index(name = "idx_withdraw_date", columnList = "withdrawDate")
})
public class UserWithdraw {
@Id
private Long userId;
private String reason;
private LocalDateTime withdrawDate;
}
withdrawDate필드로 7일 경과 여부를 판단userId는@Id로 단일 키 관리
4.2 UserWithdrawService - 삭제 스케줄러
@Service
@RequiredArgsConstructor
public class UserWithdrawService {
private final UserWithdrawRepository withdrawRepository;
private final UserRepository userRepository;
private final UserRoleRepository userRoleRepository;
@Scheduled(cron = "0 0 5 * * *")
@Transactional
public void deleteWithdrawnUsers() {
LocalDateTime threshold = LocalDateTime.now().minusDays(7);
List<UserWithdraw> withdraws = withdrawRepository.findByWithdrawDateBefore(threshold);
for (UserWithdraw withdraw : withdraws) {
Long userId = withdraw.getUserId();
userRoleRepository.deleteByUserId(userId);
userRepository.deleteById(userId);
withdrawRepository.delete(withdraw);
}
}
}
- 매일 오전 5시, 7일 지난 탈퇴 요청들을 조회해 삭제
- 연관된
UserRole데이터도 제거
5. 테스트 전략
UserWithdraw에 요청된 유저가 7일 경과 시 삭제되는지 확인- 삭제 시
User,UserRole,UserWithdraw전부 사라지는지 확인 - 이미 삭제된 유저에 대해 중복 삭제되지 않는지 확인
6. 회고 및 확장 가능성
좋았던 점
- 유저 데이터 삭제를 안전하게 지연시켜 실수나 악의적 요청에 대응 가능
@Scheduled기반 처리로 외부 트리거 없이도 자동 운영 가능- 테이블 인덱스를 명시해 삭제 대상 조회 성능도 고려
확장 고려
- 탈퇴 사유 별 분석이 필요하다면
reason필드를 정규화하거나 별도 관리 필요 - 삭제 전 백업 또는 Kafka 이벤트 발행을 추가하면 감사 및 보관 체계까지 확장 가능
- 개인정보 보호법 대응 위해 탈퇴 시
masking,anonymizing절차를 추가 고려할 수 있음
마무리
유저 탈퇴는 단순한 delete 문 하나로 끝나지 않는다.
정책, 보안, 복구 등을 고려한 지연 삭제 프로세스는 필수다.
우리는 이번 구현을 통해 지연 삭제, 자동 스케줄링, 보관 이력이라는 세 가지 핵심을 갖춘 구조를 완성했다.
다음 글에서는 탈퇴와 함께 Kafka 이벤트를 발행하는 Outbox 연동까지 소개할 예정이다.
728x90
'BindProject' 카테고리의 다른 글
| [기획] 추후 목표 :Kafka 기반 이벤트 아키텍처 이식 설계 (0) | 2025.06.19 |
|---|---|
| [Backend]Auth모듈: 인증 시스템 설계와 구현 -FIN-!! (0) | 2025.06.19 |
| [Backend] Auth모듈 : 역할(Role) 부여 기능 구현기 (0) | 2025.06.19 |
| [Backend] Auth모듈 :사용자 등록 로직의 책임 분리와 유효성 검사 개선 (2) | 2025.06.18 |
| [Backend] AUTH모듈 : 초기 세팅 (0) | 2025.06.18 |