Kotlin의 CoroutineScope와 coroutineScope의 차이점

David Mbochi Njonge 2024년2월15일
  1. 새 Kotlin 프로젝트 생성
  2. 메인 레이아웃에 버튼 생성
  3. Kotlin에서 CoroutineScope 사용
  4. Kotlin에서 coroutineScope 사용
  5. 결론
Kotlin의 CoroutineScope와 coroutineScope의 차이점

Kotlin 문서에서는 코루틴을 네트워크에서 리소스를 다운로드하는 것과 같은 일부 백그라운드 작업이 실행될 때까지 대기하면서 일시 중지할 수 있는 실행으로 정의합니다.

코루틴은 코루틴이 일시 중단될 때 다른 계산이 계속 실행되므로 동시성을 달성하는 데 도움이 됩니다. 코루틴은 사용 중인 스레드에서 실행을 재개한다는 보장이 없기 때문에 사용 중인 스레드와 독립적입니다.

새로운 코루틴을 생성하려면 범위 내에서 수행해야 합니다. 이 튜토리얼에서는 구조화되지 않은 동시성의 범위가 자식 코루틴에 미치는 영향과 구조화된 동시성을 사용하여 범위 문제를 해결하는 방법을 배웁니다.

새 Kotlin 프로젝트 생성

이 튜토리얼에서는 IntelliJ IDEA를 활용하지만 원하는 개발 환경을 사용할 수 있습니다.

IntelliJ IDEA를 열고 파일 > 새로 만들기 > 프로젝트를 선택합니다. 열리는 창에서 아래와 같이 왼쪽 하단에서 Android를 선택한 다음 오른쪽에서 빈 활동을 선택합니다.

Android 프로젝트 - 빈 활동

Next 버튼을 누르고 열리는 창에서 프로젝트 이름을 CoroutineScope로 입력하고 패키지 이름을 com.coffeev.coroutinescope로 입력하고 언어 섹션에서 Kotlin을 선택한 다음 API 19를 선택합니다. 최소 SDK 섹션에 있습니다.

이러한 세부 정보가 아래와 같은지 확인하십시오.

프로젝트 세부정보

만들기 버튼을 눌러 새 Android 프로젝트를 생성합니다. 이 작업은 MainActivity라는 활동과 activity_main이라는 레이아웃을 포함하는 새 애플리케이션을 생성합니다.

이 파일을 사용하여 이 자습서에서 다루는 예제를 테스트합니다. 애플리케이션에 필요한 종속성을 추가하려면 활성 인터넷 연결이 있는지 확인하십시오.

코루틴으로 작업하려면 kotlinx-coroutines-core 종속성을 프로젝트에 추가해야 합니다. build.gradle 파일에 다음 종속성을 복사하여 붙여넣어 코루틴 종속성을 추가합니다.

dependencies {
    implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4")
}

메인 레이아웃에 버튼 생성

src/main/res/layout에서 acivity_main.xml 레이아웃 파일을 열고 다음 코드를 복사하여 파일에 붙여넣습니다.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:gravity="center_horizontal"
        tools:context=".MainActivity" >

    <Button
            android:id="@+id/button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="100dp"
            android:text="@string/button_text"/>

</LinearLayout>

이 코드는 Button 유형의 View 하나만 포함하는 LinearLayout을 생성합니다. 이 버튼을 사용하여 애플리케이션에서 코루틴을 호출합니다.

최종 레이아웃이 아래와 같은지 확인합니다.

앱 레이아웃

버튼은 text 속성으로 표시되는 문자열 리소스를 사용하여 레이블이 지정됩니다. src/main/res/values 폴더 아래에 있는 strings.xml 파일에 다음 문자열 리소스를 복사하여 붙여넣습니다.

그러면 버튼에 대한 텍스트가 생성되고 이 텍스트는 button_text라는 이름을 사용하여 액세스됩니다.

<resources>
    <string name="app_name">CoroutineScope</string>
    <string name="button_text">Press Me</string>
</resources>

Kotlin에서 CoroutineScope 사용

소개 섹션에서 새로운 코루틴을 생성하려면 스코프 내에서 수행해야 한다고 언급했습니다. 여기에서 CoroutineScope가 사용됩니다.

이를 실제로 보려면 src/main/java/com/coffeev/coroutinescope 폴더 아래의 MainActivity.kt 파일에 아래 코드를 복사하여 붙여넣으십시오.

package com.coffeedev.coroutinescope

