코루틴의 구조에 대해 헷갈리는 부분이 많았다. 그래서 일단 사용하며 익혔다. 이제 다소 익숙해졌기에 다시 한번 파보았다. Kotlin coroutines 소스코드와 GPT, 블로그 등을 통해 디깅한 끝에 깨닫게 된 부분에 대해 간단히 정리해본다.
코루틴 클래스부터 얘기를 풀어나가는 게 좋겠다. 여러 코틀린 구현 클래스들의 뼈대가 되는 AbstractCoroutine 클래스의 시그니쳐는 다음과 같다.
public abstract class AbstractCoroutine<in T>(
parentContext: CoroutineContext,
initParentJob: Boolean,
active: Boolean
) : JobSupport(active), Job, Continuation<T>, CoroutineScope
Job, Continuation, CoroutineScope라는 세 개의 interface를 구현하고 있다.(JobSupport는 Job의 구현체다) 여기서 Job과 CoroutineScope에 대해 얘기해보려 한다. (Continuation에 대해서는 아직 정확히 파악하지 못했다. 코루틴의 중단/재개 기능을 위한 인터페이스 아닐까 추측해본다.)
우선 Job은 하나의 작업단위로써의 코루틴을 핸들링하게 해주는 핸들이다. Job에는 두가지 역할이 있다. 작업의 상태를 보여주는 것이 첫번째 역할, 부모/자식 Job을 저장해 코루틴 간의 트리 구조를 연결하는 것이 두번째 역할이다. 우리는 코루틴 객체를 직접 다루는 것이 아니라 Job이라는 인터페이스를 통해 다루게 된다.
CoroutineScope(이하 Scope)는 코루틴의 Builder 클래스다. 이름이 scope라서 '범위'를 떠올리게 되는데 솔직히 말해 범위 역할은 거의 없는 것 같다(자신이 보유한 Job 객체에 cancel() 함수를 호출하는 것 정도. 취소를 하방 전파하는 건 결국 Job이 한다). 그냥 빌더로 이해하는 편이 낫다. Builder 클래스는 이런 저런 설정을 한 뒤 .build()를 호출해 객체를 만들어내는 패턴으로 구현된다. Scope에 있어서 '이런 저런 설정'에 해당하는 것이 CoroutineContext(이하 Context)고, build() 함수에 해당하는 것이 launch, async 등의 함수들이다. Scope에도 두 가지 역할이 있다. 하나의 영역(scope)으로서 그 영역의 설정 값(Context)을 보유하는 역할과 하나의 빌더로서 해당 코루틴의 정보를 복제/수정해 새로운 코루틴을 생산해내는 역할이다.
- CoroutineContext는 여러 구성요소들로 이뤄져 있다(이들은 CoroutineContext.Element interface를 구현한다). 코루틴의 이름, 사용할 스레드, 부모 Job의 정보, 에러 핸들러 등이다. Android의 Context와는 관련이 없다.
- launch, async, withContext 등의 빌더 함수들은 StandaloneCoroutine, DeferredCoroutine 등 AbstractCoroutine을 상속한 코루틴을 만들어낸다.
처음 코루틴을 공부했을 때 어렵게 느껴졌던 것은 CoroutineScope와 Job을 중심에 두고 이해하려 했기 때문인데 Job에도 두 가지 측면이 있고, Scope에도 두 가지 측면이 있어 이해를 혼란스럽게 만들기 때문이다. 이는 '코루틴'을 중심에 두고 하나의 작업 흐름으로서 그 본연의 기능과 복제 재생산 기능을 구분해서 봄으로써 극복할 수 있다.
우선 하나의 작업 단위로서, 코루틴에는 그 작업 환경에 대한 설정이 필요하고 현재 작업의 상태를 구분할 수 있는 기능이 필요하다. 이는 각각 Scope(정확히는 그 안에 담긴 Context)와 Job을 통해 구현되어 있다.
또한 코루틴은 여러 다른 코루틴들과 트리 형태의 구조를 이룬다. 이를 위해서는 한 코루틴 안에서 자식 코루틴(혹은 별도의 코루틴)을 생성해낼 수 있는 능력, 부모/자식 코루틴 간의 정보를 저장할 능력이 필요하다. 이 역시 Scope(빌더 함수들을 통해)와 Job을 통해 하게 된다.
이는 트리 구조에서 노드 본연으로서의 기능과 새 노드를 만들어내고 연결하는 기능으로 구분해 볼 수도 있다. 코루틴들은(그 핸들인 Job을 통해) 트리구조를 이룸으로써 취소/완료 정보를 전파할 수 있게 되고 이를 코루틴에서는 구조화된 동시성(Structured Concurrency)이라고 부르는 것이다.
자세한 구조 설명은 다음 블로그를 참조하자.
'Android' 카테고리의 다른 글
| DevFest Android in Korea 2025 - 버터맥주파티 (0) | 2026.01.11 |
|---|---|
| Manifest Android Interview 정리 (0) | 2025.12.31 |
| super.init(version=6) (0) | 2025.03.23 |
| [Error] command not found: adb (0) | 2024.12.01 |
| Android 자료 (0) | 2022.08.11 |