250x250
반응형
05-11 14:06
Today
Total
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
Notice
Recent Posts
Recent Comments
Link
Archives
관리 메뉴

Bill Kim's Life...

[RxSwift] Hello~ RxSwift! : 기본 특징 및 개발 환경 설정하기 본문

CS(컴퓨터 과학)/RxSwift

[RxSwift] Hello~ RxSwift! : 기본 특징 및 개발 환경 설정하기

billnjoyce 2020. 9. 16. 12:28
728x90
반응형
RxSwift의 기본 특징 및 개발 환경 설정에 대해서 살펴봅니다.

 

 

#. 개발 환경

  • Xcode 11.x 이상
  • Swift 5.x 이상
  • RxSwift 5.x 이상

 

 


 

 

Rx + Swift

 

Rx는 ReactiveX 이고, ReactiveX Reactive eXtensions 의 줄임말 입니다.

번역하면 반응형 확장자로서 한마디로 표현하면 반응형 비동기 이벤트 기반의 프로그래밍 라이브러리입니다.

 

여기서 비동기 이벤트 기반 프로그래밍이란 아래와 같은 특징을 가진 형태를 말합니다.

 

 

 

 


 

 

Observer 패턴 + Iterator 패턴      +      Functional 프로그래밍

 Reactive(비동기 이벤트 방식)                X(이벤트 처리 방식)   

 

 


 

 

 

 

반응형 프로그래밍의 사전적 정의를 한번 살펴보면 아래와 같습니다.

 

반응형 프로그래밍이란 데이터의 흐름 과 변화의 전파에 중점을 둔 선언적 프로그래밍 패러다임. 정적 또는 동적인 데이터 흐름 을 쉽게 표현할 수 있으며, 데이터 흐름을 통해 연관된 실행 모델이 자동으로 변화를 전파할 수 있는 것을 의미함. -by Elonwiki

 

reactivex.io

 

ReactiveX

CROSS-PLATFORM Available for idiomatic Java, Scala, C#, C++, Clojure, JavaScript, Python, Groovy, JRuby, and others

reactivex.io

 

 


 

 

 

 

이러한 ReactiveX를 Swift 언어를 통하여 제공되는 라이브러리가 바로 RxSwift 입니다.

 

앞으로의 RwSwfit 강좌는 아래의 RxSwfit 공식 Github의 내용을 기반으로 하여 하나 하나씩 살펴보도록 하겠습니다.

 

github.com/ReactiveX/RxSwift

 

ReactiveX/RxSwift

Reactive Programming in Swift. Contribute to ReactiveX/RxSwift development by creating an account on GitHub.

github.com

 

오늘은 RxSwift의 첫 강좌로서 기본적인 사용 목적과 개념 그리고 개발 환경 설정 방법등에 대해서만 살펴보도록 하겠습니다.

 

 

 

 


 

 

 

Why use rx?

 

Rx 및 RxSwift를 사용하면 아래와 같은 이점을 가질 수 있습니다.

 

  • 비동기 및 이벤트 처리를 통한 손쉽게 데이터와 UI(View)와의 바인딩 가능
  • 불필요한 콜백 및 델리게이트 이벤트가 불필요함에 따라 코드가 간결해짐
  • 일관적이고 깔끔한 스레드(비동기) 코드 적용 가능
  • 함수 및 객체의 재사용성 증대
  • 무방향의 데이터 흐름을 통한 유연한 상태 관리
  • 에러 처리 및 재시도(Retry) 코드를 쉽게 적용 가능
  • 다수의 연산자(Operators) 지원으로 인한 다양한 구현 가능

위와 같은 이점을 제공하기 위하여 Rx에서는 기본적으로 Observer 패턴을 사용한 형태로 라이브러리가 구성되어 있습니다.

그렇다면 코드를 통하여 간략한 RxSwift의 특징을 좀 더 구체적으로 살펴보겠습니다.

 

 

 


 

 

 

Bindings

 

기본에는 특정 데이터에 대한 UI 바인딩을 위해서는 Delegate, Callback, KVO, Notification, 자체 데이터 동기화 코드 등을 통하여 사용하였습니다. 하지만  RxSwift를 사용하면 아래와 같이 모든 비동기 데이터 바인딩 처리를 한 곳에서 처리할 수 있게 도와줍니다.

 

본 강의에서는 개념 정도만 파악하시고 아래의 구체적인 코드에 대한 상세한 사항은 추후의 강의에서 다루도록 하오니 그냥 이런 스타일로 비동기 처리와 바인딩을 하는구나 하고 생각하시면 되겠습니다.(한번에 너무 깊이 들어가면 머리가 아프실테니.. ^^)