import android.os.Bundle
import android.widget.Button
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val button = findViewById<Button>(R.id.button)

        button.setOnClickListener {
            CoroutineScope(Dispatchers.Main).launch {
                val message = getLoopProduct();
                Toast.makeText(applicationContext, "Message: $message", Toast.LENGTH_LONG)
                    .show();
            }
        }

    }

    private suspend fun getLoopProduct(): Int {
        var value = 1;
        CoroutineScope(Dispatchers.IO).launch {
            for (number in 1..5) {
                delay(15);
                value *= number;
            }
        }
        return value;
    }

}

이 코드에서 우리는 for 루프의 결과를 반환하는 getLoopProduct()라는 suspend 함수를 만들었습니다. for 루프는 CoroutineScope()의 인수로 전달된 Dispatchers.IO 스레드를 사용하여 실행되는 코루틴을 사용하여 실행됩니다.

for 루프가 반복될 때마다 15밀리초의 지연이 발생하여 현재 실행 중인 스레드를 일시 중단합니다.

onCreate() 수명 주기 메서드에서 단순히 기본 스레드인 Dispatchers.Main 스레드를 사용하여 실행되는 새 범위를 만들었습니다. suspend 함수가 내부에서 호출되기 때문에 getLoopProduct()의 코루틴은 onCreate() 메서드 내부에서 생성된 코루틴의 자식입니다.

서로 다른 범위에서 생성된 코루틴은 독립적으로 실행됩니다. 자식 코루틴은 부모 코루틴과 다른 범위를 사용하므로 부모는 자식이 실행을 마칠 때까지 기다리지 않습니다.

이러한 유형의 실행을 구조화되지 않은 동시성이라고 합니다.

onCreate() 메서드의 코루틴은 한 번만 실행되고 종료됩니다. 이것은 하위 코루틴이 백그라운드에서 계속 실행되고 애플리케이션을 메모리 누수에 노출시킬 수 있음을 의미합니다.

레이아웃에서 생성된 버튼을 사용하여 getLoopProduct()에서 반환된 값을 포함하는 Toast를 표시합니다. setOnClickListener() 메서드는 버튼을 누를 때 화면에 Toast를 표시합니다.

이 코드를 실행하고 하위 코루틴이 실행을 마치기 전에 상위 코루틴이 일시 중지되었기 때문에 Toast1 값이 표시됩니다.

출력:

구조화되지 않은 동시성

Kotlin에서 coroutineScope 사용

CoroutineScope()coroutineScope()의 차이점은 후자는 새 코루틴을 생성하지 않고 새 범위를 생성한다는 것입니다. 하위 코루틴은 상위 코루틴 범위를 사용하여 상위 코루틴이 실행을 완료하기 전에 완료되도록 합니다.

이러한 유형의 실행을 구조적 동시성이라고 합니다.

이를 실제로 보려면 이전 예제의 suspend 기능을 아래 제공된 기능으로 바꾸십시오.

   private suspend fun getLoopProduct(): Int {
        var value = 1;
        coroutineScope {
            for (number in 1..5) {
                delay(15);
                value *= number;
            }
        }
        return value;
    }

onCreate() 메서드의 코드는 변경되지 않으므로 자식 코루틴은 메인 스레드에서 실행되는 부모 범위를 사용하여 for 루프를 실행합니다. 부모 코루틴은 종료되기 전에 자식 코루틴이 for 루프를 실행할 때까지 기다립니다.

이 코드를 실행하고 Toast1 20 값이 표시되는지 확인합니다. 2는 자식 코루틴이 부모 범위 재사용으로 인해 종료 없이 전체 루프를 실행하고 있음을 나타냅니다.

출력:

구조적 동시성

결론

이 튜토리얼에서는 구조화되지 않은 동시성의 범위가 자식 코루틴에 미치는 영향과 구조화된 동시성을 사용하여 문제를 해결하는 방법을 배웠습니다. 우리가 다룬 주요 주제는 CoroutineScope()를 사용하여 독립 범위를 만드는 방법과 coroutineScope()를 사용하여 상위 범위를 재사용하는 방법입니다.

David Mbochi Njonge avatar David Mbochi Njonge avatar

David is a back end developer with a major in computer science. He loves to solve problems using technology, learning new things, and making new friends. David is currently a technical writer who enjoys making hard concepts easier for other developers to understand and his work has been published on multiple sites.

LinkedIn GitHub

관련 문장 - Kotlin Coroutine