RXAndroid

rxjk

모바일 앱을 개발하면서 여러가지 입력방식에 대응을 해야 하는 일들이 많아 졌다. 단순한 터치 부터 서버와의 통신, 파일 I/O, DB, 이미지 후처리 등 연산 작업들이나 blocking되어 처리 되어야 하거나 비동기적으로 행해져야 하는 프로세싱 작업들이 생겨 난 것 이다.

문제는 이 복잡한 처리들의 흐름 이다. 어떤 때에는 서버에 비동기로 rest 콜을 하고 난 뒤 받아온 resouce json정보를 파싱하여 특정한 이미지 썸네일에 대한 url을 통해서 이미지를 비동기로 불러오고, 그 다음 blur나 re-sampling, cached image(File) 을 asynctask등으로 처리 해 준다. 몰론 중간 중간 콜백 인터페이스를 구현한 구현체를 통해서 콜백을 보내고 그에 따른 main thread의 UI 갱신도 필 수 이다. 그동안 앱이 아무런 동작도 안하면 사용자는 앱이 죽을거라 생각 할 것이니까. (ANR을 주의하자)

대충 봐도 골치가 아프다. 위의 프로세스 흐름은 어렵지는 않다. 이미 유명한 모듈이나 기존에 자신이 만들어둔 모듈들을 활용하여 프로세싱 흐름을 제어 하면 되니 말이다. 문제는 나중이다. 이러한 흐름을 위한 구현들과 콜백 인터페이스에 따른 분기, 이벤트 버스, 큐, 그리고 복잡한 디자인 패턴 요소들로 복잡하게 얽혀있다. 만약 이슈가 발생하게 되면 이런 복잡한 프로세싱 흐름과 분기는 디버깅이나 파악을 위해서는 상당한 시간을 잡아 먹게 될 것이다. 그리고 아무리 재사용을 염두하고 만들어둔 모듈은 어느세 덕지 덕지 이상한 프로세스와 변수들이 붙여 나가 괴물의 형태를 띄우고 이슈를 발생할 가능성 높은 문제점 덩어리가 될 수 도 있다.

 

 Hello Reactive Extension

마이크로소프트는 Observer 디자인 패턴과 Iterator 디자인 패턴, LINQ 스타일 문법 을 확장한 비동기 처리와 이벤트를 기반으로 한 프로그래밍을 정립 하여 반응형 확장(RX, Reactive Extension)을 공개 한다. 아래를 보면 RX의 특징을 잘 설명한 문구가 있다.

The Observer pattern done right
ReactiveX is a combination of the best ideas from
the Observer pattern, the Iterator pattern, and functional programming

 

 Observer Design pattern

위키백과의 설명을 보면 다음과 같다.

옵서버 패턴(observer pattern)은 객체의 상태 변화를 관찰하는 관찰자들, 즉 옵저버들의 목록을 객체에 등록하여 상태 변화가 있을 때마다 메서드 등을 통해 객체가 직접 목록의 각 옵저버에게 통지하도록 하는 디자인 패턴이다. 주로 분산 이벤트 핸들링 시스템을 구현하는 데 사용된다. 발행/구독 모델로 알려져 있기도 하다.

  • Observer
    • 발생한 이벤트를 관찰하는 객체.
    • 관찰 대상의 콜백 객체를 통해서 notify()함수를 통해 메시지, 생성한 변수 등 데이터들을 전달 받아서 Subject에 전달 후 처리 한다.
  • Subject
    • 발생한 이벤트를 후 처리 하는 객체.

RXJava에서의 Obserable은 Observer와 유사 하지만 다른 부분이 있다. 어떤 Subject가 해당 이벤트에 대한 Observable을 구독(Subscribe)하지 않는 다면 이벤트를 발생 하지 않는 다는 점 이다. 어렵지만 나중에 직접 구현해 보고 사용해보면서 알 수 있지 않을까 싶다.

RXAndroid에서는 이러한 RXJava의 ‘Observable’과 ‘Subscribe’의 구현 패턴을 잘 기억하면 된다.

 

 Hello RXAndroid

