ballqs 님의 블로그
[Spring] @Async 란? 본문
Spring Boot의 @Async 이해 및 활용
@Async는 Spring에서 비동기 작업을 처리하는 기능을 제공하는 어노테이션입니다. 이 어노테이션을 메서드에 적용하면, 해당 메서드는 별도의 스레드에서 비동기적으로 실행됩니다. 이를 통해 메인 스레드의 작업이 차단되지 않으면서 동시에 다른 작업을 처리할 수 있어 애플리케이션의 성능과 응답성을 높일 수 있습니다.
@Async 동작 원리
Spring에서 @Async는 AOP(Aspect-Oriented Programming)와 스레드 풀을 활용하여 비동기 처리를 구현합니다. @Async가 붙은 메서드를 호출하면, Spring은 별도의 스레드를 생성하고 해당 메서드를 실행합니다. 이때, 메서드는 호출 즉시 반환되며, 메서드의 실제 실행은 백그라운드 스레드에서 처리됩니다.
- 스레드 풀: @Async가 붙은 메서드는 기본적으로 SimpleAsyncTaskExecutor를 사용하여 실행됩니다. 이 스레드 풀은 작업을 분배하여 다수의 스레드에서 병렬로 작업을 처리합니다. 기본적으로 새 스레드를 무제한으로 생성할 수 있지만, @EnableAsync와 함께 커스텀 스레드 풀을 설정하여 스레드 개수를 조절할 수 있습니다.
- 리턴 타입: @Async 메서드는 void, Future<T>, CompletableFuture<T>, ListenableFuture<T> 등의 리턴 타입을 가질 수 있습니다. Future나 CompletableFuture를 사용하면 비동기 작업의 결과를 기다리거나 작업 완료 후 특정 로직을 처리할 수 있습니다.
@Async 설정
기본 설정: @Async를 사용하려면, Spring Boot 애플리케이션에서 비동기 처리를 활성화해야 합니다. 이를 위해 메인 클래스 또는 설정 클래스에 @EnableAsync 어노테이션을 추가합니다.
@Configuration
@EnableAsync
public class AsyncConfig {
// 스레드 풀 설정을 커스터마이징할 수 있음
}
사용법: 비동기 처리하고자 하는 메서드에 @Async 어노테이션을 적용합니다. 이 메서드는 호출 즉시 반환되고, 실제 처리는 백그라운드 스레드에서 수행됩니다.
@Service
public class AsyncService {
@Async
public void performAsyncTask() {
System.out.println("비동기 작업 실행 중...");
}
}
@Async 리턴 타입
- void: 반환값이 없는 경우입니다. 메서드가 비동기로 실행되며 호출 즉시 반환됩니다.
- Future<T>: 비동기 작업의 결과를 받을 수 있는 타입입니다. Future.get() 메서드를 사용하여 작업이 완료될 때까지 기다릴 수 있습니다.
- CompletableFuture<T>: 자바 8 이상에서 사용할 수 있는 비동기 API로, 비동기 작업의 결과를 기다리지 않고도 추가적인 작업을 연결할 수 있습니다.
@Async
public CompletableFuture<String> fetchData() {
// 비동기 처리 작업
return CompletableFuture.completedFuture("작업 완료");
}
@Configuration 설정
@Configuration
@EnableAsync
public class AsyncConfig {
@Bean(name = "customExecutor")
public Executor taskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(5); // 기본 스레드 개수
executor.setMaxPoolSize(10); // 최대 스레드 개수
executor.setQueueCapacity(500); // 큐 사이즈
executor.setThreadNamePrefix("AsyncThread-");
executor.initialize();
return executor;
}
}
이렇게 설정한 후 @Async("customExecutor")와 같이 특정 메서드에 적용하여 사용할 수 있습니다.
주의사항
- 트랜잭션: @Async 메서드는 기본적으로 호출한 메서드와 같은 트랜잭션 컨텍스트에 속하지 않습니다. 만약 트랜잭션 내에서 비동기 작업을 처리하려면 @Transactional과 함께 적절한 트랜잭션 전파 레벨을 설정해야 합니다.
- 같은 클래스 내 호출: @Async 메서드는 프록시 기반으로 동작하므로, 같은 클래스 내에서 다른 메서드를 호출할 때는 비동기 처리가 이루어지지 않습니다. 이를 해결하려면 Spring의 AOP 구조에 맞게 별도의 빈을 통해 호출해야 합니다.
사용 예시
@Service
public class NotificationService {
@Async
public void sendNotification(String message) {
// 오래 걸리는 작업을 비동기로 처리
System.out.println("메시지 전송 중: " + message);
}
}
이를 호출하는 클라이언트는 다음과 같이 @Async 메서드를 사용할 수 있습니다.
@RestController
public class NotificationController {
private final NotificationService notificationService;
public NotificationController(NotificationService notificationService) {
this.notificationService = notificationService;
}
@GetMapping("/send")
public String sendNotification() {
notificationService.sendNotification("Hello!");
return "알림 전송 요청됨!";
}
}
이렇게 하면 /send 요청은 비동기로 처리되고, 클라이언트는 응답을 기다리지 않고 빠르게 응답을 받을 수 있습니다.
'코딩 공부 > Spring' 카테고리의 다른 글
[Spring] Redis 동시성 문제 Redisson으로 해결! (0) | 2024.10.08 |
---|---|
[Spring] Redis pub/sub란? (0) | 2024.10.07 |
[Spring] JpaRepository 쿼리 사용 방법 및 효율적으로 사용 방법 (0) | 2024.09.26 |
[Spring] JPA 매핑 기능 (0) | 2024.09.26 |
[Spring] @TransactionalEventListener란? (0) | 2024.09.20 |