본문 바로가기
spring

[Spring] CompletableFuture 주요 함수들

by goblin- 2025. 1. 17.

CompletableFuture는 비동기 프로그래밍에서 다양한 함수들을 제공하여 작업의 실행, 결과 처리, 작업 병합, 에러 처리 등을 간편하게 수행할 수 있도록 합니다. 아래에서 주요 함수들과 그 기능에 대해 설명하겠습니다.

 

1. 비동기 작업 실행

 

1.1 runAsync

결과값을 반환하지 않는 비동기 작업을 실행.

주로 Runnable을 실행할 때 사용.

기본적으로 ForkJoinPool을 사용하지만, Executor를 지정할 수도 있음.

CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
    System.out.println("비동기 작업 실행!");
});

 

1.2 supplyAsync

결과값을 반환하는 비동기 작업을 실행.

주로 Supplier를 실행할 때 사용.

CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
    return "비동기 작업 결과";
});

 

2. 작업 완료 후 결과 처리

 

2.1 thenApply

작업 완료 후 결과를 받아 새로운 결과를 반환.

Function을 사용하여 결과를 변환 가능.

future.thenApply(result -> result + " 변환됨")
      .thenAccept(System.out::println);

 

2.2 thenAccept

작업 완료 후 결과를 받아 소비(출력, 저장 등)만 하고 반환값은 없음.

future.thenAccept(result -> {
    System.out.println("결과 처리: " + result);
});

 

2.3 thenRun

작업 완료 후 결과를 사용하지 않고 단순 작업 실행.

future.thenRun(() -> {
    System.out.println("작업 완료 후 실행");
});

 

3. 작업 조합 및 체이닝

 

3.1 thenCompose

이전 작업의 결과를 입력으로 받아 새로운 비동기 작업 실행.

flatMap과 유사하며, CompletableFuture의 결과를 연결할 때 사용.

CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> "Hello");
CompletableFuture<String> future2 = future1.thenCompose(result -> 
    CompletableFuture.supplyAsync(() -> result + " World")
);
future2.thenAccept(System.out::println); // Hello World

 

3.2 thenCombine

두 개의 CompletableFuture 결과를 조합하여 새로운 결과 생성.

두 작업이 모두 완료될 때 실행됨.

CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> "Hello");
CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> "World");

future1.thenCombine(future2, (result1, result2) -> result1 + " " + result2)
       .thenAccept(System.out::println); // Hello World

 

3.3 allOf

여러 비동기 작업을 병렬로 실행하고, 모든 작업 완료 후 실행.

반환값은 CompletableFuture<Void>이므로 개별 결과는 수동으로 처리해야 함.

CompletableFuture<Void> allOf = CompletableFuture.allOf(future1, future2);
allOf.thenRun(() -> System.out.println("모든 작업 완료"));

 

3.4 anyOf

여러 비동기 작업 중 하나라도 완료되면 실행.

반환값은 가장 먼저 완료된 CompletableFuture의 결과.

CompletableFuture<Object> anyOf = CompletableFuture.anyOf(future1, future2);
anyOf.thenAccept(System.out::println);

 

 

4. 에러 처리

 

4.1 exceptionally

작업 중 예외가 발생했을 때, 기본값 또는 대체 동작을 수행.

future.exceptionally(ex -> {
    System.out.println("예외 처리: " + ex.getMessage());
    return "대체 결과";
});

 

4.2 handle

작업 완료 후 결과 또는 예외를 처리.

결과와 예외를 동시에 처리할 수 있어 유용.

future.handle((result, ex) -> {
    if (ex != null) {
        System.out.println("예외 처리: " + ex.getMessage());
        return "대체 결과";
    }
    return result + " 성공";
}).thenAccept(System.out::println);

 

 

5. 기타 유용한 함수들

 

5.1 complete

수동으로 작업 결과를 설정.

주로 테스트나 예외 상황에서 사용.

CompletableFuture<String> future = new CompletableFuture<>();
future.complete("수동 결과");
System.out.println(future.join()); // 수동 결과

 

5.2 join

작업이 완료될 때까지 대기하고 결과를 반환.

get()과 유사하지만, ExecutionException 대신 CompletionException을 발생시킴.

String result = future.join();

 

5.3 isDone

작업이 완료되었는지 확인.

if (future.isDone()) {
    System.out.println("작업 완료!");
}

 

 

6. 커스텀 Executor

 

모든 비동기 작업은 기본적으로 ForkJoinPool.commonPool()에서 실행됩니다. 커스텀 Executor를 지정하여 제어할 수도 있습니다.

Executor executor = Executors.newFixedThreadPool(4);
CompletableFuture.supplyAsync(() -> "Hello", executor)
                 .thenAcceptAsync(result -> System.out.println(result), executor);

 

요약

작업 실행: runAsync, supplyAsync

결과 처리: thenApply, thenAccept, thenRun

작업 조합: thenCompose, thenCombine, allOf, anyOf

에러 처리: exceptionally, handle

기타: complete, join, isDone