Observable.combineLatest(firstName.rx.text, lastName.rx.text) { $0 + " " + $1 }
    .map { "Greetings, \($0)" }
    .bind(to: greetingLabel.rx.text)
    
    
// Using also UITableViews and UICollectionView
viewModel
    .rows
    .bind(to: resultsTableView.rx.items(cellIdentifier: "WikipediaSearchCell", cellType: WikipediaSearchCell.self)) { (_, viewModel, cell) in
        cell.title = viewModel.title
        cell.url = viewModel.url
    }
    .disposed(by: disposeBag)    
    
    
    
 self.resultsTableView
    .rx.contentOffset
    .map { $0.x }
    .bind(to: self.leftPositionConstraint.rx.constant)
    
    
    
 view.rx.observe(CGRect.self, "frame")
    .subscribe(onNext: { frame in
        print("Got new frame \(frame)")
    })
    .disposed(by: disposeBag)
    
    
    
 someSuspiciousViewController
    .rx.observeWeakly(Bool.self, "behavingOk")
    .subscribe(onNext: { behavingOk in
        print("Cats can purr? \(behavingOk)")
    })
    .disposed(by: disposeBag)  
    
    
    
NotificationCenter.default
    .rx.notification(NSNotification.Name.UITextViewTextDidBeginEditing, object: myTextView)
    .map {  /*do something with data*/ }
    ....    

 

 

 


 

 

 

 

Retries

 

기존의 Swift 코드에서는 특정 함수에서 실패에 대한 재시도 처리를 위해서는 일일이 상태 체크와 다양한 예외 처리 코드를 적용해야 했습니다.

 

하지만 RxSwift에서는 아래와 같이 간단하게 재시도에 대한 규칙을 적용할 수 있습니다.

doSomethingIncredible("me").retry(3)

 

retry라는 연산자(Operator)를 통하여 간단히 적용한 것을 볼 수 있습니다.

참고로 Rx에서는 함수에 대해서 연산자(Operator)라는 용어를 사용하고 있습니다.

 

 

 

 


 

 

 

 

Transient state

 

기존의 Swift에서는 데이터 상태에 대해서 항상 신경을 써야하며 연결된 UI 객체와의 비동기 바인딩 처리를 항상 고민해야 했었습니다.

 

예를 들어 검색 기능을 구현하기 위하여 특정 Textfield에서 텍스트 입력 완료 시에 해당 텍스트 값을 가져와서 검색을 하는 코드를 위해서는 다양한 Delegate 메소드를 통하여 처리를 해야했습니다.

 

하지만 RxSwift에서는 아래와 같이 간편하게 한 곳에서 데이터 상태에 따른 모든 비동기 처리와 바인딩 처리를 할 수 있습니다.

searchTextField.rx.text
    .throttle(.milliseconds(300), scheduler: MainScheduler.instance)
    .distinctUntilChanged()
    .flatMapLatest { query in
        API.getSearchResults(query)
            .retry(3)
            .startWith([]) // clears results on new search term
            .catchErrorJustReturn([])
    }
    .subscribe(onNext: { results in
      // bind to ui
    })
    .disposed(by: disposeBag)

 

 

 


 

 

 

 

Compositional disposal

 

특정 테이블뷰에서 URL로부터 이미지를 가져온 후 디코딩을 한 후 흐리게(Blur) 처리가 된 이미지를 표시하는 기능이 있다고 가정해봅니다.

해당 기능을 효과적으로 구현하기 위해서는 현재 보이는 셀(가시 영역)에 대해서만 블러링을 처리를 할 필요가 있으며 스와이프를 통한 요청 실행 및 취소가 될 수 있기에 가시 영역에 들어온 다음에 이미지 가져오기를 하는게 좋을 것 입니다. 또한 블러링 처리는 비용이 많이 드는 작업임으로 동시에 처리되는 이미지 수를 제한할 필요도 있을 것입니다.

 

이와 같은 다양한 복합 조건에 대한 비동기 처리를 RxSwift에서는 아래와 같이 간략하게 수행할 수 있습니다.

// this is a conceptual solution
let imageSubscription = imageURLs
    .throttle(.milliseconds(200), scheduler: MainScheduler.instance)
    .flatMapLatest { imageURL in
        API.fetchImage(imageURL)
    }
    .observeOn(operationScheduler)
    .map { imageData in
        return decodeAndBlurImage(imageData)
    }
    .observeOn(MainScheduler.instance)
    .subscribe(onNext: { blurredImage in
        imageView.image = blurredImage
    })
    .disposed(by: reuseDisposeBag)

 

 

 


 

 

 

 

Aggregating network 

RxSwift에서는 두개 이상의 네트워크 요청에 대해서 아래와 동시에 처리를 할 수 있습니다.

