코루틴을 사용할 때 스코프를 통해서 블록을 생성하고 코루틴의 중요 메서드인 await(), join(), delay(), suspend fun는 스코프 내에서만 호출이 가능합니다.
만약 다른 곳에서 위 메서드를 호출하게 된다면 컴파일에서 에러가 발생 하게 됩니다.
스코프를 사용할 때 저희는 여러 스코프가 존재하는걸 알 수 있고, 이 스코프가 왜 존재하는지 알아보려고 합니다.
(사실 필자는 ViewModelScope 밖에 사용하지 않아서... 큰 실수를 저지른적이 있다.. 이를 교훈 삼아 제대로 공부하고 알리기 위해 글을 작성합니다)
우선 안드로이드의 코루틴에서의 Scope는 개발자의 실수를 막아주기 위함으로 필자는 이해하고 있습니다. (이부분이 틀릴시 피드백 주시면 즉각 수정하도록 하겠습니다)
코루틴은 비동기로 실행이 되어 Activity가 종료되어도 cancel()이 되지 않으면 계속해서 작동할 수 있고, 이는 큰 문제로 이어질 수 있기에 개발자는 Activity의 onDestroy() 메서드에서 코루틴을 취소하는 메서드를 반드시 작성 해야한다.
하지만 개발자도 사람이고, 아키텍처를 나누어 설계를 하다보면 ViewModel, Domain layer, Data Layer 등에서 코루틴을 사용할 수 있는데 모두 해당 객체가 종료될 때 코루틴을 취소하는 작업을 하다가 실수를 범할 수 있다는 문제가 있다.
여기에서 우리는 스코프를 직접 작성하거나, 미리 작성된 스코프를 명시적으로 사용하여 작업이 취소 될 부분을 미리 설정할 수 있다.
CoroutineScope
[Kotlin - CoroutineScope 공식 문서]
가장 기본적인 코루틴 스코프입니다. 지정된 코루틴 콘텍스를 감싸는 코루틴 범위를 만듭니다. 사용할 때 주의할 점은 어느 부분에 종속되어 작동되지 않으므로, context가 종료될 때 반드시 작업을 중단 (cancel)을 해주어야합니다.
ex) onDestory(), onCleared() 등...
GlobalScope
[Kotlin - GlobalScope 공식 문서]
application이 시작되고, 종료 될 때 까지 유지되고 작동 됩니다.
Singletone 이기 때문에 따로 생성하지 않아도 되고, 어디에서든 바로 접근할 수 있기 떄문에 간단하게 사용할 수 있다는 점이다.
주의해야할 점으로 이 코루틴을 적절하게 사용 또는 종료하지 않을 시 메모리 릭의 문제가 생길 수 있다는 점이다. 이부분은 Android Studio를 사용할 때 경고로 알려주며, 어노테이션을 작성해서 경고를 무시할 수 있다.
LifecycleScope
[Android Developers - 코루틴 공식 문서]
여기에서부턴 Kotlin이 아닌 Android에서 제공하는 Scope이다.
실제 사용을 하면 Import는 Kotlin.coroutine이 아닌 androidx.lifecycle에서 제공된다.
왜 Android에서 제공을 할까? 이름부터 Lifecycle이다. 우리가 중요하게 생각하는 생명주기에 연관이 있다고 생각하면 된다. Activity, Fragment에서 생명주기에 따라 스코프가 작동, 취소, 일시중지를 할 수 있다고 생각하면 된다.
물론 제대로된 개발자라면 생명주기가 종료될 때 생성된 모든 객체는 GC에서 빠르게 알 수 있게 null을 처리하지만 개발자도 사람이다. 실수 할 수 있기에... Lifecyclescope는 이를 생명주기에 따라서 알아서 처리 해준다.
또한 생명주기의 onPause(), onStop()에서 코루틴의 일시중지가 필요 할 때 repeateOnLifecycle과 같은 API를 제공한다. 자세한 사항은 위 공식문서에서 나와있다!
ViewModelScope
[Android Developers - 코루틴 공식 문서]
MVP, MVVM 패턴을 사용할 때 ViewModel()을 상속받아서 ViewModel을 작성한 경우가 있을 것이다. 이 때 ViewModel은 Provider를 통해 Activity의 생명주기에 결합을 시키는데 결국 View를 상속받지 않기 때문에 lifecycleScope를 사용할 수 없다. 이를 대신하여, ViewModelScope가 존재하는데 이는 ViewModel에 연관되어 작동된다. onCleared()에서 해당 스코프는 자동으로 취소되고, ViewModel이 활동 상태일 때만 실행된다.
간단하게 4개의 Scope에 대해서 알아보았습니다.
필자는 ViewModel, Global Scope만을 이용해서 코루틴을 작성 해오다가 최근 큰 낭패를 본적이 있습니다. 물론 Scope의 정의를 본다면 앱의 작동에는 문제가 없었지만 이에 대한 정의를 제대로 알고 사용하지 않았다면 추후에 더 큰 문제를 발생할 수 있었기에 좀 더 정확하게 알아보았고, 이 내용을 작성하였습니다.