앱을 막힘없이 효율적으로 동작시키기 위해서는 어떻게 해야할까요?
사람이 물체를 인지하는 과정은 눈이 보내는 신호를 뇌가 받아들이는 구조입니다. 그리고 빠르게 보여지는 연속적인 이미지를 인식하는데에는 한계가 있습니다. 보통 사람은 초당 60프레임의 연속된 움직임과 그 이상의 프레임의 움직임의 차이를 느끼지 못한다고 합니다.
1000ms / 60frames = 16.666..ms/frame
따라서, 사용자가 스마트폰의 화면에서 움직임이 부드럽다고 느끼도록 하기 위해서는 16ms마다 한 프레임을 그리는 작업(통신, 렌더링, 입력 ,처리)을 완료해야합니다.
하지만, 앱에 필요한 적업 중에서 16ms보다 긴 처리 시간을 요구하는 작업(네트워크 통신, 데이터베이스 작업, JSON 파싱) 등이 있습니다. 다. 이 긴 작업이 메인 스레드에서 처리된다면 화면이 느리거나 ANR이 발생할 수 있습니다. 그러므로 안드로이드 개발에서는 UI Thread(메인 스레드)에서 최소한의 작업을 하고, Worker Thread(백그라운드 스레드)에서 긴 작업을 처리해야 합니다.
그렇다면, Worker Thread에서 단순히 오래 걸리는 작업을 처리하면 효율적일까요?
회원 정보, 뉴스 기사, 날씨 정보 총 3개의 네트워크 통신을 해서 한 화면에 정보를 표시해야한다고 가정해보겠습니다. 만약 회원 정보를 서버에서 가져온 후에 뉴스 기사 정보를 가져오고, 그 후에 날씨 정보를 가져온다면 화면에 정보를 표시하는데 상당히 오랜시간이 소요될 것입니다. 예시와 같이 오래걸리는작업들을 효율적으로 처리하기 위해 비동기 처리가 필요합니다.
비동기(Asynchronous) 처리를 통해 개발자는 여러 작업을 수행할 때 앞서 실행 했던 작업의 끝마침 여부와 상관없이 다음 작업이 수행할 수 있습니다. 따라서, 안드로이드 프로그래밍에서는 Worker Thread에서 비동기 처리를 통해 긴 작업을 수행하고, 작업이 완료되면 UI Thread에 구현해 놓은 결과를 파라미터로 하는 callback 함수를 통해서 화면을 업데이트 하게 됩니다.
병렬성 vs 동시성
처리해야 할 작업 A와 B 두 개가 있다고 가정해봅시다.
1. 작업을 처리할 수 있는 코어의 수가 두 개 이상인 경우
처리 작업을 진행할 수 있는 코어가 두 개가 있다면, A 작업과 B 작업을 동시에 진행하여 빠른 속도로 작업을 처리할 수 있습니다. 이것이 병렬성 프로그래밍 입니다.
2. 작업을 처리할 수 있는 코어의 수가 두 개 미만인 경우
처리 작업을 진행할 수 있는 코어가 한 개라면, 병렬성 프로그래밍과 같이 두 개의 작업을 동시에 진행할 수 없습니다. 따라서 A 작업을 진행하다가 suspend 등으로 기다려야 하는 시간에 B 작업을 진행하다가 A 작업이 재개되면 다시 돌아와 A 작업을 진행하여 두 작업이 동시적으로 진행되는 것처럼 보이게 처리하는 하는 것을 동시성 프로그래밍 이라고 합니다. 그리고 코루틴(Corountine)은 이러한 동시성 프로그래밍을 지원하는 설계 패턴입니다.
코루틴(Corountine)
코루틴은 Lightweight Thread 라고도 부릅니다. 작업 하나하나에 Thread 를 할당하는 것이 아닌 'Object' 를 할당해주고, 이 Object 를 자유롭게 스위칭함으로써 Context Switching 비용을 대폭 줄이고 작업을 효율적으로 분배하여 동시성을 보장합니다.
코루틴의 특징
- Dispacher(코루틴이 실행을 특정 스레드 풀로 전달)를 간단히 설정 할 수 있음
- suspend 키워드를 만난 Kotlin 컴파일러는 내부적으로 콜백 코드를 생성하여, 코루틴은 반복적인 들여쓰기로 인한 콜백 기반 코드를 순순차적인 코드로 작성할 수 있어서 가독성 증가 및 코드를 단순화 할 수 있음
- 스레드에 비해 적은 생성 비용, 특정 스레드에 종속되지 않음
- 여러 개의 코루틴을 실행한다고 했을 때 코루튼 1을 실행하던 중에 Context Switching 으로 스레드를 바꾸며 코루틴 2를 실행하는 것이 아니라 기존 스레드 위에서 코루틴 1을 정지시키고 코루틴2를 실행한다. 이러한 방식으로 빠른 연산 및 메모리 비용 측면에서 효율적임
- 코루틴의 수명을 제한하는 특정 Scope(GlobalScope, CoroutineScope, ViewModelScope, LifecycleScope)를 통해서 메모리 누수를 감소시킴
* 프로세스 : 운영체제로부터 자원을 할당받은 작업의 단위.
* 스레드 : 프로세스가 할당받은 자원을 이용하는 실행 흐름의 단위
'안드로이드 > Coroutine' 카테고리의 다른 글
Coroutine 예외처리 (0) | 2023.03.08 |
---|---|
Coroutine Flow (0) | 2023.02.13 |
[안드로이드] Coroutine의 Dispatchers.IO 와 Dispatchers.Default의 차이 (0) | 2022.04.12 |
[안드로이드] Coroutine Scope / Thread vs Corountine (0) | 2022.04.08 |