[프로젝트 회고] 7STARBALL Meeting 상태 자동 변경 스케줄러
들어가며
Meeting 도메인에는 시간이 지나면 자동으로 바뀌어야 하는 상태가 있었다.
모임 시간이 끝났는데도 상태가 계속 RECRUITING이나 ONGOING으로 남아 있으면 사용자 입장에서는 혼란스럽다.
그래서 만료된 모임을 COMPLETED 상태로 변경하는 기능이 필요했다.
이 작업에서는 관리자용 수동 API와 주기적으로 실행되는 스케줄러를 함께 구현했다.
왜 자동 상태 변경이 필요했나
모임 상태는 화면의 기준이 된다.
예를 들어 사용자는 다음과 같은 상태를 보고 행동한다.
- 모집 중인 모임인지
- 진행 중인 모임인지
- 정원이 찬 모임인지
- 완료된 모임인지
그런데 시간이 지난 모임이 계속 모집 중으로 보이면 사용자는 이미 끝난 모임에 참여하려고 할 수 있다.
이 문제를 막으려면 모임 시간이 지난 데이터를 시스템이 정리해야 했다.
관리자 수동 API
먼저 관리자용 API를 만들었다.
1
POST /api/admin/meetings/complete-expired
이 API는 현재 시간을 기준으로 만료된 모임을 조회하고, 아직 완료되지 않은 모임을 COMPLETED로 변경한다.
수동 API를 둔 이유는 운영 중 필요할 때 관리자가 직접 상태 정리를 실행할 수 있도록 하기 위해서였다.
스케줄러가 있어도 수동 실행 API는 유용하다.
배포 직후 확인하거나, 특정 상황에서 즉시 정리가 필요할 수 있기 때문이다.
스케줄러 구현
자동 실행을 위해 Spring의 @Scheduled를 사용했다.
1
@Scheduled(cron = "0 */10 * * * *")
10분마다 만료된 모임을 확인하고 상태를 변경하도록 구성했다.
흐름은 다음과 같다.
- 현재 시간을 가져온다.
- 현재 시간보다 이전에 끝났고,
COMPLETED가 아닌 모임을 조회한다. - 각 Meeting의 상태를
COMPLETED로 변경한다. - 변경된 모임들을 저장한다.
Repository에는 다음 목적의 메서드를 두었다.
1
findExpiredMeetingsNotCompleted(now, COMPLETED)
이름이 조금 길어지더라도, 어떤 데이터를 조회하는지 명확히 드러나게 하고 싶었다.
테스트한 내용
스케줄러와 관리자 API는 눈에 바로 보이는 기능이 아니라서 테스트가 중요했다.
Controller 테스트에서는 다음을 확인했다.
- 정상 호출 시 200 OK
- 예외 발생 시 500 응답
- 여러 번 연속 호출해도 정상 동작
- 잘못된 HTTP 메서드 접근 시 405
- 잘못된 URL 접근 시 404
- 응답 메시지와 Content-Type 검증
Scheduler 테스트에서는 다음을 확인했다.
- 만료된 모임이 있으면 상태가 변경됨
- 만료된 모임이 없으면 아무 작업도 하지 않음
- 단일 모임과 여러 모임 상태 변경
- Repository 메서드 호출 파라미터 검증
- 대량 목록 처리 시 크기와 호출 흐름 검증
테스트를 작성하면서 스케줄러도 결국 비즈니스 로직이라는 생각이 들었다.
단순히 시간이 되면 실행되는 코드가 아니라, 데이터 상태를 바꾸는 중요한 기능이다.
그래서 일반 API처럼 검증이 필요했다.
운영 관점에서 고민한 점
스케줄러는 편리하지만 조심해야 한다.
운영 환경에서는 다음을 고려해야 한다.
- 실행 주기가 너무 짧으면 DB 부하가 생길 수 있다.
- 실행 주기가 너무 길면 상태 반영이 늦어진다.
- 여러 서버 인스턴스에서 동시에 실행될 수 있다.
- 관리자 API는 인증/인가가 반드시 필요하다.
이번 구현에서는 10분 주기로 설정했지만, 실제 운영 트래픽과 데이터 양에 따라 조정이 필요하다고 생각했다.
특히 /api/admin 경로는 관리자 권한 확인이 중요하다.
상태 변경 API는 단순 조회가 아니라 데이터 변경이기 때문이다.
배운 점
이번 작업을 통해 시간 기반 상태 관리의 중요성을 배웠다.
사용자가 직접 요청하지 않아도 시스템은 계속 데이터를 관리해야 한다.
특히 Meeting처럼 시간과 상태가 연결된 도메인은 스케줄러가 자연스럽게 필요해진다.
또한 스케줄러를 만들 때도 테스트와 운영 고려가 필요하다는 것을 느꼈다.
마무리
Meeting 상태 자동 변경 기능은 작은 기능처럼 보이지만, 서비스의 신뢰성과 연결된 작업이었다.
끝난 모임이 계속 모집 중으로 남아 있지 않게 만드는 것.
이런 정리가 사용자 경험을 조용히 지탱한다고 생각한다.
앞으로 시간 기반 상태를 다룰 때는 스케줄러, 수동 복구 API, 테스트, 운영 설정을 함께 고려해야겠다.
Leave a comment