Skip to content

Comments

[feat] 장기 미접속 사용자 자동 탈퇴 및 알림 스케줄러 구현#171

Merged
saokiritoni merged 7 commits intofeat/#155-schedulerfrom
feat/#170-deleteUser
Jan 14, 2026
Merged

[feat] 장기 미접속 사용자 자동 탈퇴 및 알림 스케줄러 구현#171
saokiritoni merged 7 commits intofeat/#155-schedulerfrom
feat/#170-deleteUser

Conversation

@saokiritoni
Copy link
Member

@saokiritoni saokiritoni commented Jan 14, 2026

🌱 관련 이슈

🌱 작업 사항

사용자의 자발적 탈퇴가 저조할 것으로 예상됨에 따라, 리소스 관리 및 보안 강화를 위해 장기 미접속 계정을 자동으로 관리하는 시스템을 구축했습니다. 매일 오전 09:00에 스케줄러가 실행되어 경고 알림 → Soft Delete (비활성화) → Hard Delete (영구 삭제) 프로세스를 수행합니다.

1. DB 스키마 및 Entity 수정 (User)

[필요한 필드 추가]

  • lastLoginAt: 마지막 로그인 시점 (로그인 시 갱신)
  • deletedAt: Soft Delete 된 시점 (1년 뒤 영구 삭제 계산용)
  • isActive: 계정 활성화 여부 (-> 기존 필드 유지)

[연관관계 추가]

  • User 삭제 시 Request도 함께 정리되도록 CascadeType.REMOVE 적용

2. 비즈니스 로직 구현

[로그인 (UserLoginService)]

  • 로그인 성공 시 lastLoginAt 업데이트
  • isActive = false (Soft Delete 상태)인 계정은 로그인 차단

[스케줄러 (UserSchedulerService)]

  • 실행 주기: 매일 09:00 (Asia/Seoul)
  • 대상 선정 기준: (마지막 로그인 > 3개월) AND (마지막 Pod 만료일 > 3개월)
  • Pod 사용 기록이 없는 유저는 로그인 날짜만으로 판단
  • 알림 발송: 삭제 예정 D-7, D-3, D-1 일전에 Slack/Email 발송
  • Soft Delete: 예정일 도래 시 isActive = false 처리 및 안내 발송
  • Hard Delete: Soft Delete 후 1년 경과 시 DB 영구 삭제

3. 메시지 관리 리팩토링

  • 하드코딩된 문자열을 messages.properties로 분리하고 MessageUtils를 도입하여 유지보수성을 높였습니다.

4. UserRepository

Q. 활동이 없는 유저(Inactive User) 판단 기준은? UserRepository.findInactiveUsers 쿼리에서 판별합니다.
lastLoginAt이 3개월 지남 AND MAX(requests.expiresAt)이 3개월 지남 (혹은 기록 없음)

특이사항: Pod 사용 기록이 아예 없는 유저(NULL)도 조건에 포함되도록 IS NULL OR ... 조건을 사용했습니다.

Q. 알림 및 삭제 흐름

D-7, 3, 1: 경고 알림 발송 ("로그인하면 삭제되지 않습니다")
D-Day: Soft Delete 수행 (로그인 불가, "1년 뒤 정보 파기" 안내)
D+1년: Hard Delete 수행 (개인정보 파기)

🌱 참고 사항

  • 1년 -> 학기 단위로 작동하도록 학사일정 확인하도록 조정 필요

  • ✅ 통합 테스트 (UserSchedulerServiceTest)

  • 정상 유저: 최근 로그인 시 삭제되지 않음

  • 보호 유저: 로그인은 오래됐지만 최근 Pod 사용 기록이 있으면 삭제되지 않음

  • 알림 발송: D-7, D-1 시점에 정확한 메시지(Slack/Email) 발송 검증

  • Soft Delete: isActive False 변경 및 deletedAt 기록 확인

  • Hard Delete: Soft Delete 1년 후 DB에서 데이터 삭제 확인

  • 메시지 문구: messages.properties에 추가된 문구들이 적절한지 확인해 주세요.

@saokiritoni saokiritoni requested a review from a team as a code owner January 14, 2026 08:03
@saokiritoni saokiritoni changed the base branch from develop to feat/#155-scheduler January 14, 2026 08:03
@saokiritoni saokiritoni merged commit 53feded into feat/#155-scheduler Jan 14, 2026
@saokiritoni saokiritoni self-assigned this Jan 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[ feat ] 사용자 자동 탈퇴

1 participant