본문 바로가기
Framework & Lib & API/스프링

[스프링] @async 비동기 사용법

by 코딩공장공장장 2021. 2. 22.

여러 작업을 하나의 요청으로 처리할때 많은 시간이 소요되는 경우가 있습니다. 

 

작업의 선후관계가 중요하지 않고 각각의 작업들이 독립적인 상황이라면 이를 비동기로 처리하여

 

요청에 대한 시간을 절약하는것이 좋은 방법이 될 수 있습니다. 

 

저의 경우에도, 채팅을 하는 어플리케이션에서 소켓을 통해 상대방과 대화하고 상대방이 메세지를 안 읽은 상태이면

 

이를 푸시알림을 보내주게끔 구현을 했었습니다. 허나, 푸시알림을 보내는 과정에서 시간이 상당히 소요되어

 

채팅을 하는데 메세지가 2~3초 뒤에 표시되는 현상이 나타났습니다. 

 

따라서 이를 비동기를 통해 메인쓰레드에서 소켓을 통해 채팅하고 DB에 메세지를 넣는 작업을 하고

 

새로운 쓰레드에서 푸시알림을 보내게끔하여 요청에 대한 응답을 빠르게 할 수 있었습니다. 

 

이런식으로 비동기를 이용한다면 시간을 절약할 수 있습니다. 

 

허나 작업이 서로 연관이 있고, 작업의 결과를 받아 결과값을 가지고 작업을 처리해야한다면 비동기는 사용할 수 없겠죠.

 

비동기는 작업이 서로 연관이 없고 독립적으로 실행될 수 있을때 사용을 하는게 바람직합니다. 

 

 

스프링에서 비동기 작업은 @async 애노테이션을 통해 작업 할 수 있습니다. 

 

xml 방식과 java config 방식 두가지가 있는데 두개 다 어떻게 하는지 알아보겠습니다.

 

 

 

config 설정

- xml 방식

 

	<bean id="taskExecutor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
  		<property name="corePoolSize" value="5" />
  		<property name="maxPoolSize" value="10" />
  		<property name="queueCapacity" value="25" />
	</bean>	
	
    <!-- messageSender 빈은 @Async애노테이션이 적용된 메서드가 포함된 클래스입니다. -->
   	<bean id="messageSender" class="[패키지].MessageSender">     
        
	<task:annotation-driven executor="taskExecutor" />

 

xml설정 파일에 위와 같이 빈설정과 <task:annotation-driven /> 에 executor="taskExecutor" 속성을 넣어준다.

 

ThreadPoolTaskExecutor 클래스를 통해 우리는 쓰레드 관련 설정을 할 수 있습니다.

 

corePoolSize는 기본 쓰레드 풀 생성 갯수를 설정하고,

 

maxPoolSize는 최대 쓰레드 풀 생성 갯수를 설정할 수 있고,

 

queueCapacity는 최대 쓰레드가 생성되어 있을때 대기하는 큐의 사이즈를 설정하는 것입니다.

 

 

 

 

 

- java config

import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;

@EnableAsync
@Config
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.context.annotation.Bean;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;

public class AsyncConfig implements AsyncConfigurer {

	@Bean
	public ThreadPoolTaskScheduler taskScheduler() {
		ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
		scheduler.setPoolSize(4);
		scheduler.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());
		return scheduler;
	}
	
    // @Async 메소드를 사용할 클래스
	@Bean
	public MessageSender messageSender() {
		return new MessageSender();
	}
	
	@Override
	public Executor getAsyncExecutor() {
		return taskScheduler();
	}

	@Override
	public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
		// TODO Auto-generated method stub
		return null;
	}

}

 

 

자 이제 설정을 끝났고 비동기를 사용할 클래스를 작성하겠습니다.

 

 

import org.springframework.scheduling.annotation.Async;

@EnableAsync
public class MessageSender {

	@Async
	public void myAsyncTask1() {
		//처리할 작업 구현
	}
	
	@Async
	public void myAsyncTask2() {
		//처리할 작업 구현
	}
	
	@Async
	public void myAsyncTask3() {
		//처리할 작업 구현
	}
	
	@Async
	public void myAsyncTask4() {
		//처리할 작업 구현
	}
}

 

 

위와 같은 형태에서 처리하고 싶은 작업이 있다면 본인이 구현을 하시면 됩니다. 

 

그리고 사용할 때에 주의 사항이 

 

사용할 클래스에서 

 

	@Resource
	private messageSender MessageSender;

 

위와 같이 필드값을 줘서

 

message.myAsyncTask1();

 

이렇게 사용을 하시면 됩니다. 그러면 message.myAsyncTask1()에서 하는 작업은 비동기로 처리가 됩니다.

 

반응형