let userRequest: Observable<User> = API.getUser("me")
let friendsRequest: Observable<[Friend]> = API.getFriends("me")

Observable.zip(userRequest, friendsRequest) { user, friends in
    return (user, friends)
}
.observeOn(MainScheduler.instance)
.subscribe(onNext: { user, friends in
    // bind them to the user interface
})
.disposed(by: disposeBag)

 

 

 


 

 

 

 

Easy integration

기존의 Cocoa 코드 및 Regacy 코드에도 나만의 Observable 객체로서의 통합을 손쉽게 적용할 수 있습니다.

아래는 Rxcocoa에서 HTTP 요청을 위한 URLSession에 대한 Observable 적용 예제 코드입니다.

 

기존의 HTTP 통신 함수를 Observable 객체로의 생성을 통하여 onNext, onCompleted, onError 등에 처리를 구현한 코드입니다.

여기서 나오는 onNext, onCompleted, onError 등의 내용은 다음에 진행할 Obverable 관련 강의에서 자세히 설명하도록 할 예정이니 현재는 그냥 참고만 하시길 바랍니다.

extension Reactive where Base: URLSession {
    public func response(request: URLRequest) -> Observable<(Data, HTTPURLResponse)> {
        return Observable.create { observer in
            let task = self.base.dataTask(with: request) { (data, response, error) in
            
                guard let response = response, let data = data else {
                    observer.on(.error(error ?? RxCocoaURLError.unknown))
                    return
                }

                guard let httpResponse = response as? HTTPURLResponse else {
                    observer.on(.error(RxCocoaURLError.nonHTTPResponse(response: response)))
                    return
                }

                observer.on(.next(data, httpResponse))
                observer.on(.completed)
            }

            task.resume()

            return Disposables.create(with: task.cancel)
        }
    }
}

 

 

 


 

 

 

 

Installation(CocoaPods)

이상으로 RwSwift 에 대한 기본 특징에 대해서 간단히 살펴보았습니다.

그렇다면 이제 실제 사용을 위해서 개발 환경을 설정해야할텐데요. 어떻게 RxSwift 개발을 위한 설정을 할 수 있을까요?

 

RwSwfit 공식 Github에서는 다양한 방식의 설치 방법을 안내하고 있는데요. 여기서는 가장 많이 사용하는 방식인 CocoaPods를 사용한 방법을 소개해 보도록 하겠습니다.

# Podfile
use_frameworks!

target 'YOUR_TARGET_NAME' do
    pod 'RxSwift', '~> 5'
    pod 'RxCocoa', '~> 5'
end

# RxTest and RxBlocking make the most sense in the context of unit/integration tests
target 'YOUR_TESTING_TARGET' do
    pod 'RxBlocking', '~> 5'
    pod 'RxTest', '~> 5'
end

 

CocoaPods의 기본 설정 파일은 Podfile에서 다음과 기본적으로 RxSwit 및 RxCocoa를 입력합니다. 

원하는 버전이 있을 경우는 해당 버전을 직접 명시하여 사용하여도 좋습니다.

 

또한 유닛 테스트 및 통합 테스트 등을 위해서는 RxTest, RxBlocking 또한 설정하여 설치할 수 있습니다.

 

해당 파일을 수정한 후에 바로 'pod install' 명령어를 실행하여 설치한 후 xcworkplace 파일을 실행하여 프로젝트를 열어보면 RxSwift 관련 코드가 적용된 것을 보실 수 있습니다.

 

그럼 이제부터는 즐거운 RxSwift 개발을 위한 준비를 모두 마쳤습니다.

 

 

 


 

 

 

이상으로 RxSwift의 기본 특징 및 개발 환경 설정에 대해서 살펴보았습니다.

 

본 강의에서는 간략한 RxSwift에 대한 기본 특징에 대해서만 개념적으로 살펴보았습니다.

추후 강의부터는 자세한 RxSwift의 개발에 대한 사항을 예제 코드와 함께 살펴보도록 하겠습니다.

 

 

 

감사합니다.

 

 

 

 


[참고 자료(References)]

 

[1] RxSwift: ReactiveX for Swift : github.com/ReactiveX/RxSwift

[2] [RxJava2] 1. ReactiveX 란? : k-elon.tistory.com/1

[3] [iOS Swift] RxSwift 왜 사용하면 좋을까요? : medium.com/@jang.wangsu/ios-swift-rxswift-왜-사용하면-좋을까요-5c9995f47bab
[4] [RxSwift] RxSwift란? ReactiveX 란? : medium.com/@jang.wangsu/rxswift-rxswift란-reactivex-란-b21f75e34c10

[5] RxSwift 장점 (2/2) : app-developer.tistory.com/5

[6] ReactiveX : http://reactivex.io/

 

 

728x90
반응형
Comments