(Kotlin Coroutines) 001. Before know about Coroutines

코루틴을 배우기 전에 조금은 알아두어야할 것들.

코틀린 코루틴에 대해 알아보기전에,

코루틴이 해결하려는 것이 무엇인지 알아둘 필요가 있다.

코루틴이 해결하려는 문제 중 가장 큰 두 가지는 바로 동시성(Concurrency)병렬성(Parallelism) 이다.

1. 동시성(Concurrency)

동시성을 보장하지 않으면 “사용자”가 매우 불편해진다.

동시성이 무엇인지 위키피디아의 정의를 살펴보자.

Concurrency (computer science) : In computer science, concurrency is the ability of different parts or units of a program, algorithm, or problem to be executed out-of-order or in partial order, without affecting the final outcome.

컴퓨터 과학에서 동시성이란 어떤 프로그램이나 알고리즘 혹은 문제와 상관없이 결과에 영향을 미치지않으면서 순차적으로 실행되는 특징을 말한다.

동시성이 보장되지 않는다면 우리는 빌드를 걸어두고 개발을 이어서 할수도, 무언가를 다운받으면서 인터넷 서핑을 할 수도 없다.

즉, 일하면서 유튜브를 볼 수 없다는 뜻이다

이 동시성을 구현하기 위해 컴퓨터의 코어는 멀티스레드 환경을 구성하고 Context Switching을 통해 사용자로 하여금 모든 작업이 동시에 시작되는 것처럼 보여준다.

결론적으로 인지할 수 없을 정도로 빠른 시간내에 시분할로 작업되므로, 싱글 코어에서 멀티 스레드를 동작시키는 것이다.

2. 병렬성(Parallelism)

병렬성은 코어가 2개 이상인 경우 성립하므로 기본적으로 하드웨어가 뒷받침되어야 한다.

동시에 실행되는 것처럼 보이는 동시성과는 다르게 병렬성은 같은 시점에 같은 알고리즘을 동시에 실행한다.

이 병렬성은 크게 데이터 병렬성과 작업 병렬성으로 구분된다.

데이터 병렬성 은 전체 데이터를 쪼갠 뒤, 그 쪼갠 데이터들을 각각 벙렬처리하여 빠르게 작업을 수행하는 것을 말한다.

Java 8의 Stream.parallel()이 그 예시이다.

작업 병렬성 은 서로 다른 작업을 병렬처리하는 것을 의미한다.

하나의 서버가 여러 클라이언트의 요청을 개별 스레드에서 처리하는 것이 그 예시이다.

결론적으로 멀티코어에서 멀티 스레드를 동작시키는 것으로, 한 개 이상의 스레드를 포함하는 각 코어들이 동시에 실행되는 것이다.

3. 코루틴을 써야하는 이유

위에서 알아본 특징들처럼 비동기 및 병렬 프로그래밍에는 어려움이 따라오기 마련이다.

프로그래밍 언어는 이러한 문제를 해결하기 위해 콜백 방식이나, RxJava 등의 방법을 제공해준다.

허나 이 방법들은 문제를 해결할 수 있으나, 가독성이 안 좋아지거나 유지보수가 힘들다는 단점이 있다.

먼저 콜백 방식은 중첩되어서 사용하는 경우 Callback Hell 이란 문제를 발생시킨다.

1
2
3
4
5
6
7
callback("start") { result ->
callback(result) { result ->
callback(result) { result ->
// ...
}
}
}

Callback Hell 이란 위와 같이 계속해서 콜백 구조가 반복되어 Depth가 계속해서 늘어나는 현상을 말한다.

RxJava는 조금 다를까?

물론 RxJava를 쓰면 Callback Hell을 회피할 수는 있지만, 계속해서 Stream을 써야하며 이는 유지보수 비용의 증가를 유발한다.

반면에 코루틴은 비동기와 병렬성을 순차적으로 짤 수 있도록 구조화된 문법을 제공 해주며,

코루틴 Flow는 비동기와 병렬성을 Stream으로 풀어낼 수 있도록 해준다.

그렇다면 코루틴을 무조건 쓰는 것이 좋을까?

물론 정답은 없고, 현재 환경에 맞추어 선택하면 된다.

만약 개발중인 프로덕트에 난독화를 적용할 수 없는 환경이라면(오픈 소스라던지, SDK라던지) RxJava가 좀 더 경량화에 좋다.

kotlin으로의 마이그레이션이 진행중이어서 java와 kotlin이 혼재되어 있는 상황이라면 RxJava를 먼저 적용하는 것이 권장되고

KMM과 같이 kotlin 친화적 플랫폼이라면 코루틴이 권장된다.

반면에 현재 프로덕트가 Stream 기반이라면 RxJava를 써야 한다.

다만 구글이 현재 Kotlin을 밀어주고 코루틴이 대세로 떠오른 만큼 Stream까지 커버할 수 있는 Flow까지 익혀

코루틴과 Flow에 대한 기술셋을 익히는 것이 가장 합리적일 것이다.

4. Kotlin Coroutine의 간단한 정의

원활한 비동기 프로그래밍 개발을 위하여 Kotlin은 언어 레벨에서 코루틴이라는 도구를 제공한다.

코루틴은 상술 했듯 비동기적으로 실행되는 코드를 간소화하기 위해 사용할 수 있는 동시 실행 설계 패턴으로,

Kotlin 버전 1.3에 추가되었으며 다른 언어에서 이미 확립된 개념을 기반으로 한다.

코루틴 개념은 1963년에 출판된 논문에서 확인할 수 있으며, subroutine이나 thread 등과 비교한 글들도 쉽게 찾아 볼 수 있다.

참고 Design of a Separable Transition-Diagram Compiler(1963)

4.1. 비동기 프로그래밍 관점에서의 Coroutine 기능

  • Lightweight : 경량
    • 코루틴을 실행 중인 스레드를 차단하지 않는 정지를 지원하므로 단일 스레드에서 많은 코루틴을 실행할 수 있다.
    • 정지는 많은 동시 작업을 지원하면서도 차단보다 메모리를 절약할 수 있다.
  • Fewer memory leaks : 메모리 누수 감소
    • 구조화된 동시 실행을 사용하여 범위 내에서 작업을 실행한다.
  • Built-in cancellation support : 기본으로 제공되는 취소 지원
    • 실행 중인 코루틴 계층 구조를 통해 자동으로 취소가 전달된다.

마무리

이제 코루틴이 어떠한 역할을 하는 지 파악해보았으니, 다음 포스트부턴 예제를 통해 코루틴의 동작을 확인해보도록 하자.

References