출처 : http://kunny.github.io/community/2016/02/08/gdg_korea_android_weekly_02_1/

MissingBackpressureException

MissingBackpressureException은 Observable에서 항목(item)을 보내는(emit) 속도보다 처리하는 속도가 느릴 때 발생합니다.

RxJava 가이드 문서 내 Backpressure 항목에도 이와 관련된 항목이 기술되어 있는데, 문서에서 예로 든 사례(zip 연산자를 사용하는 경우)를 사용하지 않는 경우에도 상당히 높은 확률로 경험할 수 있습니다.

RxAndroid를 사용하는 경우, 수신된 데이터를 UI에 표시하기 위해 observeOn(AndroidSchedulers.mainThread()) 를 많이 사용합니다. 그런데, 이 과정에서 UI 쓰레드 내에서 다른 작업이 수행되고 있어 Observable에서 보낸 항목을 바로 처리하지 못할 경우 MissingBackpressureException이 발생합니다. 따라서, 항상 발생하지 않고 사용자 환경에 따라 발생 여부가 달라질 수 있는 부분이라 개발 도중에는 발견하지 못할 가능성도 매우 높습니다.

위 오류를 방지하려면 Backpressure가 필요할 때 처리할 방법을 다음과 같이 지정해 주면 됩니다.

  • onBackpressureBuffer(): Observable에서 보낸 항목을 큐에 계속 쌓아두어, 항목을 처리하는 쪽에서 해당 항목을 나중에 처리할 수 있도록 합니다. 항목이 무한정 쌓이는 것을 방지하기 위해 onBackpressureBuffer(int)를 사용하여 큐에 쌓아둘 수 있는 항목 수를 제한할 수도 있습니다.
  • onBackpressureDrop(): Observable에서 항목을 보냈을 때 바로 처리되지 못한 데이터는 무시합니다. 서버나 데이터베이서에서 받은 데이터를 처리할 때 이 방법을 사용하면 실제로 받은 데이터와 UI에 표시되는 데이터 간 차이가 발생할 수 있으니 신중하게 사용해야 합니다.

subscribeOn / observeOn

작업이 수행될 쓰레드를 지정하기 위해 subscribeOn()과 observeOn() 메서드를 사용하는데, 역할은 비슷하지만 각각 적용되는 효과가 조금 다릅니다.

  • subscribeOn: 작업을 시작하는 쓰레드를 지정합니다. 체인의 어느 곳에 사용해도 가장 마지막에서 지정해 준 것만 적용됩니다.
  • observeOn: 바로 다음 번에 실행되는 연산이 실행되는 쓰레드를 지정합니다. 이를 사용하여 하나의 체인 내에서 실행되는 여러 연산들이 수행될 쓰레드를 각각 지정할 수 있습니다. 안드로이드에서 사용할 경우, 일반적으로 subscribe() 직전에 observeOn(AndroidSchedulers.mainThread())를 사용하여 onNext() 메서드가 UI 쓰레드에서 실행되도록 구성합니다.

공식 문서 내 Scheduler 항목에 포함되어 있는 아래 그림을 보시면 좀 더 이해가 쉽습니다.

Schedulers

flatMap / concatMap

두 연산자는 Observable 에서 받은 항목을 다른 형태로 변형해 준다는 점은 동일하지만, 세부 동작이 하나 다릅니다. 빠른 이해를 위해 공식 문서 내 포함되어 있는 각 연산자별 설명 이미지를 보겠습니다.

[flatMap]flatMap

flatMap은 아밴트 스트림에서 발생한 항목들을 처리할 때 merge 연산자를 사용합니다. 따라서 이벤트 스트림에서 항목이 인입됨과 동시에 결과를 출력합니다.

이러한 특성 때문에, 인입되는 항목 순서와 출력되는 순서가 달라질 수 있습니다. 위의 예 에서도 초록색과 파란색 항목의 순서가 섞여 출력되는 것을 확인할 수 있습니다.

[concatMap]concatMap

