반응형
CompletableFuture 완벽 이해하기
이전 글에서:
- ExecutorService
- Future
- ThreadPoolExecutor
를 배웠다.
그런데 실무에서는 Future를 거의 직접 쓰지 않는다.
왜냐하면 Future에는 치명적인 문제가 있기 때문이다.
그래서 Java 8에서 등장한 것이:
CompletableFuture
이다.
현재 Spring Boot 실무 비동기 처리에서 가장 많이 사용하는 기술 중 하나다.
1. Future의 문제
예제.
ExecutorService executor =
Executors.newFixedThreadPool(10);
Future<String> future =
executor.submit(() -> {
Thread.sleep(3000);
return "완료";
});
결과 얻기.
String result =
future.get();
2. 문제
future.get();
는
작업 끝날 때까지 대기
한다.
3. 이것을
Blocking
이라고 한다.
예:
3초 작업
↓
3초 동안 Thread 정지
4. 또 다른 문제
Future끼리 연결이 안 된다.
예:
DB 조회
↓
API 호출
↓
결과 가공
Future는 이런 체인을 만들기 어렵다.
5. 그래서 등장
CompletableFuture
6. CompletableFuture란?
한 줄 정의.
비동기 작업을 조합(Compose)할 수 있는 Future
7. 가장 기본 예제
CompletableFuture<String> future =
CompletableFuture.supplyAsync(() -> {
return "Hello";
});
8. 결과 받기
String result =
future.get();
출력.
Hello
9. supplyAsync()
매우 중요.
의미.
반환값 있는 비동기 작업
예:
CompletableFuture<Integer> future =
CompletableFuture.supplyAsync(() -> {
return 100;
});
10. runAsync()
반환값 없는 작업.
CompletableFuture.runAsync(() -> {
System.out.println("실행");
});
11. 차이
메서드반환값
| runAsync() | 없음 |
| supplyAsync() | 있음 |
12. 진짜 강점
작업 연결 가능.
예:
DB 조회
↓
가공
↓
응답 생성
13. thenApply()
가장 많이 사용.
CompletableFuture<String> future =
CompletableFuture.supplyAsync(() -> {
return "hello";
})
.thenApply(value -> {
return value.toUpperCase();
});
결과.
HELLO
14. 흐름
hello
↓
thenApply
↓
HELLO
15. thenAccept()
결과 소비.
future.thenAccept(value -> {
System.out.println(value);
});
반환 없음.
16. thenRun()
결과도 필요 없고
그냥 다음 작업.
future.thenRun(() -> {
System.out.println("완료");
});
17. 실무 예제
회원 조회.
CompletableFuture<User> future =
CompletableFuture.supplyAsync(
() -> userRepository.findById(1L)
);
가공.
future.thenApply(
user -> user.getName()
);
18. thenCompose()
면접 단골.
예:
API1 호출
↓
결과 이용
↓
API2 호출
19. 잘못된 방식
CompletableFuture<
CompletableFuture<String>
>
생성.
중첩 Future.
20. 해결
thenCompose()
예:
CompletableFuture<String> future =
getUser()
.thenCompose(
user -> getOrder(user)
);
21. 의미
Future 평탄화
22. thenApply vs thenCompose
매우 중요.
thenApply
A → B
thenCompose
A → Future<B>
23. 그림
thenApply
A
↓
B
thenCompose
A
↓
Future<B>
24. allOf()
실무 중요.
여러 작업 병렬 실행.
CompletableFuture<User> userFuture =
getUser();
CompletableFuture<Order> orderFuture =
getOrder();
25. 병렬 실행
CompletableFuture.allOf(
userFuture,
orderFuture
);
26. 의미
둘 다 끝날 때까지 대기
27. 그림
User 조회
↘
allOf
↗
Order 조회
28. 실무 예시
쇼핑몰.
회원 정보 조회
주문 조회
포인트 조회
동시에 수행.
29. 순차 실행
1초
+
1초
+
1초
=
3초
30. 병렬 실행
1초
정도.
31. exceptionally()
예외 처리.
future.exceptionally(ex -> {
log.error("오류", ex);
return "기본값";
});
32. 의미
예외 발생 시 대체값 반환
33. handle()
더 강력함.
future.handle((result, ex) -> {
});
둘 다 접근 가능.
정상 결과
또는
예외
34. whenComplete()
후처리.
future.whenComplete(
(result, ex) -> {
log.info("완료");
}
);
35. ForkJoinPool
매우 중요.
기본적으로.
CompletableFuture.supplyAsync(...)
는
ForkJoinPool.commonPool()
사용.
36. 문제
실무에서는 위험.
공용 Pool 사용.
트래픽 많으면.
서로 영향
줄 수 있음.
37. 실무 방식
Executor 지정.
CompletableFuture.supplyAsync(
() -> doWork(),
executor
);
38. Spring @Async 연결
실무 핵심.
@Async
public CompletableFuture<User>
findUser() {
return CompletableFuture.completedFuture(
user
);
}
Spring 내부.
ThreadPoolTaskExecutor
사용.
39. completedFuture()
즉시 완료.
CompletableFuture.completedFuture(
"OK"
);
이미 완료된 Future 반환.
40. Future vs CompletableFuture
항목FutureCompletableFuture
| 결과 조회 | O | O |
| 체이닝 | X | O |
| 예외 처리 | 제한적 | 강력 |
| 병렬 조합 | X | O |
| 실무 사용 | 적음 | 많음 |
41. 면접 단골 질문
Q. Future와 CompletableFuture 차이는?
CompletableFuture는
비동기 작업 조합 가능
Q. thenApply와 thenCompose 차이는?
thenApply
=
값 변환
thenCompose
=
Future 연결
Q. allOf는?
여러 Future 병렬 처리
Q. supplyAsync 기본 ThreadPool은?
ForkJoinPool.commonPool()
Q. 실무에서 supplyAsync만 쓰나요?
아니오
Executor 지정
42. 실무 예제
매우 흔한 패턴.
CompletableFuture<User> user =
getUser();
CompletableFuture<Order> order =
getOrder();
CompletableFuture<Point> point =
getPoint();
CompletableFuture.allOf(
user,
order,
point
).join();
기존.
1초
+
1초
+
1초
=
3초
병렬.
약 1초
43. 지금까지 흐름 연결
Thread
↓
Runnable
↓
ExecutorService
↓
ThreadPoolExecutor
↓
Future
↓
CompletableFuture
44. 핵심 흐름 요약
비동기 작업 생성
↓
CompletableFuture
↓
thenApply
↓
thenCompose
↓
allOf
↓
exceptionally
↓
완료
45. 가장 중요한 핵심 한 줄
CompletableFuture는 Future의 한계를 해결하여 비동기 작업의 조합, 병렬 처리, 예외 처리, 후속 작업 연결을 가능하게 하는 Java의 현대적인 비동기 프로그래밍 도구이다.
46. 다음 글 예고
다음 글은:
ForkJoinPool
이다.
여기서부터는:
Work Stealing
RecursiveTask
RecursiveAction
Parallel Stream
CompletableFuture
가 모두 어떻게 연결되는지 배우게 된다.
그리고 왜 parallelStream()이 내부적으로 ForkJoinPool을 사용하는지도 이해하게 된다.
반응형
'language > java' 카테고리의 다른 글
| ReentrantLock 완벽 이해하기 (0) | 2026.06.01 |
|---|---|
| ForkJoinPool 완벽 이해하기 (0) | 2026.06.01 |
| ThreadPool 구조 완벽 이해하기 (0) | 2026.06.01 |
| ExecutorService 완벽 이해하기 (0) | 2026.06.01 |
| Thread-safe 컬렉션 완벽 이해하기 (0) | 2026.05.29 |
댓글