Java에서 비동기 프로그래밍은 높은 성능과 확장성을 필요로 하는 애플리케이션에서 필수적인 요소입니다. 비동기 처리를 통해 I/O 작업을 효율적으로 수행하고, 응답 시간을 단축할 수 있습니다. Java는 CompletableFuture
와 Reactive Streams
를 활용하여 비동기 프로그래밍을 효과적으로 구현하는 방법에 대해 알아 보겠습니다.
1. Java에서 비동기 프로그래밍이 필요한 이유
1) 블로킹(Blocking) vs. 비블로킹(Non-Blocking)
Thread.sleep()
사용)CompletableFuture
)2) 비동기 프로그래밍의 장점
Java는 CompletableFuture
와 Reactive Streams
를 활용하여 이러한 문제를 해결합니다.
2. CompletableFuture를 이용한 비동기 처리
1) 기본적인 CompletableFuture 사용법
import java.util.concurrent.CompletableFuture;
public class CompletableFutureExample {
public static void main(String[] args) {
CompletableFuture.supplyAsync(() -> {
return "Hello, CompletableFuture!";
}).thenAccept(System.out::println);
}
}
supplyAsync()
는 별도의 스레드에서 실행합니다.thenAccept()
를 사용해 결과가 준비되면 실행합니다.2) 여러 작업을 병렬 실행하기
import java.util.concurrent.CompletableFuture;
public class ParallelTasks {
public static void main(String[] args) {
CompletableFuture<String> task1 = CompletableFuture.supplyAsync(() -> "Task 1 완료");
CompletableFuture<String> task2 = CompletableFuture.supplyAsync(() -> "Task 2 완료");
task1.thenCombine(task2, (result1, result2) -> result1 + " & " + result2)
.thenAccept(System.out::println);
}
}
thenCombine()
을 사용하여 두 개의 작업을 동시에 실행하고 결과를 조합을 합니다.3) 예외 처리
CompletableFuture.supplyAsync(() -> {
if (Math.random() > 0.5) throw new RuntimeException("에러 발생");
return "성공";
}).exceptionally(ex -> "예외 발생: " + ex.getMessage())
.thenAccept(System.out::println);
exceptionally()
를 활용하여 예외 발생 시 대체 값 제공합니다.3. Reactive Streams를 이용한 비동기 처리
1) Reactive Streams란?
Reactive Streams는 비동기 데이터 흐름을 처리하는 표준 API입니다. 주요 구현체로는 Project Reactor(Spring WebFlux), RxJava 등이 있습니다.
Reactive Streams의 주요 개념:
2) Reactor를 활용한 비동기 스트림 처리
import reactor.core.publisher.Flux;
public class ReactiveExample {
public static void main(String[] args) {
Flux.just("데이터 1", "데이터 2", "데이터 3")
.map(String::toUpperCase)
.subscribe(System.out::println);
}
}
Flux.just()
는 여러 개의 데이터를 스트림으로 생성합니다.map()
을 통해 데이터를 변환 가능합니다.subscribe()
를 호출해야 데이터가 전송됩니다.3) 비동기 데이터 스트림 결합하기
import reactor.core.publisher.Mono;
public class ReactiveCombine {
public static void main(String[] args) {
Mono<String> task1 = Mono.just("Task 1 완료");
Mono<String> task2 = Mono.just("Task 2 완료");
task1.zipWith(task2, (result1, result2) -> result1 + " & " + result2)
.subscribe(System.out::println);
}
}
Mono.zipWith()
를 사용하여 두 개의 작업을 병렬로 실행하고 결과를 결합합니다.4) 백프레셔(Backpressure) 처리
Reactive Streams는 과도한 데이터 흐름을 조절하는 백프레셔(Backpressure) 개념을 지원합니다.
Flux.range(1, 1000)
.onBackpressureDrop()
.subscribe(System.out::println);
onBackpressureDrop()
을 사용하면 처리할 수 없는 데이터는 자동으로 폐기됩니다.4. CompletableFuture vs. Reactive Streams 비교
기능 | CompletableFuture | Reactive Streams |
---|---|---|
동시 실행 | O | O |
데이터 스트림 처리 | X | O |
콜백 기반 | O | O |
백프레셔 지원 | X | O |
사용 용도 | 단일 작업 비동기 처리 | 대량 데이터 흐름 처리 |
CompletableFuture
는 단일 또는 병렬 작업을 수행할 때 적합합니다.Reactive Streams
는 대량의 데이터를 실시간으로 처리할 때 유용합니다.결론
Java의 비동기 처리인 CompletableFuture와 Reactive Streams에 대해 알아 보겠습니다. Java의 비동기 프로그래밍은 성능 최적화와 응답 시간 단축에 필수적인 요소이며, CompletableFuture
는 단일 작업의 비동기 실행에 적합하며, Reactive Streams
는 대규모 데이터 스트림 처리에 유용하니 이 방법을 배워 효율적인 프로그램을 개발해 보시길 바랍니다.
오키나와 나하공항에 도착하거나 돌아가는 길, 바쁜 비행 일정에 쫓겨 허겁지겁 평범한 음식으로 끼니를 대충 때우신…
간사이 여행을 계획 중이신가요? 오사카, 교토, 고베를 아우르는 간사이 지역 여행에서 가장 중요한 필수품이 바로…
일본으로의 여행을 꿈꾸며 설레는 마음으로 출발을 준비할 때, 반드시 잊지 말아야 할 부분이 있습니다. 그것은…
일본여행의 준비 청소년 시기, 가장 많이 꿈꾸는 ‘해외여행’. 그 중에서도 한국에서 가깝고 볼거리·즐길거리도 다양해 많은…