이전 [Spring] 비동기(Asynchronous) 처리 포스팅에서 @EnableAsync
와 @Async
어노테이션을 통해 간편하게 비동기 처리를 구현할 수 있다까지만 살펴보고 따로 쓰레드 풀을 어떻게 설정해야되는지에 대한 내용이 없는 것 같아서 추가로 내용을 작성하였습니다.
특정 수의 쓰레드를 미리 생성해 놓고, 필요할 때마다 이 쓰레드들을 재사용하여 작업을 처리하는 방식
서버는 동시에 여러 사용자가 접속할 수 있습니다. 이때 동시 접속자가 많아지게 되면 쓰레드가 무한대로 생성되면서 서버가 다운될 수 있습니다. 이때 쓰레드 풀을 설정하여 시스템 자원의 효율적 사용을 가능하게 합니다.
이처럼 쓰레드 풀을 사용하면 작업 처리에 대한 오버헤드를 줄이고, 시스템의 응답 시간을 개선할 수 있습니다.
Spring의 @Async
어노테이션을 사용할 때, 별도의 TaskExecutor를 설정을 해주지 않으면, SimpleAsyncTaskExecutor
가 기본적으로 사용됩니다. (이전 포스팅에서 따로 설정해주지 않았기 때문에 이 경우에 해당합니다.)
이때 SimpleAsyncTaskExecutor
는 쓰레드 풀을 사용하지 않고, 매 요청마다 새로운 쓰레드를 생성해서 작업을 수행합니다. ⇒ 따라서 이는 권장되지 않는 방법입니다.
별도로 쓰레드 풀 설정을 해주어야, 시스템 과부하를 방지할 수 있습니다.
Spring에서는 ThreadPoolTaskExecutor
를 통해 쓰레드 풀을 쉽게 설정할 수 있습니다.
ThreadPoolTaskExecutor
는 Spring의 Task Execution 추상화의 일부로, Java의 기본 java.util.concurrent.ThreadPoolExecutor
의 기능을 그대로 사용하면서, 스프링 관리 환경에 적합한 추가 기능과 속성을 제공하는 확장된 클래스입니다.
아래와 같이 AsyncConfigurer
인터페이스의 getAsyncExecutor()
메서드를 오버라이드하여 사용할 Executor
즉, 쓰레드 풀을 정의합니다.
@Configuration
@EnableAsync
public class AsyncConfig implements AsyncConfigurer {
@Override
public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(10); // 기본 스레드 수
executor.setMaxPoolSize(20); // 최대 스레드 수
executor.setQueueCapacity(500); // 큐 용량
executor.setThreadNamePrefix("async-executor-");
executor.initialize();
return executor;
}
}
corePoolSize
보다 많을 때까지 쓰레드 수가 증가할 수 있습니다. 위에서 해준 설정을 바탕으로 ThreadPoolExecutor가 어떻게 동작하는지 그 처리 과정에 대해 알아보겠습니다.
ThreadPoolTaskExecutor
는 먼저 설정된 corePoolSize
내에서 쓰레드를 생성합니다.corePoolSize
를 초과하는 추가 작업이 들어오면, 이 작업들은 queue
에 저장됩니다.queue
가 가득 차면, ThreadPoolTaskExecutor
는 maximumPoolSize
에 도달할 때까지 추가 쓰레드를 생성합니다.keep-alive time
동안 아무 작업도 하지 않으면, 쓰레드 풀은 이 쓰레드를 종료시켜 시스템 리소스를 절약합니다.쓰레드 풀이란 특정 수의 쓰레드를 미리 생성해 놓고, 필요할 때마다 이 쓰레드들을 재사용하여 작업을 처리하는 방식입니다.
Spring에서는 ThreadPoolExecutor를 통해 쓰레드 풀을 쉽게 설정할 수 있으며, 기본 쓰레드 수(corePoolSize), 최대 쓰레드 수(maxPoolSize), 작업 큐의 용량(queueCapacity) 등을 설정하여 효율적으로 쓰레드 관리와 작업 처리를 수행하게 됩니다.
기존에는 @Async
어노테이션을 통해 간편하게 비동기 처리를 구현할 수 있다는 것만 알고 쓰레드 풀 설정을 별도로 해야된다는 것을 몰랐었는데, 쓰레드 풀의 설정 필요성과 ThreadPoolTaskExecutor 설정 방법을 알게 되었습니다.
프로젝트 서버 스펙에 맞도록 설정을 해줘야 할 것 같습니다!