목차

1. @Async에서 예외 처리의 한계

2. Spring Retry와 @Retryable의 활용

3. 예시 코드

4. 유의사항

5. 마무리

태그

#SPRINGBOOT

#ASYNC

#ERROR

#RETRYABLE

Spring @Async 실패 시 자동 재실행(재시도) 방법 정리

2025년 6월 17일 19:58

68-thumbnail-image

Spring에서 비동기 작업을 처리할 때 @Async 어노테이션을 자주 사용합니다. 하지만 비동기 메서드에서 예외가 발생했을 때, 이를 자동으로 재실행(재시도)하고 싶다면 어떻게 해야 할까요? 이번 글에서는 Spring Retry 라이브러리를 활용해 @Async 메서드의 실패 시 자동 재실행 방법을 정리합니다.


1. @Async에서 예외 처리의 한계

@Async가 붙은 메서드는 별도의 스레드에서 실행되기 때문에, 예외가 발생해도 호출자에게 바로 전달되지 않습니다.
따라서 단순히 try-catch로는 예외 상황을 감지하거나, 자동으로 재실행하는 것이 어렵습니다.


2. Spring Retry와 @Retryable의 활용

이럴 때 사용할 수 있는 것이 바로 Spring Retry 라이브러리입니다.
@Retryable 어노테이션을 사용하면 지정한 예외가 발생했을 때 자동으로 재시도할 수 있습니다.

적용 방법

  • 설정 파일에 @EnableAsync@EnableRetry를 추가합니다.
  • 비동기 메서드에 @Async@Retryable을 함께 붙입니다.
  • @Retryable의 속성(maxAttempts, backoff 등)으로 재시도 횟수와 간격을 설정할 수 있습니다.
  • 모든 재시도에도 실패하면 @Recover 메서드가 호출되어 후처리를 할 수 있습니다.

3. 예시 코드

@EnableAsync
@EnableRetry
@Configuration
public class AppConfig {}

@Async
@Retryable(
    value = {RuntimeException.class}, // 재시도할 예외 타입
    maxAttempts = 4,                  // 최대 4번 시도
    backoff = @Backoff(delay = 2000)  // 2초 간격
)
public void asyncMethod(String param) {
    // 실패 가능성이 있는 로직
    throw new RuntimeException("실패!");
}

@Recover
public void recover(RuntimeException e, String param) {
    // 모든 재시도 실패 시 실행되는 복구 로직
}

4. 유의사항

  • @Async@Retryable은 반드시 public 메서드에만 적용해야 하며, 같은 클래스 내에서 자기 자신을 호출하면 프록시가 적용되지 않아 동작하지 않습니다.
  • 반환 타입이 Future, CompletableFuture 등일 경우 호출부에서 예외를 직접 확인할 수도 있습니다.
  • Spring Retry를 사용하지 않고 직접 재시도 로직을 구현하려면, 실패 이벤트를 기록하고 스케줄러로 재실행하는 방법도 있습니다.

5. 마무리

Spring에서는 @Async@Retryable을 함께 사용함으로써, 비동기 작업의 실패 시 자동 재실행을 손쉽게 구현할 수 있습니다.
여기에 @Recover 메서드를 활용하면, 모든 재시도 실패 시에도 안정적으로 후처리를 할 수 있습니다.

비동기 작업의 신뢰성과 안정성을 높이고 싶을 때 위 방법을 적극적으로 활용해보세요!