Spring에서는 @Async 어노테이션 기반으로 비동기 호출을 쉽게 할 수 있습니다.
다만 Proxy 기반으로 동작을 하다보니 동일 클래스의 다른 메서드에서 호출하는 경우
Proxy가 아닌 본래 메서드를 직접 호출하기 때문에 Async로 동작하지 않습니다.
이 때 클래스를 분리해서 해결할 수 있지만 비동기 처리만을 위해 클래스를 분리하기가 애매할 때가 많습니다.
이런 경우에는 아래와 같이 Async 처리만을 위한 별도 서비스를 두어 해결해 볼 수도 있습니다.
@Service
public class AsyncService {
@Async
public <R> CompletableFuture<R> callInternalMethodAsAsync(Supplier<CompletableFuture<R>> supplier) {
return supplier.get();
}
}
해당 서비스를 사용하는 코드는 아래와 같습니다.
@RequiredArgsConstructor
public class FooService {
private final AsyncService asyncService;
@Async
public CompletableFuture<List<String>> findManyFooNames(List<Long> fooIds) {
var fooNameFutures = fooIds.stream()
.map(fooId -> asyncService.callInternalMethodAsAsync(
() -> findFooName(fooId))
).toList();
return CompletableFuture.completedFuture(
fooNameFutures.stream()
.map(AsyncUtils::get)
.toList()
);
}
@Async
public CompletableFuture<String> findFooName(Long fooId) {
return CompletableFuture.completedFuture("Bar" + fooId);
}
}
AsyncUtils는 제가 편의를 위핸 만든 Util로 아래와 같은 형태로 되어 있습니다.
public class AsyncUtils {
public static <R> R get(CompletableFuture<R> future) {
try {
return future.get();
} catch (Exception e) {
throw new CustomAsyncExecutionException(e);
}
}
}
'제안&정리' 카테고리의 다른 글
[SQL] join에서 on vs where (0) | 2023.10.08 |
---|---|
[Spock] 쉽게 테스트 작성하기 (0) | 2023.08.27 |
[JAVA] IntelliJ로 class -> record 변환 (0) | 2023.06.25 |
2023 AWS Summit Seoul Session Review (Day1) (0) | 2023.05.05 |
[AWS] EB에서 인스턴스 분리하기 (1) | 2023.04.03 |