Coroutine
코루틴은 작업 수행을 일시 정지 및 재개될 수 있도록 하는 프로그래밍 구성요소입니다. 코루틴은 서브루틴을 일반화합니다. 협력 작업, 예외, 이벤트 루프, 반복자, 무한 목록 및 파이프와 같은 친숙한 프로그램 구성 요소를 구현하는 데에 매우 적합합니다.
멜빈 콘웨이(Melvin Conway) 는 1958년 어셈블리 프로그램 구축에 이를 적용하면서 Coroutine 이라는 용어를 만들었습니다. 이후 이에 대한 설명은 1963년에 처음 발표되었어요. 즉, 코루틴이 비교적 최근에 등장한 개념이라 알고 있는 분들이 계신데, 전혀 그렇지 않습니다.
Coroutine 은 Co-Routine 이라 쓸 수 있는데, Routine 은 '컴퓨터 프로그램의 일부로서, 특정한 일을 실행하기 위한 일련의 명령' 을 일컫습니다. 어쩐지 그 정의가 익숙한데, 바로 메서드의 정의와 같습니다. 루틴이라는 말이 나오면 꼭 따라 나오는 서브루틴. 서브루틴은 메서드 내부에 메서드가 있는 경우, 그 안쪽의 메서드를 서브루틴이라 칭합니다.
보통 영단어 앞에 Co- 라는 접두사가 붙으면 coexist 를 의미하므로, 함께 존재한다는 의미를 가집니다. 즉, 프로그래밍의 동시성을 말하는데요. 하나의 스레드는 한 순간에 하나의 루틴만을 수행하지만, 스위칭의 속도가 빨라 수 개의 루틴이 동시에 존재하는 것처럼 인지하도록 합니다.
이러한 이유로, 비동기로 작성해야했던 코드를 코루틴과 함께 작성하면 마치 동기 코드를 작성하고 있는 듯한 느낌을 받을 수 있습니다.
Coroutine In Android
안드로이드에서의 코루틴은 매우 간단합니다!
CoroutineScope(Dispatchers.Main).launch {
doSomething()
}
CoroutineScope 를 하나 열어주고, Dispatcher 를 지정해준 뒤, launch() 메서드를 실행해주면 끝입니다.
Dispatcher 에는 Main, IO, Default, Unconfined 로 총 네 가지 선택지가 존재하며, 이들은 모두 스레드 관리 객체입니다. 별도로 지정하지 않는 경우에는 Dispathers.Default 가 할당되어 작업을 수행합니다.
Dispatcher 에 관한 설명은 이전에 설명해두었으니, 다음 포스트를 참고하시면 좋겠습니다.
위 포스트에서 이야기하듯, Dispatcher 들은 스레드 풀에 접근하고 해당 스레드 풀 내의 유휴 스레드에 코루틴 작업을 할당하는 오브젝트입니다.
저는 평소와 다름없이 코루틴을 사용하다가, 코루틴의 작동 방식이 동시성 프로그래밍의 대표적 개념인 그린 스레드와 비슷하다고 생각했고, 이에 대한 궁금증이 생겨 이번 포스트를 작성하게 되었습니다.
Light-Weight Thread
코루틴과 관련된 포스트에는 '경량 스레드' 라는 용어가 꼭 나옵니다. 말 그대로 스레드이긴 한데, 스레드보다 가벼운 스레드를 의미하는데요. 그렇다면 코루틴은 경량 스레드라 불리우는 또 다른 개념인 그린 스레드와 관련이 있는 걸까요?
그린 스레드
그린 스레드는 우리가 알고 있는 네이티브 스레드를 흉내낸 가짜 스레드입니다. VM 이나 라이브러리 등에 의해 관리되며, 개발자가 직접 제어할 수 있기 때문에 User-Level 스레드라고도 불립니다. 그린 스레드는 싱글 코어 환경을 위해 설계된 모델이기 때문에 여러 개의 그린 스레드를 생성할 수 있습니다.
그렇다면 네이티브 스레드와 그린 스레드는 관리 및 스케줄링의 역할을 담당하는 것의 차이 말고는 다른 점이 없을까요?
그린 스레드와 네이티브 스레드의 차이점
- 스레드 스케줄링 알고리즘 : 그린 스레드의 스케줄링은 OS 가 아닌 언어나 라이브러리 수준에서 이루어지므로, 해당 언어나 라이브러리에서 채택한 알고리즘에 의해 스케줄링됩니다.
- 컨텍스트 스위칭 메커니즘 : 그린 스레드는 컨텍스트 스위칭이 필요한 경우, 유저 스페이스에서 진행됩니다. 이를 위해서는 스레드의 상태와 레지스터 정보 등을 저장하고, 다른 스레드의 상태와 레지스터 정보 등을 복원하는 작업이 필요합니다. 코루틴에서는 이를 스테이트 머신을 통해 해결합니다.
- 락 메커니즘 : 멀티 스레드 환경에서 동기화 문제를 해결하기 위해서는 락 메커니즘이 필요합니다. 당연히 그린 스레드 환경에서도 락 메커니즘이 필요하며, 이를 위해 뮤텍스나 세마포어 등의 동기화 기법을 사용합니다.
- 취소 메커니즘 : 그린 스레드는 유저 스페이스에서 동작하기 때문에, 커널 스레드와는 달리 강제 종료 자체가 어렵습니다. 따라서 취소 기능이 필요하며, 이를 위해 취소 요청을 받으면 해당 스레드는 종료되는 방식으로 동작합니다.
- 각 스레드마다 독립적 스택을 갖고 있으며, 스택은 해당 스레드가 수행하는 함수 호출과 반환을 위한 메모리 공간을 제공합니다. 스택의 크기는 스레드 생성시 설정할 수 있으며, 당연히 초과시 스택 오버 플로우가 발생할 수 있습니다.
그린 스레드에 대한 궁금증은 어느 정도 해결 되었습니다. 우리가 아는 코루틴과 굉장히 유사한 느낌입니다.
그린 스레드는 안드로이드 및 코루틴과 관계가 있을까요? 질문과 답변 형태로 알아봅니다.
🤔 안드로이드의 메인 스레드와 백그라운드 스레드는 그린 스레드인가요?
아닙니다. 안드로이드에서 UI 작업을 처리하는 메인 스레드와 I/O 작업을 처리하는 백그라운드 스레드는 모두 리눅스 커널이 제공하는 네이티브 스레드입니다. 메인 스레드는 안드로이드 시스템(리눅스 커널 계층 및 런타임 계층)에서 직접 관리되고, 백그라운드 스레드는 프레임워크 계층에 생성된 스레드 풀이 관리합니다.
🤔 그렇다면, Dispatcher Object 가 스케줄링하는 스레드 풀의 스레드는 그린 스레드인가요?
이 역시 아닙니다. Coroutine Dispatchers 는 네이티브 스레드에 코루틴 작업들을 스케줄링 합니다.
🤔 코루틴은 그린 스레드인가요?
네. 코루틴은 그린 스레드입니다. 언어 차원에서 제공 및 관리되고, 개발자가 이를 제어할 수 있습니다.
코루틴과 그린 스레드의 유사성과 차이점에 대해 간단히 알아보았습니다. 다소 비슷한 개념이라 연관이 있을 거라 생각했는데, 코루틴이 그린 스레드라는 개념에 포함되는 것이었습니다.
코루틴은 그 깊이가 대단한 기술입니다. 앞으로도 더욱 자세히 알아 볼 기회가 많을 것 같습니다.
'Android > Tech' 카테고리의 다른 글
[Jetpack Compose] Jetpack Compose 의 다양한 Side-Effect (0) | 2023.03.15 |
---|---|
Bitmap, Drawable, BitmapDrawable, ImageBitmap, AndroidBitmap (0) | 2023.03.13 |
[Jetpack Compose] Glide 와 Coil, 무엇을 사용하면 좋을까. (2) | 2023.03.07 |
안드로이드와 Clean Architecture (0) | 2023.02.11 |
JVM 의 Garbage Collector (0) | 2023.02.01 |