WebClient
**를 사용하여 비동기 방식으로 외부 API를 호출하고, **CompletableFuture
**를 이용하여 병렬 처리를 적용할 예정이다.MyExternalData
**를 processExternalData()
메서드에서 Map으로 처리하였다. 그리고 이 처리된 데이터와 DB에서 가져온 데이터를 함께 **performBusinessLogic()
**에서 사용하여 최종적인 **MyEntity
**를 생성하고 저장하는 로직을 구현하였다.import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.reactive.function.client.WebClient;
import java.util.concurrent.CompletableFuture;
@Service
public class MyOptimizedService {
@Autowired
private MyRepository myRepository;
@Autowired
private CacheService cacheService;
@Autowired
private WebClient.Builder webClientBuilder;
@Transactional
public void optimizedMethod() {
List<MyEntity> entitiesToSave = new ArrayList<>();
// 캐시에서 데이터 가져오기 시도
MyEntity cachedEntity = cacheService.getFromCache(key);
if (cachedEntity != null) {
// 캐시에 데이터가 있을 경우 로직 처리
} else {
// DB에서 데이터 가져오기
List<MyEntity> fetchedEntities = myRepository.findAllByIds(ids);
// 외부 API에서 데이터 가져오기
CompletableFuture<MyExternalData> futureExternalData = webClientBuilder.build()
.get()
.uri("<https://external-api.com/data>")
.retrieve()
.bodyToMono(MyExternalData.class)
.toFuture();
MyExternalData externalData = futureExternalData.join(); // 병렬 처리를 위해 CompletableFuture 사용
// 외부 API에서 가져온 데이터를 로컬에서 처리 (예: Map을 사용)
Map<String, Object> processedData = processExternalData(externalData);
// 로직 처리 (DB + 외부 API 데이터를 이용)
MyEntity updatedEntity = performBusinessLogic(fetchedEntities, processedData);
// 변경된 엔터티를 리스트에 추가
entitiesToSave.add(updatedEntity);
// 캐시 업데이트
cacheService.saveToCache(key, updatedEntity);
}
// 배치 저장
myRepository.saveAll(entitiesToSave);
}
private Map<String, Object> processExternalData(MyExternalData externalData) {
// 외부 데이터 처리 로직
return new HashMap<>();
}
private MyEntity performBusinessLogic(List<MyEntity> fetchedEntities, Map<String, Object> processedData) {
// 비즈니스 로직 처리
return new MyEntity();
}
}
<aside> 📌 근데 CompletableFuture 이거는 WebFlux에서 쓰는게 아니었나?
</aside>
CompletableFuture
**는 Java 8에서 도입된 java.util.concurrent
패키지의 일부이다. 이는 비동기 프로그래밍을 쉽게 하기 위해 사용되며, Spring WebFlux와는 직접적인 관계가 없다.Mono
**와 **Flux
**를 주로 사용한다. 하지만 Spring WebFlux 환경에서도 **CompletableFuture
**를 사용할 수 있다.WebClient
**를 예로 든 것은, 이것이 Spring 5에서 도입된 논블로킹 웹 클라이언트이기 때문이다. **WebClient
**는 기본적으로 Reactor를 사용하지만, .toFuture()
메서드를 통해 **CompletableFuture
**로 변환할 수 있다.CompletableFuture
**는 Java의 표준 라이브러리이며, WebFlux와도, 또는 WebFlux가 아닌 다른 환경과도 잘 작동한다. 이를 통해 비동기 작업을 쉽게 할 수 있다.<aside> 📌 그럼 Spring MVC 즉 @Controller, @RestController를 쓰는 프로젝트에서도 CompletableFuture 이건 자주 사용되는가?
</aside>
CompletableFuture
는 Spring MVC 프로젝트에서도 자주 사용된다.CompletableFuture
를 사용할 수 있다.@Async
애노테이션과 함께 사용하여 비동기 메서드를 쉽게 구현할 수 있다.@Service
public class MyService {
@Async
public CompletableFuture<String> asyncMethod() {
// 비동기로 처리할 로직
return CompletableFuture.completedFuture("result");
}
}
@Controller
또는 @RestController
에서는 이렇게 비동기로 처리된 결과를 받아 응답을 생성할 수 있다.