개발린생

Android 비동기 작업 처리를 위한 Coroutines과 AsyncTask 본문

Dev Lab ✧.·˚/Android & iOS

Android 비동기 작업 처리를 위한 Coroutines과 AsyncTask

김블루 2024. 10. 20. 01:21

안드로이드 개발을 예전부터 해왔던 분이라면 언제적 AsyncTask냐 싶을 것이다.

AsyncTask는 예전에 비동기 작업을 처리하기 위해 흔히 사용되던 클래스지만 현재로써는 RxJava와 Coroutines가 대표적으로 사용된다.

AsyncTask > RxJava > Coroutines 이 외에도 중간중가 여러가지가 있긴 하다.

 

현재 AsyncTask는 디플리케이트 되었고 Coroutines이 많이 사용되고 있다.

(가끔 유지보수건 프로젝트를 보면 AsyncTask를 많이 마주치긴 함)

 

💬 AsyncTask를 사용할 때를 주절거려보자면 

과거 Android Java로 앱을 개발하던 시절, 화면을 띄운 상태에서 네트워크 통신이나 파일 처리 등 무거운 작업을 하면 UI가 멈추는 문제가 있었다. 이것을 해결하기 위해 AsyncTask를 사용해 UI 스레드와 별도로 비동기 작업을 처리했다.

그때는 AsyncTask 만큼 편리한 방법이 없다고 생각해서 자주 사용했지만, 코드가 복잡해지고, 메모리 누수 문제에 취약했으며, 생명 주기를 관리하기 어려웠던 것 같다. UI가 재생성될 때도 어디선가 꼬이는 문제도 있어서 신경써서 개발을 해야했다.

 

Coroutines(코루틴)을 알게된건 Kotlin을 접하면서 알게됐는데, 사실 코틀린 언어가 나오면서 코루틴이 생겨난 것은 아니다.

코루틴이라는 개념은 오래전부터 여러 프로그래밍 언어에서 비동기 프로그래밍을 효율적으로 처리하는 기술로 존재했다고 한다.

하지만, 코틀린에서 코루틴을 언어 차원에서 공식적으로 지원하며, 이를 통해 안드로이드 개발에 더 나은 비동기 처리를 가능하도록 했기 때문에 코틀린을 알면 코루틴에 대해서 알아보게 될 수 밖에 없었다. 

(코틀린 비동기 처리 검색하면 코루틴 나옴)


현재 Kotlin의 Coroutines은

기존의 스레드나 콜백 방식을 대체하면서 복잡한 비동기 작업을 훨씬 간결하고 쉽게 처리할 수 있게 해준다.

특히 Kotlin은 Android와의 호환성을 염두해두고 발전했기 때문에, Coroutines은 Android 개발에서 비동기 작업의 표준 도구로 자리잡았다.

 

Kotlin Coroutines 특징

1. 비동기 작업을 동기 코드처럼 작성한다.

  • 코루틴은 비동기 작업을 마치 동기 코드처럼 간결하게 작성할 수 있도록 도와준다.
  • suspend 키워드 사용만으로 비동기 작업을 기다렸다가 처리할 수 있다.
suspend fun fetchData(): String {
    // 네트워크 요청 같은 비동기 작업
    return result
}

 

2. 언어 차원의 지원

  • 코틀린은 코루틴을 언어의 중요한 부분으로 통합해서 비동기 작업을 쉽게 처리할 수 있게 했다. 자바에서는 이러한 비동기 작업을 AsyncTask, RxJava 같은 외부 라이브러리에 의존했지만, 코틀린에서는 언어 자체에서 비동기 작업을 처리할 수 있는 기능을 제공한다.

3. 비동기 작업의 간결화

  • 위 AsyncTask를 설명하며 말했지만, 과거에는 복잡한 비동기 작업에 대해 많은 콜백과 에러 처리가 필요했지만 코루틴을 사용하면서 코드가 직관적이고 간결해졌다.

4. 스레드의 효율성

  • 코루틴은 실제로는 경량 스레드처럼 동작한다. 수많은 코루틴이 실행되더라도 실제로는 하나의 스레드에서 처리되기 때문에, 리소스를 적게 소모하면서도 고성능의 비동기 작업을 구현할 수 있다.

요약

Kotlin의 Coroutines은 코루틴 개념 자체를 Kotlin 언어에 맞게 최적화해서 도입한 것이고, Kotlin이 Android의 공식 언어로 채택되면서 코루틴도 Android 개발에서 널리 사용되게 된 것이다.

코루틴은 코틀린이 등장하면서 처음 나온 기술은 아니지만, 코틀린 덕분에 더 간편하고 강력하게 사용할 수 있는 비동기 처리 방법이 되었다.


더 나아가 AsyncTask와 Coroutines 비교해보기

💬 신규 개발만 하거나 Kotlin으로만 개발할 것이라면 AsyncTask를 몰라도 되지만, Java 프로젝트나 유지보수를 할거라면 AsyncTask에 대해 더 알아보기

1. AsyncTask 코드 예시 (Java)

public class NetworkTask extends AsyncTask<Void, Void, String> {

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        // UI 스레드에서 실행됨 - 로딩 표시
    }

    @Override
    protected String doInBackground(Void... voids) {
        // 네트워크 요청 처리 (백그라운드에서 실행)
        try {
            URL url = new URL("https://api.example.com/data");
            HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
            InputStream inputStream = urlConnection.getInputStream();
            BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
            StringBuilder result = new StringBuilder();
            String line;
            while ((line = reader.readLine()) != null) {
                result.append(line);
            }
            reader.close();
            return result.toString();
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }

    @Override
    protected void onPostExecute(String result) {
        super.onPostExecute(result);
        // 결과를 UI에 반영 (UI 스레드에서 실행됨)
        if (result != null) {
            // 결과 처리
        }
    }
}

// AsyncTask 실행
new NetworkTask().execute();

 

2. Coroutines 코드 예시 (Kotlin)

// Coroutines를 사용한 비동기 처리
fun fetchData() {
    // IO 디스패처를 사용하여 네트워크 요청을 처리
    CoroutineScope(Dispatchers.IO).launch {
        try {
            val url = URL("https://api.example.com/data")
            val urlConnection = url.openConnection() as HttpURLConnection
            val result = urlConnection.inputStream.bufferedReader().use { it.readText() }

            // UI 디스패처에서 결과 처리
            withContext(Dispatchers.Main) {
                // 결과 처리 (UI 스레드)
            }
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }
}

// 함수 호출
fetchData()