[RxSwift] 9-1. RxCocoa Traits : Driver ; 리소스 낭비 예방

miori·2022년 2월 22일
0

RxSwiftBasic

목록 보기
20/29

RxSwift를 21일간 공부하는 루틴
"Rx를 기깔나게 쓰는 신입개발자 도전" 시작 🚀


이번에 RxCocoa의 Traits중 하나인 Driver에 대해 정리해보겠다.
Driver 는 무엇이며, 왜 써야하는지에 대해서 중점적으로 정리해보겠다.

왜 굳이 Rx? : 두번째 이야기이야기 에서 구현했던 것을 변형하려고 한다.

구현 목표

  1. textfield를 통해 사용자의 이메일 주소를 입력받는다.
  2. 입력한 이메일에 @ 가 포함이 되면, 옳은 이메일 형식임을 알려준다.

기존 2가지에서 1가지 옵션을 더 추가하려고 한다.

  1. 옳은 이메일 형식일때는, label 의 text색을 green으로 아닐때는, red로 변경한다.

이를 구현하기 위해 Observable이 전달하는 bool 값을 label의 textcolor에 binding을 추가해야한다.

1차 구현 코드

        //MARK:  rx
        let result = myTF.rx.text 
            .map { self.checkEmail(email: $0)}
        
        result
            .map { $0 ? "옳은 이메일 형식입니다 😀" : "이메일 형식이 아닙니다 ☹️"}
            .bind(to: myLabel.rx.text)
            .disposed(by: disposeBag)
        
        result
            .map { $0 ? UIColor.systemGreen : UIColor.systemRed}
            .bind(to: myLabel.rx.textColor)
            .disposed(by: disposeBag)
    }

위와 같이 구현하였다.
result는 bool 값을 전달하는 Observable이다.
왜나하면, checkEmail의 return값이 bool 이기 때문이다.

그리고 result를 각각 myLabel.rx.textmyLabel.rx.textColor 에 binding을 해주었다.

결과영상

output

문제점

결과적으로 봤을때, 유저의 입장에서 본다면 기능은 잘 작동한다.
하지만, 시스템 측면에서 본다면 문제점이 있다.
문제점은 바로 불필요한 리소스가 낭비되고 있는 점이다.

checkemail 함수에 print문을 추가하여보았더니 다음과 같이 출력이 되었다.

결과물

두개의 시퀀스가 다시 시작 되는 것을 확인 할 수 있다.
binding 된것이 두개라서, 즉 Observer가 둘이기 때문이다.
Observer 가 늘어날 때마다, 시퀀스도 늘어난다면... 이는 리소스를 너무 많이 낭비하게 될것이다.

해결 1 : share

물론 share()연산자를 통해 모든 구독자가 하나의 시퀀스를 공유하게 할 수 있다.
만약 api통신에서 데이터를 가져오는 과정에서 Result로 데이터와, 에러값을 갖고온다 가정을 했을때, 이를 share로 하면 리소스가 낭비되지 않을 것이다.

하지만 현재는 UI 부분이고, 이보다 더 간편하게 사용할 수 있는 traits가 있다.

해결 2 : Driver

  • Driver는 데이터를 UI에 바인딩할때 직관적이고 효율적으로 사용할 수 있다.
  • Driver는 구독자에게 next, completed 이벤트만 전달한다.
  • Driver는 모든 작업을 mainthread에서 진행되는 것을 보장한다.
  • Driver는 모든 구독자가 시퀀스를 공유한다.

2차 구현 코드 : Driver

        // 드라이버는 시퀀스를 공유 share 필요없음
        let result = myTF.rx.text.asDriver()
            .map { self.checkEmail(email: $0)}
            .asDriver(onErrorJustReturn: false)
        
        result
            .map { $0 ? "옳은 이메일 형식입니다 😀" : "이메일 형식이 아닙니다 ☹️"}
            .drive(myLabel.rx.text)
            .disposed(by: disposeBag)
        
        result
            .map { $0 ? UIColor.systemGreen : UIColor.systemRed}
            .drive(myLabel.rx.textColor)
            .disposed(by: disposeBag)

이 코드처럼 driver 를 활용해 코드를 수정할 수 있다.
correct

그러면 리소스가 낭비되던 문제점을 해결할 수 있다.
또다른 driver의 장점은 .asDriver(onErrorJustReturn: false)처럼 에러처리가 단순하다.
ui에서 에러가 발생한다면, 시퀀스가 종료되어 더이상의 ui 업데이트가 되지 않기 때문에 에러처리는 중요하다고 생각한다.
driver는 에러처리가 단순하기 때문에 UI를 처리할때 유용하다고 생각한다.

정리

정리해본다면,
UI의 업데이트는 mainThread에서 보장이 되어야한다.
Driver는 mainThread에서 작업을 보장해주기 때문에 데이터를 UI에 바인딩할때 유용하다.
그리고 bind와 달리, 시퀀스를 공유하기 때문에 리소스 낭비를 예방할 수 있다.


전체코드는 깃허브 에서 확인 가능하다.

profile
iS를 공부하는 miori 입니다.

0개의 댓글

관련 채용 정보