RxJava와 Kotlin Coroutine

김말이·2023년 7월 16일
0

1️⃣ RxJava

  • RxJava는 ReactiveX를 Java로 구현한 라이브러리이다.
  • ReactiveX는 관찰 가능한 스트림을 사용하는 비동기 프로그래밍을 위한 API이다.
  • 동시성 문제, 다중 이벤트 처리, 백그라운드 처리 등의 문제를 해결하는 데 쓰인다.

✏️ Rxjava 적용

Observable

  • 어떤 데이터를 Observer가 처리할 수 있도록 포장하는 작업
  • Observer는 연산자(Operator)를 통해 기존 데이터를 참조, 변형하여 Observable을 생성한다.
  • Observable이 데이터를 발행하고 Event를 보내면 Observer는 Observable을 구독(Subscribe)소비(Consume)자를 생성한다.

    💡 Observable 클래스는 Observer Patter을 응용한 것이다.

val observer = object : Observer<Int> {
        override fun onComplete() {
            // Observable이 완료된 경우
        }
        override fun onSubscribe(d: Disposable) {
            // Observable이 데이터 전달할 준비가 되었을 때
            // 작업 취소를 위한 Disposable에 대한 레퍼런스를 받는다
        }
        override fun onNext(t: Int) {
            // Observable이 데이터를 전달할 때 호출
        }
        override fun onError(e: Throwable) {
            // Observable이 에러를 전달할 때 호출
            // Error가 발생하면 Complete 없이 종료
        }
    }
    Observable.just(1, 2, 3, 4).subscribe(observer)
  1. onComplete: 데이터 발행이 끝났음을 알리는 완료 이벤트를 Observer에 전달하여 onNext()를 더 호출하지 않음을 나타낸다.
  2. onNext: 하나의 소스 Observable에서 Observer까지 한 번에 하나씩 순차적으로 데이터를 발행한다.
  3. onError: 오류가 발생했음을 Observer에 전달한다.

Just

  • Observable 선언 방식

Subscribe

  • 수신한 데이터를 통해 어떤 행동을 할지 정의
  • 데이터를 수신할 구독자가 Subscribe 함수를 호출해야 Observable에서 데이터가 발행됨
Observable
	.just("hi","jrary")
	.subscribe(System.out::println)

2️⃣ Kotlin Coroutine

💡 Co(협동) + routine(루틴)

  • 메인 스레드가 블로킹될 수 있는 부분을 처리
  • 이전에 자신의 실행이 마지막으로 중단되었던 지점 다음의 장소에서 실행을 재개함
  • 비동기 처리를 순차적인 코드로 만들 수 있게 함

✏️ Coroutine을 사용하는 이유

RxJava와의 비교

  • 안드로이드 공식 언어가 자바에서 코틀린으로 바뀜
  • Jetpack에서 Coroutine에 대한 최고 수준의 품질 지원

퍼포먼스 향상

  • 기존 Java Thread에 비해 CPU 자원을 효율적으로 사용

간결한 코드

  • 알아야 하는 함수와 개념이 적어서 사용하기 쉬움
  • 비동기 코드 작성 시 가독성 있게 예외 처리가 가능
  • Multi Thread와 비교하여, Thread 간 통신과 Callback 구조로 코드가 흐르지 않음

✏️ Coroutine 적용

Coroutine 코드 흐름
1. 사용할 Dispatcher를 결정한다.
2. Dispatcher를 이용해서 CoroutineScope를 만든다.
3. CoroutineScope의 launch 또는 async에 수행할 코드 블록을 넘긴다.

CoroutineScope

  • Coroutine을 동작하기 위해서 CoroutineScope을 정의한다.
CoroutineScope(IO).launch{
	val resultStr = getResultFromApi()
    withContext(Main){
    	textView.text = resultStr
    }
}
  • launch : 코루틴으로 동작해야 할 코드 스쿱을 지정한다. 이때 이 스쿱에서 사용할 스케줄러를 함께 지정할 수 있으며, 지정하지 않을 경우 CoroutineScope에서 지정한 스케줄러를 사용한다.
  • Dispatchers : 코루틴에서 사용할 스케줄러를 정의하며, Default(Work Thread), Main(UI Thread) 등을 지정할 수 있다.
  • withContext : Coroutine 영역 바깥에 있는(Main 등) Context를 사용해야 할 때 오버헤드를 생성하지 않고 작업을 처리한다.
CoroutineScope(IO).launch{
	val resultStr = withTimeoutOrNull(10000) {
    	getResultFromApi()
    }
    if(resultStr != null){
    	withContext(Main) {
        	textView.text = resultStr
        }
    }
}
  • withTimeOutOrNull : 네트워크 타임아웃 처리를 할 때 사용한다. 초과 시 null을 반환한다.

Suspend

// API 통신의 결과를 반환받는 함수
suspend fun getResultFromApi(): String{
	//do something
    return RESULT_OK
}
  • Suspend는 그 함수가 비동기 환경에서 사용될 수 있다는 가능성을 내포함
  • 다른 Suspend 함수 또는 Coroutine 내에서만 호출할 수 있음

결론

  • Coroutine은 RxJava에 비해서 읽기 편한 코드를 제공한다.
  • Coroutine은 RxJava에 비해서 초기 러닝 커브가 낮아 이해하는 게 쉽다.
  • 많은 Jetpack 라이브러리에 코루틴을 완전히 지원하는 확장 프로그램이 포함되어 있다.

현재 Kotlin과 Coroutine의 사용 점유율이 크게 늘어났다. 이로 인해 기존 RxJava를 사용하는 이유 중 하나였던 자료와 활용사례가 많다는 점, 익숙한 라이브러리라는 장점들의 의미가 사라지고 Kotlin Coroutine의 중요도가 높아졌다. 앞으로는 Coroutine 대신 RxJava를 사용할 이유가 없다고 생각하며, 이 글에서 다루지 못했던 Coroutine의 좀 더 깊은 개념과 실전 활용 방법에 대해서 더 공부하고 싶어졌다. 이전 기술이었던 RxJava를 Coroutine으로 변경하기 위해, 또는 Coroutine을 좀 더 깊게 이해하거나 Coroutine, Thread와의 비교를 위해서 RxJava도 한 번 사용해보며 더 이해해야 할 필요성도 느꼈다.

참고
RxJava와 Kotlin Coroutines 비교해보기
[RxJava] RxJava 이해하기 - 2. Observable
코루틴(coroutine)에 대하여. 1편. 코루틴을 왜 쓸까?

profile
공부해서 남주자

1개의 댓글

comment-user-thumbnail
2023년 7월 17일

저도 개발자인데 같이 교류 많이 해봐요 ㅎㅎ! 서로 화이팅합시다!

답글 달기