본문 바로가기
Spring/Spring

Spring의 @Schduled 어노테이션으로 어느 구현체가 스케쥴링을 실행할까?

by 졸린개발자 2024. 2. 17.

안녕하세요, 졸린 개발자입니다.

 

Spring에서 @Schduled 어노테이션을 붙이면 스프링이 마법같이 스케쥴링을 해주는데요,

그 이면에 어떤 구현체들이 실제 스케쥴링 코드를 실행시켜주는지 한번 살펴보도록 해보겠습니다.

 

 

코드를 따라가며 하나하나 살펴봅시다.

 

그럼 어디서부터 코드를 봐야할까요?

SpringBoot에서 스케쥴링이 동작할 수 있게, 관련 빈을 Auto configuration을 해줄테니 해당 Configuration을 한번 살펴봅시다.

TaskSchedulingAutoConfiguration이라는것이 나오는군요.

 

주석을 보니, 제대로 찾아온게 맞는거 같군요.

 

하나하나 살펴보기에는 너무 글이 길어지니, 제가 관심있는 ScheduledExecutorService 관련된 설정만 글로 적겠습니다.

 

우선 먼저, TaskSchedulerBuilderConfiguration으로 가보죠

 

제대로 찾아온거 같군요, TaskSchedulerBuilder를 통해 property로 관련 설정을 받고, builder를 리턴해주고 있습니다.

ExecutorService의 pool size나 threadName의 prefix도 같이 설정이 가능하군요.

 

그럼, builder를 build하는 부분을 찾아봅시다.

아까 자동 설정을 해주는 클래스인 TaskSchedulingAutoConfiguration에서 import하는 설정 중 하나에서 해주고 있습니다.

아까 보셨던 TaskSchedulerBuilder 를 주입받아 build를 해서 ThreadPoolTaskScheduler를 빈으로 등록하는군요.

 

재밌는 점은, java 21부터 공식적으로 지원하는 virtual thread일때와 platform thread일때와 schdule하는 thread pool 방식이 다른가 보군요,

저는 platform thread를 현재 일을 하는데 쓰고 있어서, 해당 부분만 한번 딥다이브 해보겠습니다.

 

그럼 build한 결과는 실제로 어떤 객체일까요?

 

ThreadPoolTaskScheduler에 아까 보셨던 property같은 커스텀한 부분을 설정하는군요.

그럼, ThreadPoolTaskScheduler는 뭘까요?

 

정답은 스프링에서 제공해주는 TaskScheduler의 ThreadPool 버전입니다.

TaskScheduler라는 스케쥴링을 도와주는 추상화를, 실제 구체적인 객체중에서도 ThreadPool버전으로 만든 것이죠.

 

그럼, ThreadPoolTaskScheduler는 어떻게 스케쥴링을 해주는걸까요?

정답은 ScheduledThreadPoolExecutor로 다시 위임을 합니다.

그럼 ScheduledThreadPoolExecutor가 뭔지 다시 파악을 해야겠죠?

 

Java에서 제공하는 스케쥴링 - ScheduledExecutorService

ScheduledThreadPoolExecutor는 java에서 스케쥴링을 도와주는 클래스 입니다.

하지만 저희는 구체적인 클래스보다는 스케쥴링을 도와주는 역할을 하는 인터페이스를 한번 살펴보도록 하죠.

 

ScheduledThreadPoolExecutor를 비롯한 스케쥴링 처리를 하는 클래스들은,

실제 그 역할을 하는 ScheduledExecutorService 인터페이스를 구현을 하고 있습니다.

이런식으로 java에서 제공해주고 있고, 좀 더 내려다가보면 scheduledAtFixedRate, scheduledAtFixedDelay 같은 메소드도 자바에서 제공해 주고 있는것을 볼 수 있습니다.

 

앗차차, 글이 또 길어지고 있군요.

더 길어지기전에, 결론으로 java에서 지원하는 스케쥴링하는 객체를 spring에서도 그대로 사용하고 있다고 결론을 짓고, 마무리를 해봅시다.

 

재미있는 사실은, java는 기본적으로 thradpool을 사용하고 있긴 하지만, pool size가 1입니다.

TaskSchedulingAutoConfiguration에서 import했던 것들중 properties를 설정하는데, 그 안을 보시면,

이렇게 size가 1입니다. 따라서 기본적으로는 여러개의 스케쥴링이 된 메소드를 한번에 실행할 수는 없습니다.

따라서 application.properties에 spring.task.scheduling.pool.size로 적절한 값을 지정해서 한번에 여러개의 스케쥴링 메소드가 동작할 수 있게 처리해주는게 중요합니다.

 

 

결론

오늘은 스프링이 스케쥴처리를 할때 실제 어느 구현체가 동작을 하는지 알아봤습니다.

실제로 어떻게 동작하는지 알아보니 재미있군요.

 

다음에도 재미있는 포스팅으로 돌아오겠습니다.