| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | ||||
| 4 | 5 | 6 | 7 | 8 | 9 | 10 |
| 11 | 12 | 13 | 14 | 15 | 16 | 17 |
| 18 | 19 | 20 | 21 | 22 | 23 | 24 |
| 25 | 26 | 27 | 28 | 29 | 30 | 31 |
- designPattern
- 추상 팩토리
- Observer Pattern
- 코루틴
- 팩토리 메소드
- Abstract Factory
- Design Pattern
- Coroutines
- Kotlin
- 안드로이드 디자인시스템
- factory method
- 빌터패턴
- 함수형프로그래밍
- android designsystem
- compose
- kotlin multiplatform
- Functional Programming
- kmp
- builderPattern
- 코틀린멀티플랫폼
- 코틀린
- PrototypePattern
- 추상팩토리패턴
- define
- 디자인패턴 #
- 옵저버 패턴
- material3
- 프로토타입 패턴
- ㅋㅁ
- 디자인패턴
- Today
- Total
오늘도 더 나은 코드를 작성하였습니까?
7장 코루틴 컨텍스트 본문
public fun CoroutineScope.launch(
context: CoroutineContext = EmptyCoroutineContext,
start: CoroutineStart = CoroutineStart.DEFAULT,
block: suspend CoroutineScope.() -> Unit
): Job { ... }
코루틴 빌더의 첫번째 인자는 CoroutineContext 이다.
마지막 인자인 block의 리시버 타입은 CoroutineScope이다.
public interface CoroutineScope {
public val coroutineContext: CoroutineContext
}
CoroutineScope는 CoroutineContext의 랩퍼처럼 보인다.
public interface Continuation<in T> {
public val context: CoroutineContext
public fun resumeWith(result: Result<T>)
}
Continuation도 CoroutineContext를 포함하고 있다.
CoroutineContext는 무엇일까?
CoroutineContext 인터페이스
CoroutineContext는 원소나 원소들의 집합을 나타내는 인터페이스.
Job, CoroutineName, CoroutineDispatcher Element 객체들이 인덱싱된 집합 (map, set과 같은 컬렉션이랑 비슷한 개념)
Element 또한 CoroutineContext이다.
CoroutineContext의 모든 원소는 식별할 수 있는 유일한 Key를 가지고 있다.
fun main() {
val name: CoroutineName = CoroutineName("A name")
val element: CoroutineContext.Element = name
val context: CoroutineContext = element
val job: Job = Job()
val jobElement: CoroutineContext.Element = job
val jobContext: CoroutineContext = jobElement
}
CoroutineContext 에서 원소 찾기
CoroutineContext는 컬렉션과 비슷하기때문에 get을 이용해 유일한 키를 가진 원소를 찾으수 있다.
*해당 원소가 없으면, null을 반환한다.
fun main() {
val ctx: CoroutineContext = CoroutineName("A name")
val coroutineName: CoroutineName? = ctx[CoroutineName] // ctx.get(CoroutineName)
println(coroutineName?.name) //A name
val job: Job? = ctx[Job]
println(job) //null
}
CoroutineName은 타입이나 클래스가 아닌 companion 객체이다.
public final data class CoroutineName public constructor(name: kotlin.String) : AbstractCoroutineContextElement {
public companion object Key : CoroutineContext.Key<CoroutineName> {
}
public interface Job : CoroutineContext.Element {
public companion object Key : CoroutineContext.Key<Job> {
}
CoroutineContext 더하기
서로 다른 키를 가진 두 원소를 더하여 만들어진 CoroutineContext는 두 가지 키를 모두 가집니다.
fun main() {
val ctx1: CoroutineContext = CoroutineName("Name1")
println(ctx1[CoroutineName]?.name) // Name1
println(ctx1[Job]?.isActive) // null
val ctx2: CoroutineContext = Job()
println(ctx2[CoroutineName]?.name) // null
println(ctx2[Job]?.isActive) // Active 상태라서 true
// 빌더를 통해 생성되는 Job의 기본 상태가 Active가 되어 true가 된다
val ctx3 = ctx1 + ctx2
println(ctx3[CoroutineName]?.name) // Name1
println(ctx3[Job]?.isActive) // true
}
CoroutineContext에 같은 키를 가진 또 다른 원소가 더해진다면, map 처럼 새로운 원소가 기존 원소를 대체합니다.
fun main() {
val ctx1: CoroutineContext = CoroutineName("Name1")
println(ctx1[CoroutineName]?.name) // Name1
val ctx1: CoroutineContext = CoroutineName("Name2")
println(ctx1[CoroutineName]?.name) // Name2
val ctx3 = ctx1 + ctx2
println(ctx3[CoroutineName]?.name) // Name2
}
비어 있는 CoroutineContext
CoroutineContext는 컬렉션이므로 빈 컨텍스트 또한 만들 수 있습니다. 빈 컨텍스트는 원소가 없기에, 아무런 영향을 주지 않습니다.
fun main() {
val empty: CoroutineContext = EmptyCoroutineContext
println(empty[CoroutineName]) // null
println(empty[Job]) // null
val ctxName = empty + CoroutineName("Name1") + empty
println(ctxName[CoroutineName]) // CoroutineName(Name1)
}
원소 제거
minusKey 함수를 이용하여 원소를 CoroutineContext에서 제거할 수 있다.
fun main() {
val ctx = CoroutineName("Name1") + Job()
println(ctx[CoroutineName]?.name) // Name1
println(ctx[Job]?.isActive) // true
val ctx2 = ctx.minusKey(CoroutineName)
println(ctx2[CoroutineName]?.name) // null
println(ctx2[Job]?.isActive) // true
val ctx3 = (ctx + CoroutineName("Name2"))
.minusKey(CoroutineName)
println(ctx3[CoroutineName]?.name) // null
println(ctx3[Job]?.isActive) // true
}
CoroutineContext 폴딩(누산)
- 누산기의 첫번째 원소
- 누산기의 현재 상태와 실행되고 있는 원소로 다음 상태를 계산.
fun main() {
val ctx = CoroutineName("Name1") + Job()
ctx.fold("") { acc, element -> "$acc$element" }
.also(::println)
}
CoroutineContext 와 빌더
CoroutineContext는 코루틴의 데이터를 저장하고 전달하는 방법.
부모는 기본적으로 CoroutineContext를 자식에게 전달하고, 자식은 부모로부터 CoroutineContext를 상속받는다.
import kotlinx.coroutines.*
fun main() = runBlocking(CoroutineName("main")) {
log("Started")
val v1 = async {
delay(500)
log("Running async")
42
}
launch {
delay(1000)
log("Running launch")
}
log("answer : ${v1.await()}")
}
//[main] Started
//[main] Running async
//[main] answer : 42
//[main] Running launch
fun CoroutineScope.log(msg: String) {
val name = coroutineContext[CoroutineName]?.name
println("[$name] $msg")
}
자식은 빌더의 인자에서 정의된 특정 Context를 가질수 있다.
인자로 전달된 컨텍스트는 부모로부터 상속받은 Context를 대체한다.
import kotlinx.coroutines.*
fun main() = runBlocking(CoroutineName("main")) {
log("Started")
val v1 = async(CoroutineName("c1")) {
delay(500)
log("Running async")
42
}
launch(CoroutineName("c2")) {
delay(1000)
log("Running launch")
}
log("answer : ${v1.await()}")
}
//[main] Started
//[c1] Running async
//[main] answer : 42
//[c2] Running launch
fun CoroutineScope.log(msg: String) {
val name = coroutineContext[CoroutineName]?.name
println("[$name] $msg")
}
* defaultContext + parentContext + childContext
중단함수에서 Context에 접근하기
중단함수에서 부모의 Context에 접근하는 것이 가능합니다.
coroutineContext 프로퍼티는 모든 중단 스코프에서 사용이 가능하며, 이를 통해 Context에 접근할 수 있다.
import kotlinx.coroutines.*
import kotlin.coroutines.coroutineContext
suspend fun main() = withContext(CoroutineName("Outer")) {
printName()
launch(CoroutineName("Inner")) {
printName()
}
delay(10)
printName()
}
//Outer
//Inner
//Outer
suspend fun printName() = println(coroutineContext[CoroutineName]?.name)
컨텍스트를 개별적으로 생성하기 (CustomContext)
CoroutineContext.Element 구현하기.
class MyCustomContext : CoroutineContext.Element {
override val key: CoroutineContext.Key<*> = Key
companion object Key : CoroutineContext.Key<MyCustomContext>
}
CoroutineContext
- Collection이랑 매우 개념적으로 비슷하다.
- Element로 인덱싱된 집합이며, Element도 CoroutineContext다.
- CoroutineContext는 Element를 유일하게 식별하는 key를 가진다.
- 코루틴의 상태가 어떤지, 어떤 스레드에서 작동하는지 등 코루틴의 동작방식을 정한다.
'Coroutine > 코틀린 코루틴' 카테고리의 다른 글
| 6장 코루틴 빌더 (0) | 2026.01.05 |
|---|---|
| 5장 코루틴 언어차원에서의 지원 vs 라이브러리 (0) | 2025.12.22 |
| 3장 중단은 어떻게 작동할까? (0) | 2025.11.27 |
| 2장 시퀀스 빌더 (0) | 2025.11.17 |
| 1장 코틀린 코루틴을 배워야 하는 이유 (0) | 2025.11.09 |