반응성 확장의 개념은 여러 회사들로부터 좋은 반응들을 받았다. Netflix는 RX의 개념을 이용하여 Java환경에서 사용 가능하게 게 옳겼고, Soundcloud에서는 RXJava를 RXAndroid에서 사용 할 수 있게 확장 한다.

RXAndroid를 사용하기 위해선 안드로이드 app의 build.gradle파일에 아래와 같이 라이브러리 모듈 의존을 추가 한다.

라이브러리 모듈의 버전이 다를 수도 있음을 유의 하자. RXAndroid에서는 RXJava에 대한 의존성이 이미 존재 하기 때문에 ‘rxjava’에 대한 의존성을 빼도 상관 없다.

이제 간단한 RXAndroid를 이용한 RX 비동기 처리 샘플 코드를 만들어 보도록 하자.

이벤트의 새로운 흐름을 만드는 Observable과 생성된 Observable을 통해 처리된 데이터들을 소비 하는 Subscriber가 RX의 핵심적 요소 라고 할 수 있겠다. 

Observable은

  • onNext() : 처리된 데이터들을 다음으로 전달 한다.
  • onError() : 처리 중 오류가 발생했을때의 분기를 처리 한다.
  • onCompleted() : 흐름을 종료 한다.

와 같은 작업들을 할 수 있다. 몰론 항상 이 3개의 메소드 들을 구현 하는게 아니라 onNext()만 구현해서 사용 하거나 onNext(), onError()만을 구현해서 사용 할 수도 있다.

보통 RX에 대한 흐름(데이터 스트림)은 다음과 같이 도식 할 수 있다.

rxjava_p

위의 경우는 세번 데이터를 전달 받아 onNext()메소드를 통해서 데이터를 처리 하고 난 뒤에 onCompleted()에서 정상적으로 처리 한 경우이다.

하지만, 아래의 경우엔 데이터를 처음 onNext()메소드를 통해서 전달 받고 처리 중 오류가 발생하여 onError()메소드를 통해서 에러 처리 분기로 떨어진 경우 이다.

 

그리고

구현부분을 보면 익명클래스들과 필요없는 소스들로 인해서 가독성이 떨어지고 복잡해 보임을 아 ㄹ수 있다. JAVA8의 Lambda를 이용하여 소스를 정리 할 수도 있다. 아직 Android나 Android studio에서 JAVA8을 제대로 지원하지 않아(2016년 6월 기준, 추후 지원 예정) retrolambda를 이용하여 Lambda를 사용 하여 소스의 가독성을 올릴 수도 있다.

 

Observable의 생성을 보면 일반적인 create()를 생성하여 1회용으로 사용 하는것 이외에도 시간에 따른 주기적인 Observable의 생성을 해주는 interval()메소드나, 특정 시간이 지나고 난 뒤 Observable을 생성 해주는 timer()등이 더 있다. 그 외에도, offset과 반복 횟수를 지정 하고 이벤트를 일정 시점까지 반복시켜주는 range()도 있다.

또한 생성한 여러개의 Observable을 합성하여 처리 시켜주거나(zip),  분할 해주는 방법도 있다.  몰론 이 외에도 api문서를 찾아보면 특정 상황에 걸맞는 메소드들을 제공 하기 때문에 상황에 걸맞는 RX를 구현 할 수 있다.

 

RX의 진입장벽은 확실히 높다. 예제소스를 보는것 만으로는 이해하기가 상당히 힘들다. 단순히 ‘생성’하고 ‘소모’하는 1회성 소스가 무슨 소용이 있나 하는 생각이 든다. 여기에 MVP패턴을 이용한 data, presenter, view의 개별 처리나 retrofit을 이용한 비동기 네트워크 콜, Realm을 사용 하게 되면 상당히 더 복잡해져 간다.

RX의 사용에 따른 장점은 아직 나도 크게 겪진 못했다. 낯선 개발 환경에 오히려 더 많은 시간을 투자해야 함을 느낀것도 사실 이다. 하지만, 조금 더 많이 다뤄보면서 그 장점에 대해서 좀더 생각을 해보고 싶다는 생각이 들었다. RX를 하다 보면 개발이 즐겁다는 생각이 들더라. :)

 

You may also like

댓글 남기기

이메일은 공개되지 않습니다. 필수 입력창은 * 로 표시되어 있습니다.