ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Chapter 1: Hello, RxSwift!
    Raywenderlich/RxSwift: Reactive Programming 2020. 8. 31. 16:35

    이 책은 RxSwift 라이브러리(library)를 소개(introduce)하고 RxSwift로 반응형(reactive) iOS 앱(apps)을 작성하는 것을 목표로 한다.

    RxSwift의 정의(definition)는 다음과 같다:

    RxSwift는 관찰 가능한(observable) 시퀀스(sequences)와 함수 형식(functional style)의 연산자(operators)를 사용하여 비동기(asynchronous) 및 이벤트(event) 기반 코드를 작성하기 위한 라이브러리(library)로, 스케줄러(schedulers)를 사용한 매개 변수화(parameterized)된 실행(execution)을 허용한다.

     

    복잡하게(complicated) 들리더라도 걱정할 필요는 없다. 반응형(reactive) 프로그램(programs)을 작성하고, 그 이면(behind)의 많은 개념(concepts)을 이해하며, 일반적으로(commonly) 사용하는 많은 관련(relevant) 용어를 탐색(navigating)하는 것은 위협적(intimidating)으로 생각될 수 있다. 특히(especially) 한 번에 모든 것을 이해하려 하거나, 구조적인 방식으로 시작하지 않은 경우에는 더욱 그렇다.

    다양한 RxSwift API와 일반 Rx 개념(concepts)을 점진적으로(gradually) 소개(introduce)하면서 각 API를 사용하는 방법을 설명하여(explaining), 반응형(reactive) 프로그래밍(programming)이 iOS 앱에서 RxSwift의 실제(practical) 사용(usage)을 다루는 방법에 대해 직관(intuition)을 구축(build)하는 것에 도움이 되도록 하는 것이 이 책의 목표이다.

    RxSwift의 기본(basic) 기능(features)으로 시작하여, 점차(gradually) 중급(intermediate) 및 고급(advanced) 주제(topics)까지 작업하게 된다. 진행하면서 새로운 개념(concepts)을 광범위하게(extensively) 연습(exercise)하는데 시간을 할애한다면, 책이 끝날 때 RxSwift를 더 쉽게 숙달(master)할 수 있을 것이다. Rx는 하나의 책으로 완전히(completely) 다루기에는 너무 광범위(broad)한 주제(topic)이다. 대신 Rx 기술(skills)을 스스로 계속해서 개발할 수 있도록, 라이브러리(library)에 대한 확실한(solid) 이해(understanding)를 제공하는 것을 목표(aim)로 한다.

    우리는 아직 RxSwift가 무엇인지 정확히 알지 못한다. 간단(simple)하고 이해하기 쉬운(understandable) 정의(definition)로 시작하여, 이 장(chapter)의 뒷부분에서는 반응형(reactive) 프로그래밍(programming) 주제(topic)를 살펴보면서 더 나은 표현(expressive)이 되도록 진행한다.

    본질적(essence)으로 RxSwift는 코드가 새로운 데이터에 반응(react)하고 이를 순차적(sequential)이고 격리된(isolated) 방식(manner)으로 처리(process)할 수 ​​있도록하여, 비동기(asynchronous) 프로그램 개발(developing)을 단순화(simplifies)한다.

    iOS 앱(app) 개발자(developer)로서, 이 정의가 이 장(chapter) 앞부분의 첫 번째 정의(definition)보다 RxSwift가 무엇인지 훨씬 더 명확(clear)하게 이해되어야 한다.

    아직 세부 사항(details)이 모호(fuzzy)하더라도, RxSwift가 비동기(asynchronous) 코드 작성에 도움이 된다는 것은 분명히(clear) 알 수 있을 것이다. 그리고 좋은 결정론적(deterministic) 비동기(asynchronous) 코드를 개발하는 것이 어렵다는 것도 알고 있을 것이므로, 어떤 작은 도움이라도 반가울(welcome) 것이다.

     

    Introduction to asynchronous programming

    비동기(asynchronous) 프로그래밍(programming)을 간단한(simple) 일상적 언어(earth language)로 설명하려면 다음과 같은 것을 생각해 볼 수 있을 것이다.

    iOS 앱(app)은 언제든지(any moment) 다음과 같은 작업을 수행할 수 있다:

    • 버튼 탭에 반응(Reacting to button taps)
    • 텍스트 필드의 반응이 해제되었을 때 키보드 애니메이션(Animating the keyboard as a text field loses focus)
    • 인터넷에서 대용량 사진 다운로드(Downloading a large photo from the Internet)
    • 데이터를 디스크에 저장(Saving bits of data to disk)
    • 오디오 재생(Playing audio)

    이 모든 일은 동시에 일어나는 것처럼 보인다. 키보드가 화면 밖으로 애니메이션(animates)될 때마다, 애니메이션(animation)이 완료(finished)될 때까지 앱(app)의 오디오(audio)가 일시 중지(pause)되진 않는다.

     

    프로그램(program)의 모든 다른 부분들(bits)이 서로의 실행(execution)을 차단(block)하지 않는다. iOS는 다양한 스레드(threads), 실행(execution) 컨텍스트(contexts)에서 서로 다른 작업을 기기 CPU의 여러 코어(cores)에서 수행(perform)할 수 있는 다양한(various) 종류의 API를 제공(offers)한다.

    그러나 실제 병렬(parallel)로 실행(runs)되는 코드를 작성하는 것은 다소 복잡하다. 특히 서로 다른 코드(bits of code)가 동일한 데이터(pieces of data)로 작업해야 하는 경우는 더욱 그렇다. 어떤 코드가 먼저(first) 데이터를 업데이트(updates)하는지, 어떤 코드가 최신 값(the latest value)을 읽는(read)지 확실히 알기가 어렵다.

     

    Cocoa and UIKit asynchronous APIs

    Apple은 비동기(asynchronous) 코드 작성에 도움이 되는 수 많은 API를 항상 iOS SDK에 제공(provided)했다. 실제로 플랫폼(platform)에서 비동기(asynchronous) 코드를 작성하는 방법에 대한 모범 사례(best practices)는 몇 년동안 여러 번 발전(evolved)해 왔다.

    몇 가지만 언급(mention)해 보면 다음과 같다:

    • NotificationCenter: 사용자가 기기의 방향(orientation)을 변경(changing)하거나, 화면(screen)에 소프트웨어 키보드를 표시(showing)하거나 숨기는(hiding) 것과 같은 관심(interest) 이벤트가 발생(happens)할 때마다 코드를 실행(execute)한다.
    • The delegate pattern: 다른 객체(object)를 대신하거나 다른 객체와 함께 작동(coordination)하는 객체를 정의(define)할 수 있다.
    • Grand Central Dispatch: 작업 실행(execution)을 추상화(abstract)하는 데 도움을 준다. 코드 블록(blocks)이 순차적(sequentially), 동시(concurrently), 지정된 지연(delay) 후에 실행되도록 예약(schedule)할 수 있다.
    • Closures: 코드에서 전달(pass)할 수 있는 분리된(detached) 코드 조각(pieces of code)을 만든다.

    그리고 마지막으로

    • Combine: Swift로 반응형(reactive) 비동기(asynchronous) 코드를 작성하기 위한 Apple의 자체 프레임 워크(framework)로 iOS 13부터 사용 가능(available)하다.

    어떤 API를 선택했느냐에 따라, 앱을 일관성(coherent)있는 상태(state)로 유지(maintain)하기 위한 난이도가 크게(largely) 달라진다.

    예를 들어 delegate pattern 또는 notification center와 같은 오래된(older) Apple API를 사용하는 경우, 앱(app)의 상태(state)를 일관되게(consistent) 유지하기 위해 많은 노력을 기울여야 한다.

    Apple의 Combine을 사용하는 빛나는 새로운 코드(codebase)가 있다면, 이미 반응형(reactive) 프로그래밍(programming)을 사용하고 있는 것이다.

    이 섹션(section)을 마무리(wrap up)하고, 좀 더 자세한 내용을 설명(discussion)하기 위해 동기(synchronous) 코드와 비동기(asynchronous) 코드를 비교해 본다.

     

    Synchronous code

    배열(array)의 각 요소(element)에 대해 작업(operation)을 수행(performing)하는 것을 이미 여러 번(plenty) 반복해 보았을 것이다. 이는 동기(synchronously)로 실행(executes)되고, 컬렉션(collection)을 반복(iterate)하는 동안 해당 컬렉션(collection)을 변경할 수 없다(immutable)는 두 가지를 보장(guarantees)하기 때문에 매우 간단(simple)하면서도 견고한(solid) 앱 로직(logic) 구성 요소(building block)이다.

    이것이 무엇을 의미(implies)하는지 잠시 생각해 본다. 컬렉션(collection)을 반복(iterate)할 때, 모든 요소(elements)가 여전히 존재하는지 확인(check)할 필요가 없으며, 다른 스레드(thread)가 컬렉션(collection) 시작 부분에 요소(element)를 삽입(inserts)하는 경우 되감을(rewind back) 필요가 없다. 반복(loop)의 시작 부분에서 항상 컬렉션(collection) 전체(entirety)를 반복(iterate)한다고 가정(assume)한다.

    for 반복문(loop)의 이러한 측면(aspects)을 좀 더 확인해 보고 싶다면, playground에서 다음을 시도(try)해 본다:

    var array = [1, 2, 3]
    
    for number in array {
        print(number) // 1 2 3 출력 //4 5 6 이 나오지 않는다
        array = [4, 5, 6]
    }
    
    print(array) // [4, 5, 6]

    결과는 다음과 같다:

    1
    2
    3
    [4, 5, 6]

    for 본문(body) 내부(inside)에서 배열(array)을 변경(mutable)할 수 없으며, 반복(loop iterates)하는 동안 컬렉션(collection)이 변경(change)되지 않는다. 모든 명령(commands)은 순차적(sequence)으로 실행(execution)되며, number 변수를 직접 수정할 수 없다.

     

    Asynchronous code

    유사한(similar) 코드를 고려하되, 각 반복(iteration)이 버튼(button) 탭(tap)의 반응(reaction)으로 발생한다고 가정한다. 사용자가 버튼(button)을 반복적으로(repeatedly) 탭(taps)하면, 앱(app)은 배열의 다음(next) 요소(element)를 출력한다:

    var array = [1, 2, 3]
    var currentIndex = 0
    
    // This method is connected in Interface Builder to a button
    @IBAction private func printNext() {
        print(array[currentIndex])
    
        if currentIndex != array.count - 1 {
            currentIndex += 1
        }
    }

    이전 코드와 동일한 컨텍스트(context)에서 이 코드를 생각해 본다. 사용자가 버튼(button)을 반복적으로 탭(taps)할 때, 배열(array)의 모든 요소(elements)가 출력되는 것을 보장할 수 없다. 다른 비동기(asynchronous) 코드가 출력 전에 마지막 요소(element)를 제거(remove)할 수도 있다.

    또는 사용자가 탭한 이후, 다른 코드가 컬렉션(collection) 시작 부분에 새 요소(element)를 삽입(insert)할 수도 있다.

    또한 currentIndex가 printNext()에 의해서만 변경된다고 가정(assume)하였지만, 다른 코드도 currentIndex를 수정할 수 있다. 위의 메서드(method)를 만든 후, 특정 시점에서 이를 변경하는 해당 코드를 추가할 수도 있을 것이다.

    비동기(asynchronous) 코드 작성과 관련된 핵심 문제(issues)는:

    • 작업이 수행되는 순서(the order in which pieces of work are performed)
    • 변경 가능한 데이터 공유(shared mutable data)이다.

    다행히도, 이는 RxSwift의 강력한 기능중 일부이다.

    다음으로 RxSwift의 작동 방식과 문제 해결 방식을 이해하는 데 도움이 되는 좋은 입문서(primer)가 필요하다. 이 책에서는 대략적인 소개(introduction) 이후, 다음 장(chapter)에서 첫 번째 Rx 코드를 작성(writing)할 것이다.

     

    Asynchronous programming glossary

    RxSwift의 일부 언어는 비동기(asynchronous), 반응형(reactive), 함수형 프로그래밍(functional programming)에 매우 밀접하게(tightly) 연결(bound)되어 있으므로, 다음 기본(foundational) 용어들(terms)을 먼저 이해하는 것이 좋다.

    일반적으로 RxSwift는 다음과 같은 문제들(issues)을 다룬다:

     

    1. State, and specifically, shared mutable state

    상태(state)는 다소 정의(define)하기 어렵다. 상태(state)를 이해하기 위해, 다음과 같은 실제 예제(example)를 고려해 본다.

    노트북(laptop)을 처음 켜면 정상적으로 잘 작동(runs)하지만, 며칠 또는 몇 주 동안 계속 사용하다보면 이상하게(weirdly) 작동하거나 갑자기(abruptly) 멈추거나(hang) 반응이 없을 수 있다. 하드웨어(hardware)와 소프트웨어(software)는 그대로(remains)이지만, 상태(state)가 변경되었기 때문이다. 다시 시작하자마자(as soon as you restart), 동일한 하드웨어(hardware)와 소프트웨어(software) 조합(combination)이 다시 한 번 정상적으로(fine) 작동할 것이다.

    메모리의 데이터(the data in memory), 디스크에 저장된 데이터(the one stored on disk), 사용자 입력에 반응하는 모든 구조물(all the artifacts of reacting to user input), 클라우드 서비스에서 데이터를 가져온 후 남아있는 모든 흔적(all traces that remain after fetching data from cloud services) 등 이 모든 것의 합계(sum)가 노트북(laptop)의 상태(state)이다.

    특히 여러(multiple) 비동기(asynchronous) 구성 요소(components)간에 공유(shared)되는 경우 앱의 상태(state)를 관리하는 것(managing)은 이 책에서 다루는(handle) 문제(issues) 중 하나이다.

     

    2. Imperative programming

    명령형(imperative) 프로그래밍(programming)은 문장(statements)을 사용하여 프로그램(program)의 상태(state)를 변경하는 프로그래밍(programming) 패러다임(paradigm)이다. 강아지와 놀면서 명령(imperative language)을 하는 것과 비슷하다. “Fetch! Lay down! Play dead!” 작업을 수행 시기(when)와 방법(how)을 앱에 정확히(exactly) 알려주기 위해 명령형 코드(imperative code)를 사용한다. 

    명령형 코드(imperative code)는 컴퓨터가 이해하는(understands) 코드와 유사하다. CPU가 수행하는 모든 작업은 간단한(simple) 명령들(instructions)의 일련의 긴(lengthy) 순서(sequences)를 따르는(follow) 것이다. 문제(issue)는 인간에게는 복잡한(complex) 비동기(asynchronous) 앱의 명령형 코드(imperative code)를 작성하는 것이 어렵다는 것이다. 특히(especially) 공유된(shared) 변경 가능(mutable) 상태(state)가 관련(involved)되어 있는 경우에는 더욱 그렇다.

    예를 들어, iOS 뷰 컨트롤러(view controller)의 viewDidAppear(_:)에서 다음과 같은 코드를 사용한다:

    override func viewDidAppear(_ animated: Bool) { 
        super.viewDidAppear(animated)
    
        setupUI()
        connectUIControls()
        createDataSource()
        listenForChanges()
    }

    이러한 메서드(methods)가 무엇을 하는지 알 수 없다. 뷰 컨트롤러(view controller) 자체(itself)의 속성(properties)을 업데이트(update)하는지, 올바른 순서(order)로 호출되는지 알지 못한다. 누군가 실수로(inadvertently) 이러한 메서드(method)의 호출(calls) 순서(order)를 바꾸고(swapped), 소스(source) 제어(control)에 변경 사항(change)을 가했을(committed) 수도 있다. 그러면 앱은 변경된(swapped) 호출(calls) 순서로 인해, 이전과 다르게 작동(behave)할 수 있다.

     

    3. Side effects

    지금까지 변경 가능한(mutable) 상태(state)와 명령형(imperative) 프로그래밍(programming)에 대해 알아보았다. 이 두 가지와 관련된 대부분(most)의 문제(issues)는 side effects와 연관지을(pin down) 수 있다.

    Side effects는 코드의 현재(current) 범위(scope)를 벗어난(outside) 상태(state)의 모든 변경(changes)을 나타낸다. 예를 들어, 위의 예제(example)의 마지막 코드(piece of code)를 생각해 볼 수 있다.

    connectUIControls()는 일부 UI 구성 요소(components)에 일종의 이벤트(event) 처리기(handler)를 첨부(attaches)할 것이다. 이는 뷰(view)의 상태(state)를 변경하기 때문에, side effect가 발생한다. 앱은 connectUIControls()를 실행하기 전과 그 후에 다르게 작동(behaves)한다.

    디스크에 저장된 데이터(data stored on disk)를 수정(modify)하거나 화면의 레이블 텍스트(the text of a label on screen)를 업데이트(update)할 때마다, side effect가 발생한다.

    side effects 그 자체로는 나쁜 것이 아니다. 결국, side effects를 일으키는(causing) 것이 모든 프로그램(program)의 궁극적인(ultimate) 목표(goal)이다. 프로그램(program) 실행(executing)이 완료(finished)된 후에는 어떻게든 상태(state)를 변경해야 한다.

    잠시 실행(running)되고, 아무것도 하지 않으면 쓸모없는 앱이 될 뿐이다.

     

    side effects 발생(producing)의 중요한(important) 측면(aspect)은 통제된(controlled) 방식으로 수행하는 것이다. 어떤 코드가 side effects를 일으키는지(cause), 어떤 코드가 단순히 데이터를 처리(process)하고 출력(output)하는지 판단(determine)할 수 있어야 한다.

    RxSwift는 다음 몇 가지 개념(concepts)을 다루면서, 위에 나열된(listed) 문제(issues, problems)를 해결하려고 한다.

     

    4. Declarative code

    명령형(imperative) 프로그래밍(programming)에서는 마음대로(at will) 상태(state)를 변경할 수 있다. 함수형(functional) 프로그래밍(programming)에서는 side effects를 일으키는 코드를 최소화(minimize)하는 것을 목표(aim)로 한다. 완벽한 세상에 살고 있지 않기 때문에, 균형(balance)은 중간(middle) 어딘가에 놓여있다(lies). RxSwift는 명령형(imperative) 코드와 함수형(functional) 코드의 가장 좋은 면(aspects)을 결합(combines)한다.

    선언적(declarative) 코드를 사용하면, 동작(behavior)의 일부를 정의(define)할 수 있다. RxSwift는 관련(relevant) 이벤트(event)가 있을 때마다, 이러한 동작(behaviors)을 실행(run)하고, 변경되지 않는(immutable) 격리(isolated)된 작업 데이터를 제공(provide)한다.

    이렇게 하면 비동기(asynchronous) 코드로 작업하면서, 간단한 for 반복문(loop)에서와 동일한 가정(assumptions)을 할 수 있다. 즉, 변경되지 않는(immutable) 데이터로 작업하고 있으며 순차적(sequential)이고 결정적(deterministic)인 방식으로 코드를 실행할 수 있다.

     

    5. Reactive systems

    반응형(reactive) 시스템(systems)은 다소(rather) 추상적(abstract)인 용어(term)이며, 다음 특성(qualities)을 대부분 또는 모두 나타내는(exhibit) 웹(web)이나 iOS 앱(apps)을 다룬다:

    • Responsive: 앱 상태(state)를 나타내는 UI를 항상 최신(latest)으로 유지(keep)한다.
    • Resilient: 각 동작(behavior)은 분리(isolation)하여 정의(defined)되며, 유연한(flexible) 오류(error) 복구(recovery)를 제공한다.
    • Elastic: 코드는 다양한(varied) 작업(workload)을 처리하며, 종종 지연 풀 기반 데이터 수집(lazy pull-driven data collections), 이벤트 조절(event throttling), 리소스 공유(resource sharing)와 같은 기능을 구현(implementing)한다.
    • Message-driven: 구성 요소(components)는 향상된(improved) 재사용성(reusability)과 분리(isolation)를 위해 메시지 기반(message-based) 통신(communication)을 사용하여 클래스의 수명주기(lifecycle)와 구현(implementation)을 분리한다.

    이제 RxSwift가 해결(solve)에 도움이 되는 문제(issues)와 이러한 문제(problems)에 접근(approaches)하는 방법을 이해했으므로, Rx의 구성 요소(building blocks)와 그 요소들이 어떻게 함께 작동하는지에 대해 설명할 차례이다.

     

    Foundation of RxSwift

    반응형(reactive) 프로그래밍(programming)은 새로운 개념(concept)이 아니다. 꽤(fairly) 오랫동안(long time) 사용되어 왔지만, 핵심(core) 개념(concepts)은 지난 10년(decade) 동안 눈에 띄게 재유행(comeback)했다.

    이 기간(period) 동안 웹 앱(web apps)이 더 많이 관여(involved)되어, 복잡한(complex) 비동기(asynchronous) UI 관리(managing) 문제에 직면(facing)해 왔다. 서버 측(server side)에서는 위에서 설명한 반응형(reactive) 시스템(systems)이 필수(necessity)가 되었다.

    Microsoft의 한 팀은 이 장(chapter)에서 논의한 비동기적(asynchronous)이고 확장 가능한(scalable) 실시간(real-time) 앱(app) 개발(development) 문제를 해결에 도전했다. 2009년 경, 그들은 Reactive Extensions for .NET (Rx)이라는 새로운 클라이언트(client)와 서버 측(server side) 프레임 워크(framework)를 제공했다.

    .NET 용 Rx(Rx for .NET)는 2012년부터 오픈 소스(open source)가 되어 다른 언어(languages)와 플랫폼(platforms)이 동일한 기능(functionality)을 다시 구현(reimplement)할 수 있게 되면서, Rx 교차 플랫폼(cross-platform) 간의 표준(standard)이 되었다.

    오늘날에 이르러서는 RxJS, RxKotlin, Rx.NET, RxScala, RxSwift 등이 있다. 모두 Reactive Extensions 를 기반으로, 동일한 동작(behavior)과 동일한 표현형(expressive) API를 구현하기 위해 노력(strive)한다. 궁극적으로(ultimately), RxSwift로 iOS 앱(app)을 만드는 개발자는 웹에서 RxJS를 사용하는 다른 개발자와 앱(app) 논리(logic)에 대해 자유롭게 토론할 수 있다.

    http://reactivex.io에서 Rx 구현(implementations) 제품군(family)에 대해 자세히 알아볼 수 있다.

    본래(original)의 Rx와 마찬가지로 RxSwift에서도 지금까지 다룬 모든 개념(concepts)이 포함된다. 변경 가능한(mutable) 상태(state)를 처리(tackles)하고, 이벤트(event) 시퀀스(sequences)를 구성(compose)할 수 있으며, 코드 분리(code isolation), 재사용성(reusability), 비동조화(decoupling) 같은 구조(architectural) 개념(concepts)을 개선(improves)할 수 있다.

    이 책에서는 RxSwift를 사용한 개발의 주춧돌(cornerstone)이 되는 개념(concepts)과 이를 앱(apps)에서 사용하는 방법의 실제 사례(real-world examples)를 모두 다룰 것이다.

    Rx 코드의 세 가지 구성 요소(building blocks)는 Observable, 연산자(operators), 스케줄러(schedulers)이다. 아래 섹션(sections)에서 각 항목에 대해 자세히 설명한다.

     

    Observables

    Observable<Element>는 Rx 코드의 기초(foundation)를 제공(provides)한다. 즉, Element 유형(type)의 일반(generic) 데이터에 대한 변경 불가능한(immutable) 스냅샷(snapshot)을 "전달(carry)"할 수 있는 일련의 이벤트(events)를 비동기적(asynchronously)으로 생성한다. 간단히 말해서(in the simplest words) 소비자(consumers)는 시간이 지남에 따라(over time) 다른 객체(object)에서 내보낸(emitted) 이벤트(events) 또는 값(values)을 구독(subscribe)할 수 있다.

    Observable 클래스(class)를 사용하면, 하나 이상의 observers가 실시간으로(in real time) 이벤트(events)에 반응(react)하고 앱(app)의 UI를 업데이트(update)하거나, 새로운 데이터와 수신(incoming) 데이터를 처리(process)하고 활용(utilize)할 수 있다.

    Observable이 준수(conforms)하는 ObservableType 프로토콜(protocol)은 매우(extremely) 간단(simple)하다. Observable은 다음과 같은 세 가지 유형(types)의 이벤트(events)만 방출 할 수 있으며 observers는 이를 수신(receive)할 수 있다:

    • next event: 최신(latest, 또는 "next") 데이터 값(value)을 "전달(carries)"하는 이벤트(event)이다. 이것이 observers가 값(values)을 "받는(receive)" 방식이다. Observable은 종료(terminating) 이벤트(event)가 발생(emitted)할 때까지, 이러한 값(values)을 무한정(indefinite) 내보낼(emit) 수 있다.
    • A completed event: 이 이벤트(event)는 성공(success)적으로 이벤트(event) 시퀀스(sequence)를 종료(terminates)한다. 이는 Observable이 수명주기(lifecycle)를 성공적으로 완료(completed)했으며, 추가(additional) 이벤트(events)를 내보내지(emit) 않음을 의미한다.
    • An error event: Observable은 오류(error)와 함께 종료(terminates)되며, 추가(additional) 이벤트(events)를 내보내지(emit) 않는다.

    시간이 지남(over time)에 따라 발생(emitted)하는 비동기(asynchronous) 이벤트(events)에 대해 이야기할 때, 다음과 같이 타임 라인(timeline)에서 observable 정수(integers) 스트림(stream)을 시각화(visualize)할 수 있다:

     

    Observable이 내보낼(emit) 수 있는 세 가지 가능한(possible) 이벤트(events)의 간단한 계약(contract)은 Rx의 모든 것이다. 매우 보편적(universal)이기 때문에, 가장 복잡한(complex) 앱 논리(logic)를 만드는 데까지 사용할 수 있다.

    클래스(classes)가 서로 통신하도록 하기 위해(to talk to each other) delegate 프로토콜(protocols)을 사용하거나 클로저(closures)를 삽입(inject)할 필요가 없다.

     

    Observable 시퀀스에는 유한(finite)무한(infinite)이 있다. 실제 상황(real-life situations)에서 이 두 가지에 대해 살펴본다.

     

    Finite observable sequences

    일부 observable 시퀀스(sequences)는 0개 혹은 하나 이상의 값(values)을 내보내고(emit), 이후에 성공적(successfully)으로 종료(terminate)되거나 오류(error)와 함께 종료(terminate)된다.

    인터넷(internet)에서 파일을 다운로드(downloads)하는 iOS 앱(app) 코드를 고려해 본다:

    • 먼저 다운로드(download)를 시작하고, 수신(incoming) 데이터를 관찰(observing)한다.
    • 파일의 일부가 도착(arrive)할 때, 반복적으로(repeatedly) 데이터 청크(chunks of data)를 받는다(receive).
    • 네트워크(network) 연결(connection)이 끊어지면(goes down), 다운로드(download)가 중지(stop)되고 오류(error)와 함께 연결 시간이 초과된다(time out).
    • 또는 코드가 모든 파일의 데이터를 다운로드(downloads)하면 성공적(success)으로 완료(complete)된다.

    이 작업 흐름(workflow)은 일반적인(typical) observable의 수명주기(lifecycle)를 정확하게(accurately) 설명(describes)한다. 아래의 관련 (related)코드를 확인해 본다:

    API.download(file: "http://www...") //Observable<Data> 객체를 반환. 데이터의 값을 네트워크로 전달한다.
        .subscribe(
            onNext: { data in //onNext로 "next" 이벤트를 subscribe 한다.
                // Append data to temporary file
            },
            onError: { error in //onError로 "error" 이벤트를 subscribe 한다.
                // Display error to user
            },
            onCompleted: { //onCompleted로 "completed" 이벤트를 처리한다.
                // Use downloaded file
            }
        )

    API.download(file:)는 네트워크(network)에서 가져온 데이터 청크(chunks of data)로 Data 값(values)을 내보내는(emits) Observable<Data> 인스턴스(instance)를 반환한다.

    onNext 클로저(closure)를 제공(providing)하여 next 이벤트(events)를 구독(subscribe)한다. 다운로드 예제(example)에서는 디스크(disk)에 저장된(stored) 임시(temporary) 파일(file)에 데이터를 추가(append)한다.

    onError 클로저(closure)를 제공(providing)하여 오류(error)를 구독(subscribe)한다. 이 클로저(closure)에서 알림(alert)으로 error.localizedDescription을 표시(display)하거나, 오류(error)를 처리(handle)할 수 ​​있다.

    마지막으로, 완료된(completed) 이벤트(event)를 처리(handle)하기 위해, onCompleted 클로저(closure)를 제공(provide)한다. 여기에서 새로운 뷰 컨트롤러(view controller)를 push하여 다운로드된(downloaded) 파일(file) 또는 앱(app) 논리(logic)가 지시(dictates)하는 다른 어떤 항목을 표시(display)할 수 있다.

     

    Infinite observable sequences

    자연적으로(naturally) 혹은 강제로(forcefully) 종료(terminate)되어야 하는 파일(file) 다운로드(downloads)나 이와 유사한(similar) 작업(activities)과는 달리, 단순히 무한한(infinite) 다른 시퀀스(sequences)가 ​​있다. 대체로, UI 이벤트(events)는 무한(infinite) observable 시퀀스(sequences)이다.

    예를 들어, 앱(app)의 기기(device) 방향(orientation) 변경(changes)에 대응(react)하는 코드를 고려해 본다:

    • NotificationCenter의 UIDeviceOrientationDidChange 알림(notifications)에 클래스(class)를 관찰자(observer)로 추가한다.
    • 그런 다음 방향(orientation) 변경(changes)을 처리(handle)하기 위해 메서드(method) 콜백(callback)을 제공(provide)해야 한다. UIDevice에서 현재(current) 방향(orientation)을 가져와, 최신 값(latest value)에 따라 반응(react)해야 한다.

    이 방향(orientation) 변경(changes) 시퀀스(sequence)에는 자연스러운(natural) 끝(end)이 없다. 장치가 있는 한(as long as there is a device), 방향(orientation) 변경(changes) 시퀀스(sequence)가 있을 수 있다. 또한 시퀀스(sequence)는 사실상(virtually) 무한(infinite)하고 상태를 가지고 있으므로(stateful), 관찰(observing)을 시작할 때 항상 초기 값(initial value)을 가지고 있다.

     

    사용자가 기기(device)를 회전(rotates)하지 않는 경우도 있을 수 있지만, 그렇다고 해서 이벤트(events) 시퀀스(sequence)가 ​​종료되는 것은 아니다. 그것은 단지 어떤 이벤트(events)도 발생(emitted)하지 않았음을 의미한다.

    RxSwift에서는 다음과 같은 코드를 작성하여, 기기(device) 방향(orientation)을 처리(handle)할 수 ​​있다:

    UIDevice.rx.orientation //Observable<Orientation>의 가상의 컨트롤 속성
        .subscribe(onNext: { current in //subscribe 하고 방향에 따라 UI를 업데이트 한다.
            switch current {
            case .landscape:
                // Re-arrange UI for landscape
            case .portrait:
                // Re-arrange UI for portrait
            }
        })

    UIDevice.rx.orientation은 Observable<Orientation>을 생성하는 가상의(fictional) 컨트롤(control) 속성(property)이다(이것을 직접 코딩하기는 매우 쉽습니다. 다음 장(chapters)에서 그 방법을 배울 것이다). 구독(subscribe)하고, 현재(current) 방향(orientation)에 따라 앱(app) UI를 업데이트(update)한다.

    onError, onCompleted 는 생략(skip)할 수 있다. 이러한 이벤트(events)는 이 observable에서 생성(emitted)될 수 없기 때문이다.

     

    Operators

    ObservableType 및 Observable 구현(implementation) 클래스(class)에는 비동기(asynchronous) 작업 및 이벤트(event) 조작(manipulations)의 개별(discrete) 부분을 추상화(abstract)하는 많은(plenty) 메서드(methods)가 포함(include)되어 있으며, 더 복잡한(complex) 논리(logic)를 구현(implement)하기 위해 이를 함께 구성(composed)할 수 있다. 이는 고도(highly)로 분리(decoupled)되고 합성 가능(composable)하기 때문에, 이러한 메서드(methods)를 흔히 연산자(operators)라고 부른다.

    이러한 연산자(operators)는 대부분(mostly) 비동기(asynchronous) 입력(input)을 받아, side effects 없이 출력(output)을 생성(produce)하기 때문에 퍼즐 조각처럼 쉽게 맞춰서(fit) 더 큰 구조(a bigger picture)를 만들(build) 수 있다.

    예를 들어, (5 + 6) * 10 - 2 와 같은 수학식(mathematical expression)을 생각해 볼 수 있다.

    명확(clear)하고 결정적(deterministic)인 방식으로 *, (), +, - 연산자(operators)를 미리 정의된(predefined) 순서(order)대로 입력(input) 데이터 조각(pieces of data)에 적용하고 출력(output)을 가져와 해결(resolved)될 때까지 표현식(expression)을 계속 처리(processing)할 수 ​​있다.

    유사한(similar) 방식(manner)으로, Observable이 내보낸(emitted) 이벤트(events)가 Rx 연산자(operators)를 적용(apply)하여, 표현식(expression)이 최종 값(final value)이 될 때까지 입력(inputs) 및 출력(outputs)을 결정적(deterministically)으로 처리(process)할 수 ​​있으며, 이를 사용해 side effects을 일으킬 수 있다.

    다음은 이전의 방향(orientation) 변경(changes) 관찰(observing) 예제(example)에 몇 가지 일반적인(common) Rx 연산자(operators)를 사용하여 수정한(adjusted) 것이다:

    UIDevice.rx.orientation
        .filter { $0 != .landscape } //.landscape가 아닌 값만을 통과시킨다.
        //따라서 .landscape안 경우에는 바로 반환되어 subscribe 되지 않는다.
        .map { _ in "Portrait is the best!" } //filter 이후 값이 .portrait 인 경우에만 해당된다.
        .subscribe(onNext: { string in //subscribe 해, 이벤트가 발생하면 alert으로 텍스트를 호출해 준다.
            showAlert(text: string)
        })

    UIDevice.rx.orientation이 .landscape 또는 .portrait 값(value)을 생성(produces)할 때마다, RxSwift는 방출된(emitted) 데이터에 filter를 적용(apply)하고 매핑(map)한다.

     

    먼저, filter는 .landscape가 아닌 값(values)만 통과시킬 것이다. 기기가 가로(landscape) 모드(mode)인 경우, filter가 이러한 이벤트(events)를 억제(suppress)하므로 구독(subscription) 코드가 실행되지 않는다.

    .portrait 값(values)의 경우, map 연산자(operator)는 Orientation 유형(type) 입력(input)을 받아 "Portrait is the best!"라는 문자열(String) 출력(output)으로 변환(convert)한다. 

    마지막으로 subscribe를 사용하여 next 이벤트(event)를 구독(subscribe)하고, 이번에는 문자열(String) 값(value)을 전달(carrying)하여 해당 텍스트로 화면(onscreen)에 알림(alert)을 표시(display)하는 메서드(method)를 호출(call)한다.

    또한 연산자(operators)는 고도로(highly) 구성적(composable)이다. 항상 데이터를 입력(input)으로 받아 결과를 출력(output)하므로 단일 연산자(operator)가 스스로 할 수 있는 것보다 훨씬 많은 것을 달성(achieving)하기 위해, 다양한 방법으로 연산자를 쉽게 연결(chain)할 수 있다.

    이 책에서 비동기(asynchronous) 작업의 더 많은 부분을 추상화(abstract)하는 더 복잡한(complex) 연산자(operators)에 대해 배울 것이다.

     

    Schedulers

    스케줄러(Schedulers)는 Rx에서 dispatch queues 또는 operation queues와 동일하지만, 훨씬 강력(steroids)하고 사용하기 쉽다. 특정(specific) 작업의 실행(execution) 컨텍스트(context)를 정의(define)할 수 있다.

    RxSwift에는 99%의 사용 사례(cases)를 다룰 수 있는 사전 정의(predefined)된 스케줄러(schedulers)가 제공된다. 이는 사용자 정의(own) 스케줄러(scheduler)를 만들 필요가 없음을 의미한다.

    이 책 전반부(first half)에 있는 대부분의 예제(examples)는 매우 간단(simple)하고 일반적인 데이터 관찰(observing) 및 UI 업데이트(updating)를 다루기 때문에, 기본 사항(basics)을 다룰(covered) 때까지 스케줄러(schedulers)를 전혀 살펴 보지 않을 것이다.

    말하자면(that being said), 스케줄러(schedulers)는 매우 강력하다.

    예를 들어, Grand Central Dispatch를 사용해 지정된(given) 대기열(queue)에서 코드를 직렬로(serially) 실행(run)하는 SerialDispatchQueueScheduler에서 next 이벤트(events)를 관찰(observe)하도록 지정(specify)할 수 있다.

    ConcurrentDispatchQueueScheduler는 코드를 동시(concurrently)에 실행(run)하고, OperationQueueScheduler를 사용하면 주어진 OperationQueue에서 구독(subscriptions)을 예약(schedule)할 수 있다.

    RxSwift 덕분에 다른 스케줄러(schedulers)에서 동일한 구독(subscription)의 다른 여러 작업을 예약(schedule)하여 사용 사례(use-case)에 맞는 최고의 성능(performance)을 얻을 수 있다.

    RxSwift는 구독(subscriptions, 왼쪽)과 스케줄러(schedulers, 오른쪽) 사이의 관리인(dispatcher) 역할을 하여, 작업물(pieces of work)을 올바른(correct) 컨텍스트(context)로 보내고(sending) 서로의 출력(output)과 원활하게(seamlessly) 작업할 수 있도록 한다.

     

    이 도표(diagram)를 읽으려면 여러 스케줄러(schedulers)에서 색상이 지정된 작업을 예정된(sequence) 순서대로(sequence, 1, 2, 3, ...) 따라간다. 예를 들면:

    • 파란색의 네트워크(network) 구독(subscription)은 사용자 정의(custom) OperationQueue 기반 스케줄러(scheduler)에서 실행되는 코드 (1)로 시작한다.
    • 이 블록(block)의 데이터 출력(output)은 동시(concurrent) 백그라운드(background) GCD 대기열(queue)에 있는 다른 스케줄러(scheduler)에서 실행(runs)되는 다음 블록(block) (2)의 입력(input)으로 사용된다.
    • 마지막으로 새로운 데이터로 UI를 업데이트(update)하기 위해 마지막 파란색 코드 (3)가 기본(main) 스레드(thread) 스케줄러(scheduler)에 예약(scheduled)된다.

    매우 흥미롭고(interesting) 꽤 편리(handy)해 보이지만, 지금 당장은 스케줄러(schedulers)에 너무 신경 쓸 필요 없다. 이 책의 뒷부분에서 다시 살펴 본다.

     

    App architecture

    RxSwift는 어떤 식으로든 앱(app)의 아키텍처(architecture)를 변경(alter)하지 않는다는 점을 언급할(mentioning) 필요가 있다. RxSwift는 주로 이벤트(events), 비동기 데이터 시퀀스(asynchronous data sequences), 범용 통신 계약(universal communication contract)을 다룬다.

    또한 반응형(reactive) 앱(app)으로 만들기 위해 처음부터(from scratch) 프로젝트(project)를 시작할 필요가 없다는 점도 중요합니다. 기존(exiting) 프로젝트(project)의 일부를 반복적으로(iteratively) 리팩토링(refactor)하거나, 앱(app)의 새로운 기능(features)을 만들(building) 때 간단하게(simply) RxSwift를 사용할 수 있다.

    Model-View-Controller, Model-View-Presenter, Model-View-ViewModel(MVVM) 등의 다양한 아키텍처(architecture) 패턴(pattern)을 Rx로 구현하여 앱(apps)을 만들 수 있다.

    RxSwift와 MVVM은 특히 잘 어울린다. 그 이유는 ViewModel을 사용하면 Observable 속성(properties)을 노출(expose)할 수 있으므로 ,V 뷰 컨트롤러(View controller)의 glue 코드에서 UIKit 컨트롤(controls)에 직접 바인딩(bind)할 수 있다. 이렇게 하면 모델(model) 데이터를 UI에 바인딩(binding)하는 것이 매우 간단하여 다음과 같이 나타낼 수 있다:

     

    이 책의 끝 부분에서 해당 패턴(pattern)과 RxSwift를 사용하여 구현(implement)하는 방법을 살펴 본다. 이 책의 다른 모든 예제(examples)의 샘플 코드는 간단하고 이해하기 쉬운 MVC 아키텍처(architecture)를 사용한다.

     

    RxCocoa

    RxSwift는 플랫폼에 구애받지 않는(platform-agnostic) 공통(common)의 Rx 사양(specification)을 구현(implementation)이다. 따라서 Cocoa 또는 UIKit의 특정(specific) 클래스(classes)에 대해 전혀 알지 못한다.

    RxCocoa는 UIKit 및 Cocoa 개발에 특별히 도움이 되는 모든 클래스(classes)를 포함하는 RxSwift의 동반(companion) 라이브러리(library)이다. 일부 고급(advanced) 클래스(classes)를 제공하는 것 외에도, RxCocoa는 다양한 UI 이벤트(events)를 즉시 구독(subscribe)할 수 있도록 많은 UI 구성 요소(components)에 반응형(reactive) 확장(extensions)을 추가한다.

    예를 들어 RxCocoa를 사용하여 다음과 같이 UISwitch의 상태(state) 변경(changes)을 구독(subscribe)하는 것은 매우 쉽다:

    toggleSwitch.rx.isOn 
        //RxCocoa는 UISwitch에 rx.isOn 속성을 추가하여 이벤트를 Observable sequence로 subscribe 할 수 있다.
        .subscribe(onNext: { isOn in
            print(isOn ? "It's ON" : "It's OFF")
        })

    RxCocoa는 UISwitch 클래스(class)에 rx.isOn 속성(property)을 추가하므로, 유용한 이벤트(events)를 반응형(reactive) Observable 시퀀스(sequences)로 구독(subscribe)할 수 있다.

     

    또한 RxCocoa는 UITextField, URLSession, UIViewController 등에 rx 이름공간(namespace)를 추가하고, 이 이름공간(namespace)에서 자체 반응향(reactive) 확장(extensions)을 정의(define)할 수 있도록 한다. 이에 대해서는 이 책의 뒷부분(later)에서 자세히 알아볼 것이다.

     

    Installing RxSwift

    RxSwift는 오픈 소스(open-source)이며 https://bit.ly/2ZOzK2i에서 무료로(for free) 사용할 수 있다.

    RxSwift는 MIT 라이센스(license)에 따라 배포된다. 즉, 라이브러리(library)를 그대로 무료(free) 또는 상용(commercial) 소프트웨어에 포함(include)할 수 있다. 다른 모든 MIT 라이선스(licensed) 소프트웨어(software)와 마찬가지로 배포하는(distribute) 모든 앱에 저작권(copyright) 고지(notice)가 포함되어야 한다.

    RxSwift 저장소(repository)에는 탐색(explore)해 볼 것이 많다(plenty). 여기에는 RxSwift, RxCocoa, RxRelay 라이브러리(libraries)가 포함되어 있으며, RxSwift 코드에 대한 테스트(tests)를 작성할 수있는 RxTestRxBlocking도 있다.

    확실히 살펴볼(peeking into) 가치가 있는 모든 훌륭한(great) 소스 코드 외에도 많은 연산자(operators)를 대화식으로(interactively) 보여주는(demonstrates) Rx.playground를 찾을 수 있다. 또한 많은 개념(concepts) 사례(practice)를 보여주는(demonstrates) 훌륭한 쇼케이스(showcase) 앱(app)인 RxExample도 확인해 볼 수 있다.

    RxSwift/RxCocoa는 Xcode에 내장(built-in)된 dependency management 또는 Cocoapods, Carthage를 사용해 다양한 방법으로 설치(install)할 수 있다.

     

    RxSwift via CocoaPods

    다른 CocoaPod과 마찬가지로 RxSwift를 설치(install)할 수 있다. 일반적인(typical) Podfile은 다음과 같다:

    use_frameworks!
    target 'MyTargetName' do
        pod 'RxSwift', '~> 5.1'
        pod '
    RxCocoa', '~> 5.1'
    end

    물론 RxSwift만 사용하거나, RxSwift와 RxCocoa를 모두 포함하는 외에, GitHub 저장소(repository)에 있는 모든 라이브러리(libraries)를 포함할 수도 있다.

     

    RxSwift via Carthage

    Carthage로 RxSwift를 설치하는 것 또한 간결하다(streamlined). 먼저 https://bit.ly/3cd1fF5에서 최신 버전의 Carthage를 설치했는지 확인한다.

    프로젝트(project)에서 Cartfile이라는 새 파일을 만들고 다음 행(line)을 추가한다:

    github "ReactiveX/RxSwift" ~> 5.1

    다음으로 프로젝트(project) 폴더(folder) 내에서 carthage update를 실행(execute)한다.

    이렇게 하면 RxSwift 저장소(repository)에 포함된 모든 라이브러리(all libraries)의 소스 코드를 다운로드(download)하고 빌드(build)하므로 다소 시간이 걸릴 수 있다. 작업(process)이 완료(finishes)되면, 현재(current) 폴더(folder) 내에 생성된(created) Carthage 하위 폴더(subfolder)에서 결과(resulting) 프레임 워크(framework) 파일(files)을 찾아 프로젝트(project)에 연결한다.

    Xcode가 새로 추가된 프레임 워크(frameworks)를 인덱싱(indexes)하도록 한 번 더 빌드(build)하면 준비가 완료된다(ready to go).

     

    Installing RxSwift in the book projects

    이 책의 프로젝트(projects)는 모두 CocoaPods와 함께 사용할 수 있는 완성된 Podfile과 함께 제공되지만, 책 프로젝트(projects)의 다운로드(download) 크기(size)를 줄이기기 위해 RxSwift 자체가 설치(installed)되어 있지는 않다.

    책을 시작하기 전에 최신 버전(latest version)의 CocoaPods이 설치(installed)되어 있는지 확인한다. 책의 프로젝트(projects)를 시작하기 전에 한 번만(just once) 수행하면 된다. 일반적으로 터미널(Terminal)에서 다음을 실행(executing)하는 것으로 충분하다(suffice):

    sudo gem install cocoapods

    이에 대해 더 알고 싶다면 CocoaPods 웹 사이트를 방문한다: https://bit.ly/2XGIvIN

    각 장(each chapter)의 시작(starter) 프로젝트(project)를 시작할 때, RxSwift를 설치하라는 메시지가 표시된다. 이 작업은 매우 쉽다:

    1. 책 폴더(folder)에서 작업 중인 장(chapter)의 이름과 일치하는 디렉토리(directory)를 찾는다.
    2. 컴퓨터의 편한(convenient) 위치(location)에 시작(starter) 폴더(folder)를 복사(copy)한다. 해당 위치(location)로 사용자(user) 폴더(folder)를 선택하는 것은 좋은 생각이다.
    3. 내장된(built-in) Terminal.app 또는 다른 터미널 앱(app)을 열고, 시작(starter) 폴더(folde)로 이동한다. 예제 경로(path)를 컴퓨터의 실제 경로(path)로 바꾸려면 cd /users/yourname/path/to/starter를 입력한다.
    4. Playground를 사용하는 장(chapters)에서는 단순히 ./bootstrap.sh를 실행(run)하면 GitHub에서 RxSwift를 가져오고(fetch), 프레임 워크(framework)를 미리 빌드(pre-build)한 다음, 자동으로(automatically) Xcode를 열어 코드 작성을 시작할 수 있다.
    5. 표준(standard) Xcode 프로젝트(project)를 사용하는 장(chapters)에서는 pod install을 입력(type)하여, GitHub에서 RxSwift를 가져와  챕터(chapter) 프로젝트(project)에 설치(install)한다. 새로 생성된 .xcworkspace 파일을 찾아 실행(launch)한다. 그리고 Xcode에서 workspace을 한 번 빌드(build)한다.

    이제 다음 장(chapter)을 시작할 준비가 되었다.

    모든 playgrounds가 Xcode 11에서는 테스트 되었지만, Xcode 12는 RxSwift와 같은 서드 파티(third-party) 의존성(dependencies)을 가진 playgrounds 지원(support)에 많은 문제가 있다. 만약 이 책에 제공된 playgrounds 중 하나가 작동하지 않는다면, playgrounds의 코드를 복사(copy)하여 RxSwift가 내장된(embedded) 정규(regular) 프로젝트(project)에 코드를 붙여넣거나, 이러한 특정 장(chapters)에 대해서는 Xcode 11에서 작업하는 것을 추천한다.

     

    RxSwift and Combine

    이 소개(introductory) 장(chapter)에서는 RxSwift가 무엇인지 알아보았다. notification center 및 delegates와 같은 기존의(traditional) API를 사용하는 것보다 RxSwift로 반응형(reactive) 코드를 작성하는 것의 이점에 대해 설명했다.

    마무리(wrapping up)하기 전에, 앞서 언급한(mentioned) Apple의 자체 반응형(reactive) 프레임 워크(framework)인 Combine에 대해 좀 더 알아볼 가치가 있다.

    RxSwift와 Combine은 Swift의 다른 반응형(reactive) 프로그래밍(programming) 프레임 워크(frameworks)뿐 아니라, 많은 공통적인 문법(language)과 매우 유사한(similar) 개념(concepts)을 공유한다.

    RxSwift는 주로 다중 플랫폼(multi-platform) 교차 언어(cross-language) 표준(standard)에 영향 받은 고유한(original) 개념(concepts), 연산자(operator) 이름, 유형(type) 다양성(variety)을 가진 오래되고(older) 잘 확립된(established) 프레임 워크(framework)이다. 이는 리눅스(Linux)에서도 작동하며, 서버 측(Server-Side) Swift에도 적합하다. 또한 오픈 소스(open source)이므로 원하는(wish) 경우, 핵심(core) 구현에 직접(directly) 기여(contribute)하고 특정(specific) 부분(portions)이 작동하는 방식을 정확하게(exactly) 볼 수 있다. 그리고 iOS 8까지 Swift를 지원하는 모든 Apple 플랫폼(platform) 버전(versions)과 호환(compatible)된다.

    Combine유사한 개념(concepts)을 다루는 Apple의 새로운 프레임 워크(framework)로, Swift와 Apple의 자체 플랫폼(platforms)에 맞춰(tailored) 특별히 제작되었다. Swift 표준(standard) 라이브러리(library)와 많은 공통(common) 언어(language)를 공유(shares)하므로, API는 초보자(newcomers)에게도 매우 친숙(familiar)하다. 그러나 iOS 13, macOS 10.15 이상의 최신 Apple 플랫폼(platforms)만 지원(supports)하며, 안타깝게도(unfortunately) 현재로서는 오픈 소스(open-source)가 아니고 리눅스(Linux)를 지원하지 않는다.

    다행히도 RxSwift와 Combine은 서로 매우 유사(resemble)하기 때문에 RxSwift 지식을 Combine으로 쉽게 이전(transferable)할 수 있으며, 그 반대의 경우(vice-versa)도 마찬가지다. 그리고 RxCombine(https://github.com/CombineCommunity/RxCombine)과 같은 프로젝트(projects)를 사용하면, 필요에 따라 RxSwift의 Observables과 Combine의 Publishers를 짜맞출(mix-and-match) 수 있다.

    Combine에 대해 더 배우고 싶다면, 해당 프레임 워크(framework)에 대한 책을 확인해 볼 수 있다: "Combine : Asynchronous Programming with Swift": https://bit.ly/3dgOGds.

     

    Community

    RxSwift 프로젝트(project)는 Rx로 멋진 소프트웨어를 만들도록 프로그래머(programmers)에게 영감(inspiring)을 줄 뿐만 아니라, 이 프로젝트(project)를 중심으로 형성된 커뮤니티(community)의 긍정적(positive)인 특성(nature)으로 인해 활기차고 활발한(buzzing) 활동이 이어지고 있다.

    RxSwift 커뮤니티(community)는 패턴(patterns)이나 일반적(common)인 기술(techniques)에 대해 토론(discussing)하거나 서로 돕는 것에 대해 매우 친절(friendly)하고 개방적(open minded)이며 열정적(enthusiastic)이다.

    공식 RxSwift 저장소(repository) 외에도 Rx 애호가(enthusiasts)들이 만든 많은 프로젝트(projects)를 http://community.rxswift.org에서 확인할 수 있다.

     

    비가 내린 후 버섯이 솟아 오르는 것처럼(spring up like mushrooms after the rain), 더 많은 Rx 라이브러리(libraries)와 실험(experiments)은 여기에서 찾을 수 있다: https://github.com/RxSwiftCommunity

    아마도 RxSwift에 관심이 있는 많은 사람들을 만나는 가장 좋은 방법은 라이브러리(library) 전용 Slack 채널(channel)인 http://slack.rxswift.org일 것이다.

    Slack 채널(channel)에는 거의 8,000명의 회원(members)이 있다. 이 곳의 일상적인(Day-to-day) 주제(topics)는 서로 돕고, RxSwift 또는 동반(companion) 라이브러리(libraries)의 잠재적인 새로운 특성(features)에 대해 논의(discussing)하며, RxSwift 블로그(blog) 게시물(posts) 및 세미나(conference)의 내용(talks)을 공유하는 것이다.

    'Raywenderlich > RxSwift: Reactive Programming' 카테고리의 다른 글

    Chapter 4: Observables & Subjects in Practice  (0) 2020.09.20
    Chapter 3: Subjects  (0) 2020.09.13
    Chapter 2: Observables  (0) 2020.09.10
Designed by Tistory.