<aside> 📖
학습 목표
@Async가 프록시 기반으로 동작하는 구조를 이해합니다.@Async가 접근 제한자에 따라 어떻게 다르게 동작하는지 이해합니다.이전 학습에서 @Async를 사용하면 손쉽게 비동기 처리를 구현할 수 있음을 배웠습니다.
하지만 실무에서는 단순히 어노테이션을 추가하는 것만으로 끝나지 않습니다.
Spring의 @Async는 프록시 기반 AOP 구조로 동작하기 때문에, 몇 가지 중요한 제약사항이 존재합니다.
이 단원에서는 @Async의 동작이 왜 특정 상황에서 비활성화되는지,
그리고 이를 올바르게 사용하는 방법을 실제 코드와 함께 학습합니다.
Spring의 @Async는 AOP(Aspect-Oriented Programming) 기술을 활용하여 프록시 객체를 통해 동작합니다.
즉, 비동기 메서드가 호출될 때, 실제 대상 객체가 아닌 프록시 객체(Proxy) 가 메서드 실행을 가로채어 비동기로 위임합니다.
➡️ 즉, @Async는 프록시를 통해 호출되어야만 비동기 실행이 이루어집니다.
프록시를 거치지 않고 직접 호출할 경우, 일반 메서드 호출과 동일하게 동기적으로 실행됩니다.
Spring의 @Async는 같은 클래스 내부에서 메서드를 호출할 경우 동작하지 않습니다.
이 현상을 Self Invocation(자가 호출) 문제라고 합니다.
@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()를 내부에서 직접 호출하므로, 프록시를 거치지 않아 동기 실행됩니다.