-
Spring Boot 시리즈 21편 – 비동기 처리와 병렬 프로그래밍: @Async, CompletableFuture, Reactor 실전 사용법기술과 산업/언어 및 프레임워크 2025. 4. 30. 12:41728x90
Spring Boot에서 @Async, CompletableFuture, Reactor를 활용한 비동기 및 병렬 처리 전략을 소개합니다. 서비스 성능을 높이는 실전 적용 예시 포함.
Spring Boot 시리즈 21편 – 비동기 처리와 병렬 프로그래밍: @Async, CompletableFuture, Reactor 실전 사용법
애플리케이션 성능 병목의 90%는 IO 지연 또는 외부 시스템 호출에서 발생합니다.
이럴 때 가장 효과적인 전략은 비동기화와 병렬 처리입니다.이번 글에서는 Spring Boot에서 @Async, CompletableFuture, Project Reactor를 활용해
실제로 서비스 성능을 높일 수 있는 실전 비동기 처리 전략을 소개합니다.
📌 1. 비동기 처리란?
비동기(Asynchronous)란 요청과 응답을 기다리지 않고 작업을 위임하거나 병렬로 처리하는 방식입니다.
비교 항목 동기(Sync) 비동기(Async)
응답 대기 호출자가 결과를 기다림 결과를 기다리지 않고 다음 작업 수행 쓰레드 점유 대기 중에도 점유됨 쓰레드 효율적 사용 가능 장점 코드 직관적 응답 지연 감소, 병렬 처리 가능
✅ 2. @Async 기반 비동기 처리
1️⃣ 설정
@SpringBootApplication @EnableAsync public class MyApp {}
2️⃣ 서비스에 @Async 적용
@Service @Slf4j public class NotificationService { @Async public void sendEmail(String to, String content) { log.info("Sending email to {}...", to); // 실제 이메일 발송 코드 } }
- 호출자는 즉시 리턴되며, 이메일 발송은 별도 쓰레드에서 수행됨
3️⃣ 비동기 메서드의 반환값 – Future or CompletableFuture
@Async public CompletableFuture<User> getUserInfo(Long id) { return CompletableFuture.completedFuture(userRepository.findById(id).orElseThrow()); }
⚙️ 3. CompletableFuture 활용
병렬 호출 및 결과 병합 예시
public CompletableFuture<User> getUser(Long id) { ... } public CompletableFuture<Order> getOrder(Long userId) { ... } public UserDashboard loadDashboard(Long userId) { CompletableFuture<User> userFuture = getUser(userId); CompletableFuture<Order> orderFuture = getOrder(userId); return userFuture.thenCombine(orderFuture, (user, order) -> new UserDashboard(user, order) ).join(); // 결과 대기 }
- thenCombine: 두 결과를 병합
- join(): 결과를 기다림 (주의: 블로킹 발생 가능)
🔥 4. Project Reactor – 비동기 스트림 처리
기본 개념
개념 설명
Mono 0 또는 1개의 비동기 결과 Flux N개의 스트림 비동기 결과 non-blocking Netty 등 비동기 HTTP 클라이언트 기반 (WebFlux에서 사용됨)
Mono 예시
public Mono<User> findUser(String id) { return Mono.fromCallable(() -> userRepository.findById(id).orElseThrow()); }
Flux 예시
public Flux<Product> getPopularProducts() { return Flux.fromIterable(productRepository.findTop10ByOrderByHitsDesc()); }
WebClient와 함께 비동기 외부 API 호출
public Mono callExternalApi(String query) { return WebClient.create() .get() .uri("https://api.example.com/search?q=" + query) .retrieve() .bodyToMono(ExternalResponse.class); }
- Spring WebFlux 기반의 비동기 클라이언트
- Netty 기반의 non-blocking I/O 구조로 대규모 트래픽에 적합
🧠 실무 적용 전략
항목 전략
@Async 간단한 비동기 위임 처리에 적합 CompletableFuture 비동기 병렬 작업 간 결과 조합에 효과적 WebClient + Reactor 외부 API 다수 호출, 고성능 비동기 처리에 적합 반환값 관리 비동기 Future는 적절한 예외 처리 필수 (handle, exceptionally) 리소스 관리 별도 TaskExecutor 설정 권장 (@Async thread pool 조절)
Executor 커스터마이징 예시
@Configuration public class AsyncConfig { @Bean(name = "asyncExecutor") public Executor asyncExecutor() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); executor.setCorePoolSize(5); executor.setMaxPoolSize(20); executor.setQueueCapacity(100); executor.setThreadNamePrefix("Async-"); executor.initialize(); return executor; } }
✅ 마무리 요약
항목 요약
기본 비동기 @Async + @EnableAsync로 쉽게 구현 가능 병렬 처리 CompletableFuture의 thenCombine, allOf 등 사용 고급 처리 Project Reactor의 Mono, Flux로 비동기 스트림 처리 외부 호출 WebClient로 비동기 HTTP 연동 가능 실무 주의 예외처리, 스레드풀 조절, 결과 병합 시점 명확히 설계
📌 다음 편 예고
Spring Boot 시리즈 22편: API 버전 관리 전략 – URL, Header, Accept 기반 버전 설계 Best Practice
728x90'기술과 산업 > 언어 및 프레임워크' 카테고리의 다른 글
FastAPI 시리즈 1화 - FastAPI란 무엇인가? 탄생 배경과 주요 특징 분석 (1) 2025.04.30 NestJS 마스터 시리즈 6화. DTO와 Validation – 데이터 무결성과 API 품질의 시작 (0) 2025.04.30 Spring Boot 시리즈 20편 – 메시지 큐 기반 비동기 아키텍처: Kafka, RabbitMQ로 확장성 강화 (0) 2025.04.29 Python 마스터 시리즈 3화 – 변수와 자료형 제대로 이해하기 (1) 2025.04.29 Python 마스터 시리즈 2화 Hello World! – 파이썬 기본 문법 맛보기 (0) 2025.04.29