Spring Boot · 2026-03-08

Spring Boot에서 Async와 Executor로 비동기 처리하기

Spring Boot에서 @Async와 TaskExecutor 설정을 통해 비동기 작업의 핵심 원리와 설정 코드, 예외 처리 및 성능 고려사항을 정리한 방법

작성일 : 2026-03-08 ㆍ 작성자 : 관리자
post
목차

개요

비동기 처리는 요청 대기 시간을 줄이고 시스템 처리량을 높인다. Spring Boot는 @Async와 TaskExecutor를 통해 간단하게 비동기 작업을 실행할 수 있다. 처음 접하는 개발자도 이해할 수 있도록 핵심 개념과 설정, 실용적인 코드 예제를 단계별로 설명한다.

비동기 처리의 기본 개념

@Async 애노테이션

@Async는 메서드를 별도 스레드에서 실행하도록 표시한다. 호출 스레드는 결과를 기다리지 않고 즉시 반환한다. 반환 타입으로는 void, Future, CompletableFuture 등을 사용할 수 있다. 결과를 나중에 받아 처리하거나 무시하는 패턴에 적합하다.

Executor 역할

Executor는 비동기 작업을 실행할 스레드 풀을 관리한다. 기본적으로는 SimpleAsyncTaskExecutor 같은 단순 구현이 사용되나, 실제 서비스에서는 ThreadPoolTaskExecutor로 쓰레드 풀을 구성하는 것이 안전하다. task executor spring boot 설정은 스레드 수, 큐 크기, 접두사 설정을 포함한다.

설정 예제

간단한 설정 예제는 다음과 같다. 핵심은 @EnableAsync 활성화와 ThreadPoolTaskExecutor 빈 등록이다.

@Configuration
@EnableAsync
public class AsyncConfig {
    @Bean(name = "taskExecutor")
    public Executor taskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(5);
        executor.setMaxPoolSize(20);
        executor.setQueueCapacity(500);
        executor.setThreadNamePrefix("async-");
        executor.initialize();
        return executor;
    }
}

위 설정은 task executor spring boot 설정 관점에서 기본값을 실무용으로 조정한 예다. 코어와 최대 스레드, 큐 용량을 서비스 특성에 맞춰 조정한다.

서비스와 컨트롤러 예제

비동기 메서드를 서비스에 선언하고 컨트롤러에서 호출하는 패턴을 보인다. 여기서는 CompletableFuture를 사용해 결과를 비동기적으로 받는 예제를 제시한다.

@Service
public class AsyncService {

    @Async("taskExecutor")
    public CompletableFuture<String> longRunningTask() {
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            return CompletableFuture.completedFuture("interrupted");
        }
        return CompletableFuture.completedFuture("done");
    }
}

@RestController
public class DemoController {

    private final AsyncService asyncService;

    public DemoController(AsyncService asyncService) {
        this.asyncService = asyncService;
    }

    @GetMapping("/start")
    public String start() {
        asyncService.longRunningTask();
        return "request received";
    }
}

위 코드는 spring boot @async 사용법을 적용한 간단한 예다. 컨트롤러는 즉시 응답하고, 긴 작업은 백그라운드에서 실행된다.

반환값 처리와 예외 처리

CompletableFuture는 비동기 결과를 조합하거나 에러를 처리하기 쉽다. 예외가 발생할 수 있는 작업은 exceptionally 또는 whenComplete로 후처리한다. 아래는 예외 처리를 추가한 간단한 예다.

asyncService.longRunningTask()
    .exceptionally(ex -> {
        // 로깅 또는 대체값 반환
        return "error";
    })
    .thenAccept(result -> {
        // 결과 처리
    });

또한 @Async 메서드 내부에서 체크 예외를 던지면 호출자가 직접 예외를 받지 못한다. CompletableFuture를 반환하면 예외를 비동기적으로 전달받아 처리할 수 있다.

성능 고려사항

비동기 도입 시에는 다음 항목을 점검한다:

  • 스레드 풀 크기와 큐 용량을 서비스 부하에 맞춰 조정
  • 블로킹 작업이 많다면 스레드 수를 늘리거나 논블로킹 대안을 검토
  • 모니터링과 스레드 덤프 수집으로 데드락과 스레드 고갈 여부 확인
  • 작업 시간 예측이 어려운 경우 타임아웃 로직 적용

테스트 방법

단위 테스트에서는 @Async를 비활성화하거나 동기 실행으로 대체해 검증할 수 있다. 통합 테스트에서는 실제 Executor를 사용해 결과를 기다리거나 CompletableFuture.get을 통해 확인한다. 비동기 로직은 타이밍 이슈가 발생하기 쉬우므로 안정적인 대기 로직을 사용한다.

정리

spring boot @async 사용법과 task executor spring boot 설정을 통해 간단히 비동기 처리를 구현할 수 있다. 핵심은 적절한 Executor 구성, 반환 타입 선택, 예외와 타임아웃 처리다. 이 글에서 소개한 spring boot 비동기 처리 예제를 바탕으로 서비스 특성에 맞춰 튜닝하면 안정적인 비동기 시스템을 구축할 수 있다.

spring boot @async 사용법 task executor spring boot 설정 spring boot 비동기 처리 예제 spring-boot async ThreadPoolTaskExecutor CompletableFuture 비동기 처리