# **코틀린의 코루틴과 비동기 프로그래밍** 코틀린은 **코루틴(Coroutines)** 을 통해 **비동기(Asynchronous) 프로그래밍**을 쉽고 직관적으로 구현할 수 있다. 코루틴은 **스레드보다 가볍고 효율적**이며, **콜백 지옥을 피할 수 있는 강력한 기능**을 제공한다. 이 글에서는 **코루틴의 개념과 주요 기능**을 설명하고, **비동기 프로그래밍을 구현하는 예제**를 함께 살펴보겠다. 🚀 --- ## **1. 비동기 프로그래밍이란?** 비동기 프로그래밍은 **작업이 완료될 때까지 기다리지 않고 다음 코드를 실행하는 방식**이다. 즉, **시간이 오래 걸리는 작업(예: 네트워크 요청, 파일 I/O 등)** 도 프로그램이 멈추지 않고 실행된다. ### **1.1. 전통적인 방식 (콜백 지옥)** 자바에서는 비동기 작업을 콜백(callback) 방식으로 처리해야 한다. 콜백이 중첩되면 **콜백 지옥(Callback Hell)** 이 발생할 수 있다. #### **자바의 콜백 예제** ```java void fetchData(Callback callback) { new Thread(() -> { try { Thread.sleep(2000); // 2초 대기 (네트워크 요청 가정) callback.onSuccess("데이터를 가져왔습니다!"); } catch (InterruptedException e) { callback.onError(e); } }).start(); } interface Callback { void onSuccess(String data); void onError(Exception e); } public static void main(String[] args) { fetchData(new Callback() { @Override public void onSuccess(String data) { System.out.println(data); } @Override public void onError(Exception e) { System.out.println("에러 발생: " + e.getMessage()); } }); } ``` > - `fetchData()` 가 비동기적으로 데이터를 가져오지만, **콜백을 계속 중첩해서 작성해야 한다.** > - 코드가 복잡해지고 가독성이 나빠지는 문제가 있다. --- ## **2. 코루틴이란?** **코루틴(Coroutines)** 은 **비동기 프로그래밍을 간결하고 가독성 높게** 구현할 수 있도록 도와준다. 코루틴을 사용하면 **콜백 없이도 순차적인 코드 스타일**로 **비동기 작업**을 작성할 수 있다. > **코루틴의 특징:** > - **스레드보다 가벼움** (필요할 때만 실행되고, 자동으로 일시 중단됨) > - **순차적 스타일로 작성 가능** (콜백 없이 비동기 코드 작성 가능) > - **비동기 코드가 직관적이고 읽기 쉬움** --- ## **3. 코틀린에서 코루틴 사용하기** ### **3.1. 기본적인 코루틴 사용** ```kotlin import kotlinx.coroutines.* fun main() = runBlocking { // 코루틴 블록 시작 launch { delay(1000L) // 1초 대기 println("코루틴 실행!") } println("메인 함수 실행") } ``` **출력 결과:** ``` 메인 함수 실행 코루틴 실행! ``` > - `runBlocking {}`: 메인 함수에서 코루틴을 실행하는 블록 > - `launch {}`: 새로운 코루틴을 실행 > - `delay(1000L)`: 1초 동안 비동기 대기 (스레드 차단 없이 실행 가능) --- ## **4. 코루틴 빌더 (`launch` vs `async`)** 코루틴을 실행할 때는 **`launch`** 와 **`async`** 를 사용할 수 있다. | 빌더 | 반환값 | 특징 | |------|------|------| | `launch` | 없음 (`Job` 반환) | 단순히 코루틴을 실행 | | `async` | `Deferred` 반환 | 결과 값을 반환하는 비동기 작업 | ### **4.1. `launch` 사용 예시 (결과 값 없음)** ```kotlin import kotlinx.coroutines.* fun main() = runBlocking { launch { delay(1000L) println("launch: 비동기 작업 완료!") } } ``` > - `launch {}` 는 단순히 비동기 작업을 실행하고, 결과를 반환하지 않음. > - `Job` 객체를 반환하지만, 보통 `join()`을 호출하지 않는 이상 결과를 기다리지 않음. --- ### **4.2. `async` 사용 예시 (결과 값 반환)** ```kotlin import kotlinx.coroutines.* fun main() = runBlocking { val result = async { delay(1000L) "async: 비동기 작업 완료!" } println(result.await()) // 결과 값을 기다림 } ``` > - `async {}` 는 **결과 값을 반환하는 비동기 작업**을 실행. > - `await()` 을 호출해야 실제 값을 가져올 수 있음. --- ## **5. 여러 개의 비동기 작업 실행 (`async` 활용)** 비동기 작업을 병렬로 실행하려면 **`async {}` 를 여러 개 실행**하면 된다. ```kotlin import kotlinx.coroutines.* fun main() = runBlocking { val time = measureTimeMillis { val job1 = async { fetchData(1) } val job2 = async { fetchData(2) } println(job1.await()) println(job2.await()) } println("총 실행 시간: $time ms") } suspend fun fetchData(id: Int): String { delay(1000L) // 네트워크 요청 시뮬레이션 return "데이터 $id 가져옴" } ``` **출력 결과:** ``` 데이터 1 가져옴 데이터 2 가져옴 총 실행 시간: 1003 ms ``` > - `async {}` 로 실행된 두 개의 코루틴이 **병렬로 실행됨**. > - `await()` 를 호출하면 해당 코루틴이 완료될 때까지 기다림. > - 실행 시간은 1초 내외 (동시 실행되었기 때문). --- ## **6. `suspend` 함수 사용하기** 코루틴에서 비동기 함수를 만들려면 **`suspend` 키워드**를 사용해야 한다. ```kotlin suspend fun fetchData(): String { delay(1000L) // 1초 대기 return "데이터 가져옴" } fun main() = runBlocking { val data = fetchData() println(data) } ``` > - `suspend` 함수는 **코루틴 내에서만 실행 가능** > - `delay()` 같은 비동기 함수 호출 가능 --- ## **7. 예외 처리 (`try-catch` 활용)** 코루틴에서도 **예외 처리를 `try-catch` 로 할 수 있음**. ```kotlin import kotlinx.coroutines.* fun main() = runBlocking { try { val result = async { errorTask() }.await() println(result) } catch (e: Exception) { println("예외 발생: ${e.message}") } } suspend fun errorTask(): String { delay(500L) throw RuntimeException("오류 발생!") } ``` **출력 결과:** ``` 예외 발생: 오류 발생! ``` > - `try-catch` 를 사용하면 **비동기 코드에서도 예외를 안전하게 처리 가능**. --- ## **8. 정리** | 기능 | 자바 | 코틀린 | |------|------|------| | 비동기 실행 | 콜백 기반 | 코루틴 기반 (`launch`, `async`) | | 가독성 | 콜백 중첩 발생 | 순차적 코드 스타일 | | 예외 처리 | 예외 전달 어려움 | `try-catch` 사용 가능 | | 실행 효율 | 스레드 사용 | 가벼운 코루틴 사용 | > **코루틴을 사용하면:** > ✅ **비동기 코드가 더 간결하고 직관적** > ✅ **콜백 지옥 없이 순차적 스타일로 작성 가능** > ✅ **스레드보다 가볍고 효율적** 코틀린에서 **비동기 프로그래밍을 쉽게 구현하려면 코루틴을 적극 활용하자!** 🚀