2025. 7. 2. 16:23ㆍSpring
Java로 프로젝트를 하다 보면 CompletableFuture, 비동기, 체이닝, 병렬 처리 같은 용어를 자주 듣게 됩니다. 처음에는 어렵게 느껴지지만, 실제 개념은 꽤 간단합니다. 이번 글에서는 이 개념들을 아주 쉽게 설명하고, 실제 현업에서 어떻게 활용되는지 보여드리겠습니다. 마지막에는 이 모든 개념을 더 쉽게 사용할 수 있게 도와주는 AsyncChain<T> 클래스도 함께 소개할게요.
1️⃣ 동기(Synchronous) vs 비동기(Asynchronous)
🔸 동기 처리란?
코드가 한 줄씩 순서대로 실행되고, 앞 작업이 끝나야 다음 작업으로 넘어가는 방식입니다.
System.out.println("A");
Thread.sleep(1000); // 1초 멈춤
System.out.println("B");
// 출력---------------------
A
(1초 후) B
🔸 비동기 처리란?
앞 작업이 끝나기를 기다리지 않고, 다음 작업을 바로 수행합니다. 주로 CompletableFuture를 통해 구현합니다.
CompletableFuture.runAsync(() -> {
try {
Thread.sleep(1000);
System.out.println("비동기 작업 완료");
} catch (InterruptedException e) {}
});
System.out.println("메인 쓰레드는 계속 진행됨");
// 출력------------------------------------
메인 쓰레드는 계속 진행됨
(1초 후) 비동기 작업 완료
2️⃣ 병렬 처리란?
여러 작업을 동시에 처리하는 것을 의미합니다. 주로 CompletableFuture를 여러 개 실행하고 allof로 기다립니다.
List<Integer> numbers = Arrays.asList(1, 2, 3);
List<CompletableFuture<Void>> futures = numbers.stream()
.map(n -> CompletableFuture.runAsync(() -> {
System.out.println("작업: " + n);
}))
.collect(Collectors.toList());
CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join();
// 결과는 실행 순서에 상관없이 "작업: 1", "작업: 2", "작업: 3"이 동시에 출력됩니다.
3️⃣ 체이닝(Chaining)이란?
비동기 작업들을 순차적으로 연결해서 실행하는 방식입니다. 앞의 결과를 다음 작업에 넘길 수 있어요.
덕분에 코드가 더 간결하고 읽기 쉬워집니다.
CompletableFuture.supplyAsync(() -> 10)
.thenApply(x -> x * 2) // 10 * 2 → 20
.thenApply(x -> x + 3) // 20 + 3 → 23
.thenAccept(System.out::println); // 출력: 23
4️⃣ AsyncChain<T> 클래스 소개
Java의 CompletableFuture는 강력하지만 문법이 다소 복잡하고 가독성이 떨어질 수 있습니다. 그래서 AsyncChain<T>는 다음과 같은 목적을 가지고 만들어졌습니다.
✅ 비동기, ✅ 병렬 처리, ✅ 체이닝을 더 쉽게 사용하도록 도와주는 유틸리티 클래스입니다.
📌 기본 사용법
AsyncChain.supply(() -> 10)
.map(x -> x * 2) // 20
.flatMap(x -> AsyncChain.of(x + 5)) // 25
.onSuccess(System.out::println); // 출력: 25
📌 주요 기능 요약
| 기능 | 메서드 |
| 비동기 작업 시작 | supply, of, supplyAll |
| 값 변환 | map, flatMap |
| 병렬 처리 | mapParallel, combineAll |
| 조건 분기 | filter, doIf |
| 예외 처리 | recover, orElse, onFailure |
| 완료 후 처리 | onSuccess, whenComplete |
| 타임아웃, 재시도 | timeout, retry |
📌 병렬 처리 예시
AsyncChain.ofAll(1, 2, 3, 4)
.mapParallel(x -> x * 2)
.onSuccess(result -> System.out.println("결과: " + result));
// 출력 예시:
결과: [2, 4, 6, 8] (순서는 비보장)
5️⃣ 실제 예시: 웹 API 비동기 처리
AsyncChain.supply(() -> userId)
.flatMap(id -> AsyncChain.of(userRepository.findById(id))) // DB 조회
.map(user -> user.getPoint())
.map(point -> point * 1.1) // 포인트 계산
.onSuccess(result -> System.out.println("최종 포인트: " + result))
.onFailure(Throwable::printStackTrace);
✅ 마무리:
| 개념 | 쉬운 설명 |
| 비동기 | 기다리지 않고 다음 작업 먼저 |
| 병렬 처리 | 여러 작업을 동시에 처리 |
| 체이닝 | 결과를 이어서 작업 연결 |
| AsyncChain | 위 3개를 쉽게 쓰도록 도와주는 클래스 |
AsyncChain<T>는 실무에서 자주 반복되는 패턴(비동기, 체이닝, 예외 처리, 병렬 처리)을 쉽고 깔끔하게 사용할 수 있도록 만들어진 유틸리티입니다. 초보자라도 기본 개념만 이해하면 바로 활용할 수 있고, 실무 생산성도 크게 향상됩니다.
'Spring' 카테고리의 다른 글
| 🌟 Java 초보 개발자를 위한 비동기 체이닝 클래스 만들기: AsyncChain<T> 완전 분석 (3) | 2025.07.02 |
|---|