@Async

Hannah·2023년 2월 1일
0

java

목록 보기
1/1
post-thumbnail

사용법 (Spring Boot)

spring boot에서 @Async를 사용하는 방법은 간단합니다
1. applicationClass에 @EnableAsync를 선언합니다

@EnableAsync
@SpringBootApplication
public class SpringBootApplication {
    ...
}
  1. 비동기로 작동하길 원하는 로직 함수 위에 @Async annotation을 붙어줍니다
public class AsyncClass {
	
    @Async
    public void asyncMethod(String param) {
    	...
    }
    
}

설정

spring은 기본값으로 SimpleAsyncTaskExecutor를 사용하여 실제 메소드들을 비동기로 실행합니다
설정은 두 가지 레벨로 오버라이드할 수 있습니다
1. 메소드 레벨로 실행자 오버라이드 하기
설정 코드

@Configuration
@EnableAsync // 설정 클래스에 붙이기
public class SpringAsyncConfig {
     
    @Bean(name = "threadPoolTaskExecutor")
    public Executor threadPoolTaskExecutor() {
        return new ThreadPoolTaskExecutor();
    }
}

사용 코드 : 속성 값으로 사용합니다 (bean의 이름값)

@Async("threadPoolTaskExecutor")
public void asyncMethodWithConfiguredExecutor() {
    System.out.println("Execute method with configured executor - "  + Thread.currentThread().getName());
}
  1. 어플리케이션 레벨로 실행자 오버라이드 하기
    설정 코드 : AsyncConfigurer를 구현해줍니다
@Configuration
@EnableAsync // 설정 클래스에 붙이기
public class SpringAsyncConfig implements AsyncConfigurer {
     
    @Override
    public Executor getAsyncExecutor() {
        return new ThreadPoolTaskExecutor();
    }
     
}
  1. 옵션

커스텀 설정이나, 풀을 사용할 때에는 application class에서 @EnableAsync를 제거합니다
런타임 시 @Configuration이 설정된 AsyncConfig 클래스를 읽어들이기 때문입니다


리턴 타입

  1. Future
  • 메소드의 결과를 전달받아야 한다면, Future를 사용해야 합니다
  • 스프링에서 제공하는 AsyncResult는 Future의 구현체 입니다

비동기 메소드

@Async
public Future<String> getFuture(String str) throws InterruptedException {
	...
	return new AsyncResult<>(str);
}

비동기 메소드 사용 코드

Future<String> future = service.getFuture("test");
future.get();
  • future의 get 메소드는 결과를 조회할 때까지 계속 기다립니다
  • 즉, 메서드의 수행이 완료될 때 까지 기다려야하며, 블록킹 현상이 발생합니다
  1. Listenablefuture

비동기 메소드

@Async
public ListenableFuture<String> getFuture(String str) throws InterruptedException {
	...
	return new AsyncResult<>(str);
}

비동기 메소드 사용 코드

Listenablefuture<String> future = service.getFuture("test");
future.addCallback(f -> log.info("{}", f));
  • addCallback 메소드는 비동기 메소드의 내부 로직이 완료되면 수행되는 콜백 기능입니다
  1. CompletableFuture

비동기 메소드

@Async
public CompletableFuture<String> getFuture(String str) throws InterruptedException {
	...
	return new AsyncResult<>(str).completable();
}

비동기 메소드 사용 코드

CompletableFuture<String> future = service.getFuture("test");
future.thenAccept(f -> log.info("{}", f));

에러 처리

  1. 리턴 타입이 Future 타입인 경우

구현 코드 : AsyncUncaughtExceptionHandler를 상속받습니다

@Configuration
@EnableAsync
public class AsyncExceptionHandler implements AsyncConfigurer {
    @Override
    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
        return new CustomAsyncExceptionHandler();
    }
}
  1. 리턴 타입이 void인 경우

구현 코드 : 리턴 타입인 void인 경우 예회가 호출 스레드로 전파되지 않기 때문에 따로 예외처리를 해주어야합니다

public class AsyncExceptionHandler implements AsyncUncaughtExceptionHandler {

    @Override
    public void handleUncaughtException(Throwable ex, Method method, Object... params) {
	    ...
    }
}

주의사항

  1. private method는 사용이 불가합니다
    • @Async의 동작은 AOP가 적용됩니다 (@Async가 적용된 method의 경우 스프링이 메소드를 가로채 다른 스레드에서 실행 시켜주는 동작 방식입니다)
    • 떼문에 Spring이 @Async 메소드를 가로챈 후, 다른 클래스에서 호출이 가능해야하므로 privat 메소드는 사용할 수 없습니다
  2. self-invocation은 불가합니다 (inner method)
    • 같은 객체 내의 메소드끼리 호출할 시 AOP가 동작하지 않기 때문에 비동기로 동작하지 않습니다.

읽어주셔서 감사합니다!

참고 사이트

https://spring.io/guides/gs/async-method/

https://steady-coding.tistory.com/611

https://velog.io/@gillog/Spring-Async-Annotation%EB%B9%84%EB%8F%99%EA%B8%B0-%EB%A9%94%EC%86%8C%EB%93%9C-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0

https://brunch.co.kr/@springboot/401

profile
backend developer

0개의 댓글