Reactive Programming Framework
수행원
9 월 7 일 · 14 분 읽음
크레딧 : "); background-size: 1px 1px; background-position: 0px calc(1em + 1px);">MR.Cole_Photographer
새로운 응용 프로그램 개발의 여정을 시작할 때 팀은 응용 프로그램을 구축 할 기본 기술을 설정해야합니다. 현대의 모바일 응용 프로그램 개발에서 이러한 기술 영역 중 하나는 비동기 프로그래밍 지원을 선택하는 것입니다. 팀이 스레드 전체에서 작업 수행 문제를 처리하기 위해 자체 시스템을 구현할 수 있지만 대부분의 개발자는 테스트를 거친 기존 라이브러리를 사용하여 무거운 작업을 수행하는 것을 선호합니다. 그런 다음 도메인에서 발생하는 문제에 대해 자유롭게 작업 할 수 있습니다.
현대 Android 개발에는이 작업을 처리하기위한 많은 솔루션이 있습니다. 가장 널리 사용되는 것은 RxJava와 Kotlin의 기본 코 루틴 라이브러리입니다. 이 두 라이브러리는 종종 경쟁자로 제시되어 팀이 하나를 선택하고 커밋해야합니다. 이것은 잘못된 이분법입니다. 응용 프로그램은 동일한 코드베이스 내에서 두 시스템의 장점을 모두 활용할 수 있습니다. 그럼에도 불구하고 새로운 그린 필드 애플리케이션의 개발은 해당 팀이 대부분의 문제에 대한 기본 솔루션으로 표준화 할 수있는 시스템을 만들 수있는 기회를 제공합니다. 팀의 기본 선택에서 벗어난 솔루션의 사용을 권장하는 (또는 필요한) 예외적 인 사례가있을 수 있지만 라이브러리를 사용하면 해당 라이브러리에 대한 팀의 기술을 개발할 수 있습니다.
RxJava를 기본값으로 설정하는 것과 Kotlin의 코 루틴을 선택하려면 각각에 대한 연구와 이해가 필요합니다. 다음은 현재 Kotlin의 Coroutines와 RxJava가 제공하는 기능을 요약하여 현재이 두 가지 옵션을 평가하는 팀의 고려 사항입니다. 다른 옵션도 사용할 수 있습니다. Reactor 및 Reactive Streams는 대체 가능한 실행 가능성으로 생각됩니다.
Kotlin의 다양한 비동기 언어 기능을 검사하기 전에 콜드 스트림 과 핫 스트림 의 개념적 차이를 이해하는 것이 중요 합니다.
콜드 스트림은 가치 스트림을 방출하는 계산을위한 청사진으로 생각할 수 있습니다. 구조는 정의 및 준비되었지만 실행되지 않으며 다운 스트림 소비자가 생산자에게 신호를 보낼 때까지 스트림에서 배출이 이루어지지 않습니다. 데이터를 수신합니다. 많은 Android 개발자에게 익숙한 콜드 스트림의 예로는 RxJava의 Flowable 및 Observable 스트림 유형이 있습니다. Kotlin은 Flow 시스템을 통해 콜드 스트림에 대한 지원을 제공합니다 (출시 예정).
핫 스트림 은 가입자의 상태에 관계없이 방출되는 값의 스트림을 나타냅니다. 배출 된 데이터의 소비자가 배출량을 처리하는 방법은 고려되지 않습니다. 이러한 배출의 다운 스트림 프로세서가없는 경우에도 스트림은 값을 방출합니다. 핫 스트림은 소비자의 상태에 관계없이 값을 방출하므로 값은 한 번만 처리됩니다. Kotlin 언어는 Channel API를 통해 핫 스트림을 지원합니다.
코 틀린의 비동기식 리 액티브 프로그래밍에 대한 이해에 추가적으로 중요한 것은 코 루틴 개념입니다. 코 루틴은 개발자가 일회성 작업을 수행 할 수있는 간단한 솔루션을 제공 할뿐만 아니라 채널 및 흐름 API가 모두 구현되는 기초를 나타냅니다. AsyncTask 또는 RxJava의 Single, Completable 및 Maybe 스트림 유형의 사용법에 익숙한 Android 개발자는 코 루틴의 일반적인 사용 사례를 이해하기위한 좋은 기반을 찾을 수 있습니다.
코 틀린의 코 루틴은 채널과 흐름이 모두 구현되는 기초입니다. 코 루틴은 일반적으로 경량 스레드라고도하며 스레드처럼 실행되지만 인스턴스화의 오버 헤드 비용이 크게 감소하고 실행 일정을 추가로 절약 할 수 있습니다. 코 루틴은 suspend 키워드를 통해 전통적인 함수 구조와의 인터페이스를 지원합니다. 이는 해당 함수의 내용이 실행을 중지 할 수 있음을 나타냅니다.이 중지 중에 다른 코 루틴이 실행될 수 있으므로 모든 계산 리소스를보다 효율적으로 사용할 수 있습니다. 이 서스펜션은 개발자가 코 루틴이 실행되는 범위를 정의 할 수있는 구조적 동시성에 대한 아이디어를 제공하는 중요한 구성 요소입니다.
모든 코 루틴은 CoroutineContext에서 실행됩니다.
모든 컨텍스트에는 코 루틴이 실행되는 스레드를 결정하는 코 루틴 디스패처가 포함됩니다.
Kotlin은 기본적으로 몇 개의 디스패처를 제공하며 개발자가 필요한 경우 자신의 디스패처를 구현할 수 있습니다.
다른 코 루틴 내에서 시작된 코 루틴은 부모 코 루틴의 범위를 상속하며 새 코 루틴의 작업 속성은 부모 의 자식 이라고합니다 .
부모 코 루틴을 취소하면 모든 코 루틴의 자손이 취소됩니다.
이것은 코 루틴의 누출을 방지하도록 설계되었습니다.
부모님을 취소하라는 요청에 따라 합당한 시간 내에 취소하기 위해서는 아동 코 루틴이 여전히 협조해야합니다. 이러한 이유로 개발자가 실행중인 코 루틴 (특히 장기 실행 또는 루핑 코 루틴) 내에서 CoroutineScope 객체에 의해 노출되는 isActive 확장 등록 정보를 확인하는 것이 중요합니다.
GlobalScope에서 시작된 코 루틴에는 부모가 없으며 독립적으로 운영됩니다. 메모리 누수를 방지하고 작업 관리를 가능하게하려면 가능한 경우 GlobalScope 사용을 피해야합니다.
부모 코 루틴은 개발자가 대기 메커니즘을 수동으로 관리 할 필요없이 자녀의 완료를 기다리는 동안 완료시 일시 중단됩니다. 부모는이 동작을 달성하기 위해 자식을 추적하거나 Job.join ()을 명시 적으로 호출 할 필요가 없습니다. 이는 지속적인 작업 누출을 방지하는 데 유리합니다.
코 루틴의 이름을 지정하여 개발자에게 로깅 및 디버깅에 대한 가독성을 향상시킬 수 있습니다.
코 루틴의 수명주기는 CoroutineScope에 의해 관리됩니다. 이 범위는 위에서 언급 한 컨텍스트 및 작업 시스템에 대한 추상화입니다.
Android 개발자는 일반적으로 Android 활동 라이프 사이클에서 제공하는 프레임 워크 내에서 CoroutineScope를 구현하여 해당 Coroutine의 컨텍스트, 취소 또는 정리를 명시 적으로 관리 할 필요없이 구현 활동에서 Coroutine을 실행할 수 있습니다.
CoroutineScope에서 시작된 코 루틴을 시작 범위의 자식이라고합니다.
부모-자식 관계는 구조적 동시성의 패턴을 설정하여 코 루틴 모델로 작성된 코드 구조를 이전 병렬 구현과 차별화합니다.
구조적 동시성 모델은 특정 범위에서 코 루틴을 시작해야한다는 요구 사항을 설정하기위한 기초입니다.
코 루틴은 화재 및 잊어 버린 백그라운드 작업을 실행하기위한 이상적인 솔루션입니다. AsyncTasks에 작업 위임에 익숙한 Android 개발자는 코 루틴으로의 전환이 코드 라인을 절약하고 성능을 저하시키지 않으면 서 사용 성과 가독성을 모두 향상시킵니다. doInBackground () 메서드를 재정 의하여 한 번 구현 된 논리는 단순히 일시 중단 함수로 작성된 다음 제공된 백그라운드 디스패처 중 하나에서 실행될 수 있습니다.
일반적으로 코 루틴을 시작하는 함수는 CoroutineScope 인터페이스에서 확장으로 정의됩니다. 이 규칙은 코 루틴 기능이 다소 자체 문서화되도록하는데, 그 기능의 내용이 코 루틴으로 실행되어야한다는 코드를 읽는 미래의 개발자에게 즉시 명백해지기 때문입니다.
Channels in Kotlin represent hot streams of data. When applied, they are an effective means of allowing coroutines to communicate multiple values (as opposed to the deferred system, which can communicate only a single value). Creation of a channel is accomplished by implementing the Channel interface, values are emitted to the channel via the send() function and handled via a receive() function. Note that both send() and receive() are suspending functions, making the channel API similar to Java’s familiar BlockingQueue interface while being more idiomatic to the Kotlin language. Additional deviation from BlockingQueue can be seen when observing that channels can be closed, which guarantees that all previous calls to send() have been completed and then prevents future emissions on the channel.
One common pattern in channels is the pipeline pattern, where one coroutine is tasked with producing values while other coroutines are processing those values and producing other results. This operates similarly to the RxJava pattern of defining functions that take an Observable as a parameter and returning a modified Observable (or other stream primitive)
Channels can have multiple coroutine receivers, as well as multiple coroutine producers. The developers of the API refer to these patterns as Fan-Out and Fan-In.
The Fan-Out pattern enables the handling of high-frequency emissions from a single channel across many consumer coroutines, each of which can perform processing in parallel. This handles some of the backpressure-related concerns that are common with hot channels.
팬에서의 패턴은 단일 채널에서 여러 코 루틴의 배출량의 통합을 가능하게한다. Android 개발자는 Otto와 같은 이벤트 버스 솔루션을 사용하거나 RxJava로 작성된 구현에서이 패턴에 익숙 할 수 있습니다.
채널은 이벤트 버퍼링을 허용합니다. 개발자는 채널 생성시 버퍼 크기를 지정합니다. 이 버퍼는 생산 코 루틴이 채워질 때까지 실행을 계속 한 다음 코 루틴을 일시 중단시킵니다.
채널은 채널 에서 receive () 함수를 실행하는 첫 번째 소비 코 루틴이 방출을 얻는다는 점에서 공정한 것으로 설명됩니다 .
RxJava 스트림과 같이 채널 사용을 마치면 채널을 닫아야합니다. 닫힌 채널에서 방출을 시도하면 ClosedSendChannelException이 발생합니다.
Kotlin Flow는 Kotlin 언어로 제공되는 콜드 스트림을위한 기본 반응성 프로그래밍 솔루션입니다. 기존 코 루틴 언어 기능 위에 구축 된 Flows는 원래 ReactiveX 표준에 도입 된 익숙한 아이디어의 변형을 나타냅니다. 현재 흐름 API는 안정적이지만 (현재 RC2에있는 버전 1.3.0 현재) 완전히 릴리스되지 않았습니다.
Flow 시스템과 반응 프로그래밍의 친숙한 RxJava 구현 간의 주요 차이점은 사용자에게 기본적으로 제공되는 연산자의 범위입니다. Kotlin의 확장 기능 API를 활용함으로써 Flows는 RxJava와 비교할 때 소수의 연산자를 노출합니다. 이러한 API 범위의 감소는 개발자가 무수한 운영자의 복잡성에 익숙해지기 위해 많은 시간을 소비 할 필요가 없으며, 비즈니스 유스 케이스와 관련된 조작자 만 구현해야한다는 것을 의미합니다.
연산자
Kotlin의 Flow 시스템이 외부 라이브러리로 구현되지 않고 언어로 내장되어 있기 때문에 제공된 많은 연산자는 개발자가 익숙하게 사용할 시퀀스 연산자와 동일하게 작동합니다.
중간 연산자
업스트림 흐름에 적용되면 다운 스트림 (콜드) 흐름을 반환하고 실행이 빠릅니다.
향후 실행을 위해 운영 체인 설정
예 :지도, 필터, flatMap
독립 연산자
서 스펜 딩 기능
예 : collect, single, reduce, toList
launchIn → 현재 범위에서 플로우 수집 시작
기본적으로 모든 흐름은 순차적이며 단일 코 루틴에 바인딩되며 구조적 동시성에 대한 예외가 존재합니다.
핫 스트림과 콜드 스트림 간의 전환은 채널과 해당 API를 통해 지원됩니다 : channelFlow, produceIn, broadcastIn.
흐름 만들기"); background-size: 1px 1px; background-position: 0px calc(1em + 1px);">flowOf (…) 함수는 고정 된 값 세트에서 플로우를 작성합니다."); background-size: 1px 1px; background-position: 0px calc(1em + 1px);">다양한 유형의 "); background-size: 1px 1px; background-position: 0px calc(1em + 1px);">asFlow () 확장 함수를 흐름으로 변환합니다."); background-size: 1px 1px; background-position: 0px calc(1em + 1px);">flow {…} 빌더 함수는 순차적 호출에서 "); background-size: 1px 1px; background-position: 0px calc(1em + 1px);">방출 함수로 임의의 흐름을 구성 합니다."); background-size: 1px 1px; background-position: 0px calc(1em + 1px);">channelFlow {…} 빌더 함수는 잠재적으로 동시 호출에서 "); background-size: 1px 1px; background-position: 0px calc(1em + 1px);">송신 함수 로의 임의 플로우를 구성 합니다.
상황 보존플로우 컨텍스트를 변경하는 방법 은 업스트림 컨텍스트를 변경하는 "); background-size: 1px 1px; background-position: 0px calc(1em + 1px);">flowOn 연산자 ( "flowOn 연산자 위의 모든 항목")뿐입니다.
모든 흐름 구현은 동일한 코 루틴에서만 방출되어야합니다.
예외 투명성
흐름 구현은 다운 스트림 흐름에서 발생하는 예외를 포착하거나 처리하지 않습니다.플로우에서 예외 처리는 "); background-size: 1px 1px; background-position: 0px calc(1em + 1px);">catch 연산자를 사용하여 수행해야하며 모든 다운 스트림 예외를 전달하면서 업스트림 플로우에서 발생하는 예외 만 포착하도록 설계되었습니다.
구독 개념이 없으므로 흐름 구독을 유출 할 수 없습니다.
구독에 가장 가까운 것은 수집 기능입니다.
흐름의 맥락 밖에서 코 루틴을 유출시킬 때주의를 기울여야합니다.
GlobalScope의 사용은 코 루틴이 누출되기 쉬운 일반적인 지표 중 하나입니다.
Coroutines properly scoped to a component of the Android application lifecycle are more leak-proof than their RxJava counterparts, since the framework will handle cancelation rather than developers needing to remember to call dispose() on an instance of Disposable during the destruction of the Android component (usually in onDestroy()).
Unification of onError and onCompleteFlow is"); background-size: 1px 1px; background-position: 0px calc(1em + 1px);"> Reactive Streams compliant, you can safely interop it with reactive streams using"); background-size: 1px 1px; background-position: 0px calc(1em + 1px);"> Flow.asPublisher and "); background-size: 1px 1px; background-position: 0px calc(1em + 1px);">Publisher.asFlow from kotlinx-coroutines-reactive module.
The popular RxJava library emerged shortly after the concept of Reactive Streams began gaining momentum. It became heralded as a new standard for the way that applications were constructed on the JVM. Now preparing for the release of version 3 of the API, it has gained wide adoption within the Android developer community. Libraries relied upon by major players in the industry commonly expose interfaces that conform to the RxJava specification; some of Google’s internally-developed Android Jetpack suite of libraries have taken up the RxJava banner. This significant adoption has made the usage of the library familiar to most professional Android developers; communication about reactive concepts are frequently written in the context of RxJava.
Kotlin의 코 루틴과 달리 RxJava의 스트림은 모두 동일한 기본 패턴을 따릅니다. 스트림이 선언 된 후 유동 API 패턴 (빌더 패턴과 유사)을 따르십시오.
RxJava의 모델에서 스레딩은 스케줄러에 의해 관리됩니다. 이것들은 동시성에 대한 추상화로, 작업 위임 및 다양한 스레드 풀에 대한 응답을 단순화합니다. 라이브러리는 스케줄러 유틸리티 클래스를 통해 여러 풀을 노출합니다. 추가 풀은 플랫폼별로 추가됩니다. 모든 플랫폼에 노출 된 풀에는 Schedulers.computation (), Schedulers.io (), Schedulers.single () 및 Schedulers.trampoline (); Android 개발자는 AndroidSchedulers 유틸리티 클래스가 제공하는 추가 풀을 조사하는 데 관심이 있습니다.
RxJava 라이브러리에는 공개, 공개 상태에서 두 가지 주요 버전이 있습니다. 라이브러리 버전 1은 현재 사용되지 않으며 사용 가능한 것으로 간주해서는 안됩니다. 라이브러리의 버전 2는 2020 년 12 월 31 일까지 버그 수정 및 설명서 업데이트를 통해 지원 될 예정입니다. 라이브러리의 버전 3은 현재 권장 버전이며 릴리스 후보 2가 최신 버전입니다. 새로운 응용 프로그램을 개발할 때 RxJava가 의도 한대로 응용 프로그램 아키텍처의 핵심이되는 오래된 버전의 라이브러리를 채택하는 것은 실수입니다. 이런 이유로 새 응용 프로그램은 3 버전에서 표준화하기 위해 모든 노력을 기울여야합니다. 가능하다면 RxJava.
Flowable은 RxJava가 제공하는 기본 콜드 스트림 유형으로, 단일 스트림에서 0에서 많은 배출량을 허용합니다. Reactive-Streams 표준을 지원하며 이벤트 방출 배압을 처리 할 수 있습니다.
Flowable과 같이 Observable은 0에서 많은 배출물을 지원하지만 명시적인 배압 처리를 지원하지 않는다는 점에서 다른 콜드 스트림입니다.
RxJava는 핫 스트림과 유사한 여러 주제를 노출합니다. 이러한 주제에 게시 된 이벤트는 다운 스트림 관찰자에게 전파되거나 소비자가없는 경우 이벤트가 손실됩니다. 개발자는 다양한 주제를 이용할 수 있으며, 각각은 약간 다른 이벤트 처리를 제공합니다. 일부는 버퍼링, 재생, 멀티 캐스팅이 가능합니다.
Single은 정확히 하나의 항목 또는 오류를 발생시키는 스트림에 대한 RxJava의 솔루션입니다. Kotlin 세계에서 가장 직접적인 함수는 값을 반환하거나 예외를 throw하는 일시 중단 함수입니다.
RxJava의 버전 1과 2의 중요한 차이점은 Null 허용 처리에있었습니다. 라이브러리의 버전 1은 모든 스트림에서 널 배출을 허용하므로 개발자가 수동으로 널 점검 (또는 필터링)을 구현해야합니다. 단순화하기 위해, 라이브러리의 버전 2는 널 (null) 방출을 지원하지 않으므로 스트림이 널을 방출하려고 시도하는 경우 예외가 발생합니다. 이 변경으로 인한 격차를 해결하기 위해, 아마도 스트림 유형이 만들어져 0 또는 1 개의 배출 또는 오류가 허용됩니다. 요청 유형의 스트림은 요청이 실패 할 가능성이있는 API 요청에 일반적으로 사용됩니다.
개발자가 RxJava에서 액세스 할 수있는 최종 스트림 유형은 Completable이며 배출이없는 흐름을 나타내며 완료되었거나 오류가 발생했다는 신호 만 나타냅니다. 이 유형의 플로우는 일반적으로 처리를 위해 백그라운드 스레드에 작업을 위임하고 장기 실행 계산을 완료하거나 화재 및 잊어 버린 작업을 관리하는 데 사용됩니다.
Integration with other key libraries is a key factor that must be considered when choosing a reactive framework — making the wrong decision in this regard could potentially preclude a team from using a technology that later becomes industry-standard. To that end, in considering Kotlin and RxJava we observe that the majority of the top libraries and technologies that Android teams are interested in using provide full support for both systems, either natively or via a companion library. It is likely not necessary to base the decision of which reactive framework to adopt on the support provided by third-party libraries.
전부는 아니지만 많은 안드로이드 앱 아키텍처는 깔끔한 모듈 구조를 만드는 데 관심이 있습니다. 모듈 그래프의 구성에 의해 확립 된 구조는 최신 Android 앱이 생성되는 방법에 대한 많은 측면을 알려주며 개발 팀이 새로운 기능 (예 : 동적 기능 모듈)을 수용 할 수있는 능력까지 확장됩니다. 모듈성에 대한 관심과 그에 따른 우려의 분리가 주어짐에 따라 개발자는 모듈 간의 재사용 성과 깨끗한 인터페이스를 유지하는 데 점점 더 관심을 기울이고 있습니다. 인터페이스 개발에 대한 오랜 모범 사례 중 하나는 모듈 소비자가 특정 라이브러리 또는 기술을 인터페이스 사용의 전제 조건으로 채택하지 않아도되는 것입니다. 이는 언어의 일부로 제공되기 때문에 비 동기화를 위해 Kotlin 시스템에 뚜렷한 이점을 제공합니다. 타사 라이브러리보다 개별 모듈 간의 인터페이스에 대해 Kotlin 시스템을 표준화하면 소비자 (내부 또는 외부)가 추가 종속성을 다운 스트림하지 않고 호환 될 수 있습니다.
문제의 프로젝트를 수행하는 개발 팀에 대한 이러한 API의 친숙 함은 사소한 고려 사항이 아닙니다. 코 루틴과 ReactiveX는 각각 상당한 학습 곡선을 가지고 있습니다. 각 시스템에 대한 팀의 온 보딩 오버 헤드는 생산성을 요합니다. 두 경우 모두 목표는이 시간 동안 팀의 생산성을 극대화하는 동시에 좌절을 최소화하는 것입니다. 이를 염두에두고 각 API를 중심으로 개발 된 에코 시스템은 팀이 결정을 내릴 때 고려해야합니다.
RxJava 에코 시스템은 강력한 커뮤니티와 수많은 서적, 기사, 비디오 및 기타 리소스로 시간이 지남에 따라 성숙되었습니다. 이러한 리소스는 여러 수준의 경험과 기술에 액세스 할 수있는 일반적으로 참조되는 안정적인 지식을 구축하기 위해 시간이 지남에 따라 많은 반복을 거쳐 개발되었습니다. 이 중요한 생태계는 RxJava의 모퉁이에서 중요한 지점이지만 팀은 커뮤니티 유지 문서에 존재하는 수명주기를 고려해야합니다. 업계에서 여러 버전의 RxJava 라이브러리를 사용하는 경우 다음 문서에만 적용되는 위험이 있습니다. 라이브러리의 특정 버전. 최신 문서와 모범 사례 만 따르도록 관리하는 것이 성공에 중요합니다. RxJava 라이브러리는 커뮤니티에서 개발되었으며 Android 생태계에서 확립 된 힘에 의해 직접적으로 지원되지 않기 때문에 선호도가 떨어지고 업데이트가 중단 될 가능성이 있습니다. 이러한 상황으로 인해 의존하는 개발자는 자신의 코드를 유지 관리해야 할뿐만 아니라 라이브러리 자체에서 발생하는 문제를 개별적으로 해결해야하는 어려운 위치에있게됩니다.
Kotlin 언어 및 Android 용 프로그래밍 언어로 널리 사용되는 것은 Java 및 ReactiveX에 비해 젊습니다. 이는 개발자에게 모범 사례에 대한 교육을 제공 할 수있는 리소스가 적다는 것을 의미합니다. Android 세계가 Kotlin 중심 개발로 더욱 빠르게 이동함에 따라 Google의 Kotlin이 Google I / O 2017에서 Android의 최고급 언어로 설립 된 후 Kotlin에 대한 문서 작성 속도가 증가하고 발표에 의해 더욱 발전했습니다. 이러한 개발은 Kotlin의 비동기 API에 대한 추진력을 제공하여 Android 생태계에서 발전하고 있습니다. 개발자는 이러한 API가 계속 지원 될 것이라고 확신 할 수 있습니다. 인기있는 Android Jetpack 툴 세트는 이미 Kotlin 시스템을 사용하여 강력한 인터페이스를 게시했습니다. Kotlin의 API 및 도구 주위에 존재하는 공식 문서 및 커뮤니티 제작 리소스는 모두 속도가 느려지지 않고 매일 향상됩니다.
조항로마 Elizarov, "); background-size: 1px 1px; background-position: 0px calc(1em + 1px);">"콜드 흐름, 뜨거운 채널"Roman Elizarov, "); background-size: 1px 1px; background-position: 0px calc(1em + 1px);">“Kotlin Flow의 단순한 디자인”Roman Elizarov, "); background-size: 1px 1px; background-position: 0px calc(1em + 1px);">“반응 스트림과 코 틀린 흐름”Mayowa Adegeye, "); background-size: 1px 1px; background-position: 0px calc(1em + 1px);">“Kotlin Coroutine의 흐름에 대한 초기 모습”Jag Saund, "); background-size: 1px 1px; background-position: 0px calc(1em + 1px);">“코 틀린 : 코 루틴과 수로로 다이빙하기”Roman Elizarov, "); background-size: 1px 1px; background-position: 0px calc(1em + 1px);">“구조화 된 동시성”
API 설명서"); background-size: 1px 1px; background-position: 0px calc(1em + 1px);">kotlinx.coroutines.flow 패키지"); background-size: 1px 1px; background-position: 0px calc(1em + 1px);">코 틀린 채널"); background-size: 1px 1px; background-position: 0px calc(1em + 1px);">코 틀린 코 루틴 컨텍스트 및 디스패처
비디오"); background-size: 1px 1px; background-position: 0px calc(1em + 1px);">KotlinConf 2018 —로만 엘리자 로프의 실제 코 틀린 코 루틴