Spring/Java 프로젝트 기준이면 아래 순서로 뒤지면 거의 다 잡힘.
@Scheduled
@EnableScheduling
SchedulingConfigurer
TaskScheduler
ThreadPoolTaskScheduler
ScheduledTaskRegistrar
ScheduledExecutorService
scheduleAtFixedRate
scheduleWithFixedDelay
Timer
TimerTask
Quartz
QuartzJobBean
org.quartz
Scheduler
JobDetail
Trigger
CronTrigger
SimpleTrigger
SchedulerFactoryBean
JobFactory
설정파일도:
spring.quartz
quartz.properties
cronExpression
cron-expression
@EnableBatchProcessing
JobLauncher
Job
Step
JobRepository
JobExplorer
JobOperator
CommandLineJobRunner
설정:
spring.batch.job.enabled
spring.batch.job.name
그리고 ApplicationRunner, CommandLineRunner 안에서 jobLauncher.run() 하는 경우도 꼭 봐야 함.
@PostConstruct
ApplicationRunner
CommandLineRunner
ApplicationListener
ContextRefreshedEvent
ApplicationReadyEvent
@EventListener
예를 들어 이런 것도 사실상 자동 배치임.
@EventListener(ApplicationReadyEvent.class)
public void run() {
batchService.execute();
}
cron
0 0
0 *
*/5
fixedRate
fixedDelay
특히 설정파일:
application.yml
application-*.yml
application.properties
bootstrap.yml
에서:
batch:
cron: "0 0 2 * * *"
scheduler:
enabled: true
같은 커스텀 설정이 있을 수 있음.
@Profile
@ConditionalOnProperty
@Conditional
matchIfMissing
enabled
scheduler.enabled
batch.enabled
이게 중요한 이유가 이런 식일 수 있어서임.
@ConditionalOnProperty(
name = "batch.scheduler.enabled",
havingValue = "true",
matchIfMissing = true
)
matchIfMissing = true면 로컬 설정에 값을 안 넣었는데도 켜질 수 있음.
예를 들어:
BatchController
-> batchService.execute()
를 발견했다면 execute()의 Find Usages를 돌려서:
BatchController
BatchScheduler
BatchJob
ApplicationRunner
전부 확인하는 게 좋음.
오히려 @Scheduled 전체검색보다 이 방식이 더 확실한 경우도 많음.
task:scheduled
task:scheduler
task:annotation-driven
예:
<task:scheduled-tasks>
<task:scheduled
ref="batchService"
method="execute"
cron="0 0 2 * * *"/>
</task:scheduled-tasks>
그래서:
*.xml
도 확인해야 함.
애플리케이션 내부 스케줄러가 아예 없고 외부에서 API를 때릴 수도 있음.
찾아볼 것:
Jenkins
Airflow
Control-M
cron
crontab
Kubernetes CronJob
AWS EventBridge
CloudWatch Events
Spring Cloud Data Flow
특히 Kubernetes 쓴다면:
kind: CronJob
schedule:
검색.
예:
kind: CronJob
spec:
schedule: "0 2 * * *"
그리고 이 CronJob이:
curl POST /batch/run
같이 Controller를 호출할 수도 있음.
애플리케이션이 아니라 DB가 돌리는 경우도 있음.
Oracle:
DBMS_SCHEDULER
DBMS_JOB
PostgreSQL:
pg_cron
SQL Server:
SQL Server Agent
MySQL:
CREATE EVENT
EVENT SCHEDULER
다만 이건 로컬 앱을 띄운다고 바로 따라 실행되는 구조와는 조금 다름.
내가 실제 프로젝트 처음 볼 때는 이 순서로 검색할 듯.
특히 사고 방지 관점에서 제일 중요한 건 @Scheduled만 찾고 끝내지 않는 것.
예를 들어 아래 셋은 전부 @Scheduled가 없어도 자동 실행됨.
ApplicationRunner → batchService
Quartz → batchService
Kubernetes CronJob → BatchController → batchService
그래서 최종적으로는 "실제 배치 로직을 누가 호출하는가"를 역추적하는 것이 가장 확실함.