Kotlin의 CoroutineScope와 coroutineScope의 차이점
Kotlin 문서에서는 코루틴을 네트워크에서 리소스를 다운로드하는 것과 같은 일부 백그라운드 작업이 실행될 때까지 대기하면서 일시 중지할 수 있는 실행으로 정의합니다.
코루틴은 코루틴이 일시 중단될 때 다른 계산이 계속 실행되므로 동시성을 달성하는 데 도움이 됩니다. 코루틴은 사용 중인 스레드에서 실행을 재개한다는 보장이 없기 때문에 사용 중인 스레드와 독립적입니다.
새로운 코루틴을 생성하려면 범위 내에서 수행해야 합니다. 이 튜토리얼에서는 구조화되지 않은 동시성의 범위가 자식 코루틴에 미치는 영향과 구조화된 동시성을 사용하여 범위 문제를 해결하는 방법을 배웁니다.
새 Kotlin 프로젝트 생성
이 튜토리얼에서는 IntelliJ IDEA를 활용하지만 원하는 개발 환경을 사용할 수 있습니다.
IntelliJ IDEA를 열고 파일 > 새로 만들기 > 프로젝트
를 선택합니다. 열리는 창에서 아래와 같이 왼쪽 하단에서 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
를 표시합니다.
이 코드를 실행하고 하위 코루틴이 실행을 마치기 전에 상위 코루틴이 일시 중지되었기 때문에 Toast
에 1
값이 표시됩니다.
출력:
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
루프를 실행할 때까지 기다립니다.
이 코드를 실행하고 Toast
에 1 20
값이 표시되는지 확인합니다. 2는 자식 코루틴이 부모 범위 재사용으로 인해 종료 없이 전체 루프를 실행하고 있음을 나타냅니다.
출력:
결론
이 튜토리얼에서는 구조화되지 않은 동시성의 범위가 자식 코루틴에 미치는 영향과 구조화된 동시성을 사용하여 문제를 해결하는 방법을 배웠습니다. 우리가 다룬 주요 주제는 CoroutineScope()
를 사용하여 독립 범위를 만드는 방법과 coroutineScope()
를 사용하여 상위 범위를 재사용하는 방법입니다.
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