코틀린 비동기처리 코루틴 사용법

2023. 10. 11. 16:24- 안드로이드/kotlin

코루틴

코틀린의 비동기처리 방식중 코루틴은 어렵지 않고 심플하게 사용이 가능하여 많이 쓰이는 기능인데요

코루틴의 다양한 상황에서의 사용 예제를 알아보겠습니다.

 

 

 

쓰레드 확인

일단 CoroutineScope안에서 쓰레드는 어떻게 표시 되는지 확인해보겠습니다.

        lifecycleScope.launch(Dispatchers.Default) {	// or Dispatchers.IO
            // 코루틴 스코프 영역
            delay(1000)
            Log.d(TAG, "코루틴 : ${Thread.currentThread().name}")	// worker Thread
        }
        Log.d(TAG, "메인 : ${Thread.currentThread().name}")	// main Thread

코루틴 스코프 영역안의 쓰레드는 worker 쓰레드, 그 아래 영역은 main 쓰레드인것을 확인 할수 있습니다.

 

백그라운드 쓰레드(워커쓰레드)를 사용하려면 Dispatchers.Default를 사용합니다.

Dispatchers중 자주 쓰이는것은 DefaultIO가 있는데 사용하는데 있어서 큰차이는 없지만

각각 정의되는 내용을 간단히 알아보겠습니다.

  • Dispatchers.Default
    JVM의 공유 스레드풀을 사용하고 동시 작업 가능한 최대 갯수는 CPU의 코어 수와 같습니다.
    만약 4코어 CPU를 사용하는 경우 최대 4개의 병렬작업이 가능합니다.
  • Dispatchers.IO
    필요에 따라 추가적으로 스레드를 더 생성하거나 줄일 수 있으며 최대 64개까지 생성이 가능합니다.
    또한 Default Dispatcher와 스레드를 공유하기 때문에 switching으로 인한 오버헤드를 일으키지 않습니다.

정리 하자면 IO의 경우 대기시간이 있는 네트워크 입출력 등의 작업에 적합한 반면
Default의 경우 대기시간이 없고 지속적으로 CPU의 작업을 필요로 하는 무거운 작업에 적합합니다.
후자의 경우 코어 수 만큼의 스레드만 생성하여 작업하기 때문에 CPU를 많이 점유하는 작업에서 최대의 효율을 내기 때문입니다.

 

 

코루틴으로 Retrofit 사용하기

 

서버데이터는 jsonplaceholder를 사용하여 테스트 하겠습니다.

 

 

라이브러리 추가하기

    implementation("com.squareup.retrofit2:retrofit:2.9.0")
    implementation("com.squareup.retrofit2:converter-gson:2.9.0")

 

DataClass 만들기

data class VO(val userId: Int = 0,
              val id: Int = 0,
              val title: String = "",
              val body: String = "")

 

Interface 만들기

interface JsonPlaceHolderApi {
    @GET("/posts")
    suspend fun getPosts(): List<VO>
}

 

Retrofit 코루틴으로 사용

class MainActivity : AppCompatActivity() {
    val TAG = "MainActivity__"

    val api = Retrofit.Builder()
        .baseUrl("https://jsonplaceholder.typicode.com")
        .addConverterFactory(GsonConverterFactory.create())
        .build()
        .create(JsonPlaceHolderApi::class.java)

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        
        lifecycleScope.launch(Dispatchers.IO) {
            try {
                val posts = api.getPosts()
                posts.forEach {
                    Log.d(TAG, "${it.id}, ${it.userId}, ${it.title}")
                }
            } catch (e: Exception) {    // 실패 했을때 try-catch로 처리
                e.printStackTrace()
            }

        }
    }
}

 

 

데이터 응답이 정상적으로 받아진것을 확인 할수 있습니다.

 

 

 

참고

https://www.youtube.com/watch?v=MjX102bulSM&list=PLxTmPHxRH3VVu_8Ck5kH_eMHrVMVNn6IS&index=7