<aside> 📖
학습 목표
@Async 메서드의 void, Future, CompletableFuture 차이를 구분합니다.비동기(@Async) 메서드는 호출 즉시 반환되고, 실제 로직은 별도의 스레드에서 수행됩니다.
이때 예외가 발생하면, 반환 타입에 따라 예외 전파 방식이 완전히 달라집니다.
| 반환 타입 | 예외 전파 여부 | 예외 확인 방법 |
|---|---|---|
void |
❌ 호출자에게 전파되지 않음 | AsyncUncaughtExceptionHandler 필요 |
Future<T> |
⭕ get() 호출 시 예외 확인 가능 |
ExecutionException 내부로 래핑되어 전달 |
CompletableFuture<T> |
⭕ 체이닝 내에서 직접 처리 가능 | exceptionally(), handle() 메서드 사용 |
@Async 메서드가 void를 반환하면, 비동기 스레드에서 발생한 예외는 호출자에게 전달되지 않습니다.
즉, 메인 스레드는 예외를 감지할 방법이 없습니다.
@Service
public class MailService {
@Async
public void sendEmail(String address) {
System.out.println("[Async Thread] 이메일 발송 시작: " + address);
if (address == null) {
throw new IllegalArgumentException("이메일 주소가 null입니다.");
}
System.out.println("[Async Thread] 이메일 발송 완료");
}
}
@RestController
@RequiredArgsConstructor
public class MailController {
private final MailService mailService;
@PostMapping("/send")
public String sendMail(@RequestParam(required = false) String email) {
mailService.sendEmail(email); // 예외가 발생해도 여기서는 잡히지 않음
System.out.println("[Main Thread] 요청 완료");
return "메일 전송 요청 완료";
}
}
[Main Thread] 요청 완료
[Async Thread] 이메일 발송 시작: null
Exception in thread "task-1" java.lang.IllegalArgumentException: 이메일 주소가 null입니다.
즉, 예외는 비동기 스레드(task-1) 에서 발생하지만, 호출자는 이를 감지할 방법이 없습니다.