프레임워크/스프링

[스프링] 휴면 계정 처리를 위한 전략과 그 구현 (3) 스케줄러 처리와 테스트

believekim 2025. 6. 25. 04:47

휴면계정처리를 완료해보니 개인정보 유효기간제가 폐지되었다는 사실을 알았다.
하지만 구현하여 연계되는 기능이 많기에 글을 써보려고 한다.


시스템 환경

IDE IntelliJ IDEA
Language Java 17
Framework Spring Boot 3.4.5
Build Tool Gradle
ORM JPA (Hibernate)
Database MySQL
Security Spring Security + JWT (jjwt 0.11.5)

 

  • 개인정보 보호법 폐지 관련 전문가 칼럼

https://m.ddaily.co.kr/page/view/2024040109384261610

 

[스타트업 법률상식148] 개인정보 유효기간제 폐지, 휴면계정을 복구할 수 있을까?

현수진 변호사. [ⓒ법무법인 민후]...

m.ddaily.co.kr


 

1. 스케줄러 처리 전략

  • 아래 코드를 스케줄러에 위임시킬때 생각해봐야 할 점이 있다.
  • 정확하게 1년 이상 비로그인 시 즉시 차단을 원하면면 로그인 시 검사 유지
  • 다음 날 차단돼도 괜찮라면 스케줄러만 사용
  • 성능 차이가 미미한 정도이기 때문에 코드 유지
if (user.getLastLoginAt() != null && user.getLastLoginAt().isBefore(LocalDateTime.now().minusYears(1))) {
    user.markAsDormant();
    userRepository.save(user);
    throw new BizException(UserErrorCode.DORMANT_ACCOUNT); // 휴면 전환 후 로그인 차단
}

 

2. DormantUserScheduler 작성

@Slf4j
@RequiredArgsConstructor
@Component
public class DormantUserScheduler {

    private final UserRepository userRepository;

    @Scheduled(cron = "0 0 3 * * *") // 매일 새벽 3시
    @Transactional
    public void markDormantUsers() {
        LocalDateTime threshold = LocalDateTime.now().minusYears(1); // 1년 비로그인 기준

        List<User> dormantUsers = userRepository.findAllByLastLoginAtBeforeAndUserStatus(
                threshold, UserStatus.ACTIVE
        );

        for (User user : dormantUsers) {
            user.markAsDormant();
        }

        log.info("휴면 계정 {}건 처리 완료", dormantUsers.size());
    }
}

 

 

3. DormantUserSchedulerTest 작성

  • 스케줄러는 통합테스트만 가능
@SpringBootTest
@Transactional
class DormantUserSchedulerTest {

    @Autowired
    private DormantUserScheduler dormantUserScheduler;

    @Autowired
    private UserRepository userRepository;

    @Test
    void testMarkDormantUsers() {
        // given: 6개월 전 로그인 기록을 가진 유저 생성
        User user = User.builder()
                .email("test@example.com")
                .password("encoded-pw")
                .name("testname")
                .nickname("testnickname")
                .userRole(UserRole.USER)
                .userStatus(UserStatus.ACTIVE)
                .lastLoginAt(LocalDateTime.now().minusYears(2)) // 기준점보다 예전
                .build();

        userRepository.save(user);

        // when: 스케줄러 실행
        dormantUserScheduler.markDormantUsers();

        // then: 유저의 상태가 DORMANT로 바뀌었는지 확인
        User updatedUser = userRepository.findById(user.getId()).orElseThrow();
        assertThat(updatedUser.getUserStatus()).isEqualTo(UserStatus.DORMANT);
    }
}