BE/Java

[Java] 비동기 처리 (try-catch)

baek-dev 2025. 3. 28. 19:18

자바에서 비동기 처리 시 예외 처리 (try-catch)

 

자바에서 비동기 처리(Asynchronous Processing) 를 할 때 예외(Exception)를 적절하게 처리하는 것은 매우 중요함.

비동기 코드에서는 기존의 try-catch 문이 제대로 동작하지 않을 수 있기 때문에 별도의 예외 처리 방식을 적용해야 함.

 


1️⃣ 기본적인 try-catch 블록 (동기 코드에서 예외 처리)

 

동기(Synchronous) 코드에서는 try-catch 블록을 사용하여 예외를 쉽게 처리할 수 있음.

public class SyncTryCatchExample {
    public static void main(String[] args) {
        try {
            int result = 10 / 0; // 예외 발생 (ArithmeticException)
            System.out.println(result);
        } catch (ArithmeticException e) {
            System.out.println("예외 발생: " + e.getMessage());
        }
    }
}

 

출력:

예외 발생: / by zero

이처럼 동기 코드에서는 try-catch를 사용하면 문제없이 예외를 처리할 수 있음.

 


2️⃣ 비동기(멀티스레드) 코드에서 try-catch 문제점

 

비동기적으로 실행되는 코드에서는 try-catch가 즉시 예외를 잡지 못할 수 있음.

 

예제: Thread 내부에서 try-catch 없이 예외 발생

public class AsyncExceptionExample {
    public static void main(String[] args) {
        Thread thread = new Thread(() -> {
            int result = 10 / 0; // ArithmeticException 발생
            System.out.println("비동기 결과: " + result);
        });

        thread.start();
        System.out.println("메인 스레드는 계속 실행됨");
    }
}

 

출력 결과:

메인 스레드는 계속 실행됨
Exception in thread "Thread-0" java.lang.ArithmeticException: / by zero

 

문제점:

예외가 발생해도 try-catch가 없으므로 스레드가 죽어버림.

메인 스레드에는 영향을 주지 않지만, Thread 내부에서 예외를 잡지 않으면 해당 예외가 처리되지 않음.

 


3️⃣ 비동기 코드에서 try-catch로 예외 처리하는 방법

 

비동기 코드에서 예외를 잡으려면 try-catch를 비동기 실행 블록 내부에 직접 추가해야 함.

 

✅ Thread 내부에서 try-catch 적용

public class AsyncTryCatchExample {
    public static void main(String[] args) {
        Thread thread = new Thread(() -> {
            try {
                int result = 10 / 0; // 예외 발생
                System.out.println("비동기 결과: " + result);
            } catch (ArithmeticException e) {
                System.out.println("비동기 예외 발생: " + e.getMessage());
            }
        });

        thread.start();
        System.out.println("메인 스레드는 계속 실행됨");
    }
}

 

출력 결과:

메인 스레드는 계속 실행됨
비동기 예외 발생: / by zero

 

해결됨!

비동기 코드 내부에 try-catch를 추가하면 예외가 발생하더라도 정상적으로 잡을 수 있음.

 


4️⃣ ExecutorService를 사용할 때 예외 처리

 

❌ ExecutorService에서 try-catch 없이 예외 발생 시 문제점

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ExecutorWithoutTryCatch {
    public static void main(String[] args) {
        ExecutorService executor = Executors.newSingleThreadExecutor();

        executor.submit(() -> {
            int result = 10 / 0; // 예외 발생
            System.out.println("비동기 결과: " + result);
        });

        executor.shutdown();
    }
}

 

출력 결과:

Exception in thread "pool-1-thread-1" java.lang.ArithmeticException: / by zero

submit()을 사용하면 예외가 내부적으로 처리되지 않고 조용히 무시될 수도 있음.

 


✅ ExecutorService에서 예외 처리하는 방법 ① (try-catch 사용)

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ExecutorTryCatch {
    public static void main(String[] args) {
        ExecutorService executor = Executors.newSingleThreadExecutor();

        executor.submit(() -> {
            try {
                int result = 10 / 0; // 예외 발생
                System.out.println("비동기 결과: " + result);
            } catch (ArithmeticException e) {
                System.out.println("비동기 예외 발생: " + e.getMessage());
            }
        });

        executor.shutdown();
    }
}

 

정상적으로 예외 처리 가능!

 

출력 결과:

비동기 예외 발생: / by zero

 

 


✅ ExecutorService에서 예외 처리하는 방법 ② (Future 사용)

 

Future를 사용하면 작업의 결과를 받아 예외를 처리할 수 있음.

import java.util.concurrent.*;

public class ExecutorFutureExample {
    public static void main(String[] args) {
        ExecutorService executor = Executors.newSingleThreadExecutor();

        Future<Integer> future = executor.submit(() -> {
            return 10 / 0; // 예외 발생
        });

        try {
            int result = future.get(); // 여기서 예외가 발생함
            System.out.println("비동기 결과: " + result);
        } catch (InterruptedException | ExecutionException e) {
            System.out.println("Future 예외 발생: " + e.getCause());
        }

        executor.shutdown();
    }
}

 

출력 결과:

Future 예외 발생: java.lang.ArithmeticException: / by zero

get() 호출 시 예외가 발생하므로 try-catch로 잡아야 함.

 


5️⃣ CompletableFuture에서 예외 처리

 

✅ exceptionally() 메서드를 사용한 예외 처리

import java.util.concurrent.CompletableFuture;

public class CompletableFutureExample {
    public static void main(String[] args) {
        CompletableFuture.supplyAsync(() -> {
            return 10 / 0; // 예외 발생
        }).exceptionally(ex -> {
            System.out.println("CompletableFuture 예외 발생: " + ex.getMessage());
            return 0; // 기본값 반환
        }).thenAccept(result -> System.out.println("결과: " + result));

        // 메인 스레드 종료 방지
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

 

출력 결과:

CompletableFuture 예외 발생: / by zero
결과: 0

exceptionally() 메서드를 사용하면 예외를 잡고 기본값을 반환할 수 있음.

 


6️⃣ 정리하면:

Thread 내부에서는 반드시 try-catch를 직접 사용해야 예외를 잡을 수 있음.

ExecutorService.submit()은 예외를 조용히 무시할 수 있음 → Future.get()에서 예외를 확인해야 함.

CompletableFuture는 exceptionally()를 사용하여 비동기 예외를 처리하는 것이 가장 안전함.

 

 

 

 

출처 : ChatGPT

'BE > Java' 카테고리의 다른 글

[Java] ArrayDeque  (0) 2025.04.02
[Java] 체인호출  (0) 2025.03.24
[Java] File I/O  (0) 2025.03.18
[Java] BufferedReader  (0) 2025.03.17
[Java] StringTokenizer  (0) 2025.03.16