<aside> 📖

학습 목표


1. @Async 활용 시 제약사항

이전 학습에서 @Async를 사용하면 손쉽게 비동기 처리를 구현할 수 있음을 배웠습니다. 하지만 실무에서는 단순히 어노테이션을 추가하는 것만으로 끝나지 않습니다. Spring의 @Async프록시 기반 AOP 구조로 동작하기 때문에, 몇 가지 중요한 제약사항이 존재합니다.

이 단원에서는 @Async의 동작이 왜 특정 상황에서 비활성화되는지, 그리고 이를 올바르게 사용하는 방법을 실제 코드와 함께 학습합니다.


1-1. 프록시 기반 동작의 이해

Spring의 @AsyncAOP(Aspect-Oriented Programming) 기술을 활용하여 프록시 객체를 통해 동작합니다. 즉, 비동기 메서드가 호출될 때, 실제 대상 객체가 아닌 프록시 객체(Proxy) 가 메서드 실행을 가로채어 비동기로 위임합니다.

다운로드.svg

➡️ 즉, @Async프록시를 통해 호출되어야만 비동기 실행이 이루어집니다.

프록시를 거치지 않고 직접 호출할 경우, 일반 메서드 호출과 동일하게 동기적으로 실행됩니다.


1-2. 자가 호출(Self Invocation) 문제

Spring의 @Async같은 클래스 내부에서 메서드를 호출할 경우 동작하지 않습니다. 이 현상을 Self Invocation(자가 호출) 문제라고 합니다.

1-2-1. 예시: 비동기로 동작하지 않는 코드

@Service
public class DataService {

    @Async
    public CompletableFuture<String> loadData() {
        System.out.println(Thread.currentThread().getName() + " - 데이터 로드 중...");
        return CompletableFuture.completedFuture("로드 완료");
    }

    public void execute() {
        // 같은 클래스 내부 호출 → 프록시 미적용 → 비동기 아님
        loadData();
    }
}

실행 결과:

main - 데이터 로드 중...

➡️ @Async가 적용된 loadData()를 내부에서 직접 호출하므로, 프록시를 거치지 않아 동기 실행됩니다.