concatMap은 이벤트 스트림에서 발생한 항목들을 처리할 때 concat 연산자를 사용합니다. 때문에 flatMap과는 달리 이벤트 스트림을 통해 전달된 항목 하나에 대한 처리가 완료된 후에 다음 항목을 처리합니다. 초록색 항목과 파란색 항목의 순서도 뒤바뀌지 않고 그대로 출력되는 것을 확인할 수 있습니다.

flatMap은 저도 상당히 많이 쓰는 연산자 중 하나인데, 위와 같은 차이점이 있었는지 이제야 알게 되었습니다. 순서가 섞이면 안 되는 연산에는 필히 concatMap을 사용해야겠습니다.

위와 관련하여 잘 정리된 블로그 포스트가 있으니, 추가 정보가 필요하신 분은 참고하세요.

RxJava Observable transformation: concatMap() vs flatMap() Link

RxMarbles

RxMarbles

RxMarbles 에선 Rx에서 사용하는 연산자가 어떤 방식으로 처리되는지 인터랙티브 형태로 확인할 수 있습니다.

이벤트 스트림에서 발생한 각각의 이벤트들을 직접 조작할 수 있어, 그림만으로는 이해가기 어려웠던 연산자들의 동작 방식을 좀 더 잘 이해할 수 있습니다. 이해가 잘 가지 않는 연산자가 있었다면, 이 기회에 확실하게 이해해 보는 것은 어떨까요?

Frodo

Frodo

Frodo는 RxJava의 디버깅을 도와주는 도구입니다. onSubscribe()onNext()onError()onCompleted() 등 각 절차가 어떤 순서로 발생하는지, onNext()에서 발생한 데이터가 어떻게 되는지 쉽게 확인할 수 있습니다.

RxJava를 처음 배울 때 이 도구를 알았더라면 삽질하는 시간을 좀 더 줄일 수 있었을텐데, 참 아쉽습니다. 처음 접하는 사용자부터 어느 정도 익숙해진 사용자까지, RxJava를 사용하는 개발자에게 강력 추천해 주고 싶은 도구입니다.

Rx와 관련된 더 많은 읽을거리

Going Reactive, And Android Architectural Journey

RxAndroid의 창시자 Matthias Käppler의 발표 영상으로, Rx를 사용하여 안드로이드 애플리케이션을 개발한 경험에 대해 소개하고 있습니다.

Realm Korea 블로그에 발표 내용을 한글로 번역한 포스트가 올라와 있으니 함께 보시면 더 도움이 될 것입니다.

Android Application Architecture (번역)

RxJava를 사용하여 MVP 기반 구조를 설계하는 과정을 소개한 원문 포스트를 번역한 글입니다. RxJava를 실제로 사용하는 방법과, 이를 효율적으로 사용하기 위한 설계 팁을 함께 얻을 수 있겠네요.

기본적인 액티비티와 AsyncTask 에서 시작하여 RxJava 로 만든 MVP 기반 구조까지의 여정. Link

Android Studio

Android Studio 2.0 Beta 2가 공개되었습니다. Beta 1이 공개된 직후 큰 버그가 있어, 얼마 지나지 않아 바로 Beta 2가 나오는 우여곡절을 겪기도 했습니다.

Android Studio 2.0 Beta Available in Canary Channel - Android Tools Project Site Link

주요 변경 사항은 다음과 같습니다.

  • 성능 개선
  • Incremental Java complication과 Annotation processor를 사용하는 라이브러리 간 충돌 방지
  • Instant Run 관련 오류 수정
  • 개선된 에뮬레이터
  • 더 빨라진 ADB: 애플리케이션 설치 및 파일 전송 속도 최대 5배 향상

자세한 내용은 블로그 포스트를 참조하세요.



'Android > RXAndroid' 카테고리의 다른 글

Rx 예제모음  (0) 2017.02.21
Rx에서의 멀티캐스팅 방법  (0) 2017.02.09
Flowable 를 언제 사용하면 될까?  (0) 2017.02.03
RxJava 예제  (0) 2017.01.31
RxView 예제 모음  (0) 2017.01.07

+ Recent posts