뚝딱뚝딱 모바일

ReactiveX에 대해 알아보자 본문

CS 지식

ReactiveX에 대해 알아보자

규석 2024. 1. 5. 17:14

안녕하세요!

다른 글들을 보시면 많이 언급하기도 했고, 개인적으로 정말 좋아하는 ReactiveX에 대해 알아보겠습니다.


 

ReactiveX

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

reactivex.io

ReactiveX란?

ReactiveX는 Reactive Extenstion의 줄임말로, 옵저버블 스트림을 활용한 비동기적 프로그래밍을 위한 API라고 설명할 수 있습니다.

처음 이 문장을 보시면, 단번에 이해가 어려우실 수 있습니다. 하지만 이 문장을 이해하신다면, ReactiveX (이하 Rx)의 개념을 이해하신 거나 마찬가지인 Rx를 통달하는 문장입니다. 문장을 하나하나 뜯어서 살펴보겠습니다.

비동기적 프로그래밍

개발하시면서 정말 많이 보셨을 겁니다. 간단하게 설명해드리고 가자면 아래 사진 하나로 설명이 가능합니다.

출처 : https://evan-moon.github.io/2019/09/19/sync-async-blocking-non-blocking/, 디지털 풍화가 온거 봐서는 원 출처는 아닌 것 같음

어떠한 작업들을 순차적으로 진행하면 이를 동기, 어떠한 작업들을 동시다발적으로 진행하면 이를 비동기라고 합니다.

 

예시를 하나 들어보겠습니다. 처리가 3초 걸리는 A, 처리가 7초 걸리는 B, 처리가 1초 걸리는 C가 있습니다.

이 그냥 평범하게 A, B, C 작업을 처리한다하면 개발자인 전 시간을 아끼기 위해 비동기적으로 처리하면 좋겠죠? 동기적으로 진행하면, 11초가 걸리지만 비동기적으로 동시에 진행하면 7초밖에 걸리지 않기 때문입니다. 하지만, 작업 수행에 조건이 생긴다면 어떨까요. A, B, C 작업의 결괏값들을 모아 D작업을 처리해야 한다면? A 작업이 시작 전에 특정 조건에 따라 진행될 수도 있고 안될 수도 있다면? B의 결괏값을 C 작업 시작 전에 처리해야 한다면? 등등의 많은 상황들이 나올 수 있습니다. 이러한 상황과 조건들로부터 비동기적 처리를 묶어서 관리할 수 있게 도와주는 것이 Rx입니다.

Observable Stream

Rx에서 위에서 말한 비동기적 처리를 가능케 해주는 친구입니다. 혹시 Stream의 뜻을 아시나요? 

개울, 시내

관측 가능한 개울? 뭔가 말이 이상하지만, 상상을 하나 해봅시다. 개울물이 졸졸 흐르고, 개울물에서는 종종 무언가 떠내려옵니다. 우리는 그 떠내려오는 걸 건져서 무언가의 작업을 합니다. 이해되셨을까요? 대뜸 없이 무슨 말인지도 모르겠고 글쓴이가 술을 마셨나라는 생각이 드실 수도 있습니다. 차근차근 풀어보겠습니다.

개울물(stream)이 졸졸 흐르고, 개울물에서는 종종 무언가(value / action) 떠내려옵니다. 우리는(developer) 그 떠내려오는 걸 건져서(subscribe) 무언가의 작업을 합니다.

 

개울물이 졸졸 흐른다는 것은 앱과 같은 프로그램이 진행되고 있다는 것이고, 무언가 떠내려오는 것은 유저가 입력한 값 또는 클릭 등, 그리고 개발자인 우리는 이를 가지고 추후의 작업을 하게 됩니다. 이런 커다란 프로그램의 흐름을 Stream이라고 합니다.

 

만약 이 개울물에서 물고기만 건져서, 그 물고기를 맛있게 굽는 기계를 하나 만들었다 생각합시다. 우린 기계를 개울에 설치할 것이고, 기계를 가동시킬 겁니다. 이러한 특정한 Stream을 Observable이라 하고, 이를 실행하는 행위를 구독, subscribe한다 합니다. 기계를 실행시켜주지 않는다면, 물고기를 건져 굽지 않겠죠? Observable도 마찬가지로 subscribe 하지 않는다면, 아무 일이 일어나지 않습니다.

 

그리고 이 기계는 개울에서 물고기만 건지고, 건진 물고기를 구이로 만듭니다. 이렇게 Observable에서 받아온 value를 가공하는 것을 Operator라 하며, 각각 filter (물고기만 건짐), map (물고기를 구이로 만듬 ≒ 바꿈)을 뜻합니다.

 

let disposeBag = DisposeBag()
let stream = ["물고기1", "돌", "쓰레기", "개구리", "물고기2"] // 개울
let obs = Observable.from(stream) // 기계
        
obs
    .filter { $0.contains("물고기") } // 필터
    .map { "\($0)구이" } // 고기 굽는 기능
    .subscribe { print($0.element ?? "") } // 구독 (작동 시작)
    .disposed(by: disposeBag)

// 물고기1구이
// 물고기2구이
// 라는 출력문이 나온다.

 

코드로 나타내면 이렇게 나타낼 수 있습니다. 좀 더 세부적으로 파고들면 더 많은 내용이 있지만, Rx의 큰 개념은 이렇습니다. 그렇다면 이러한 Rx를 사용했을 때 얻는 이점은 무엇일까요?

Rx를 사용함으로 얻는 이점

비동기적 코드를 동기적으로 사용하기 쉽습니다.

비동기적 코드를 동기적으로 짜기 위해서 콜백을 자주 사용해보셨을 겁니다. 하지만 이러한 콜백이 많아진다면 매우 보기 불편한 콜백지옥이 눈앞에 나타납니다. 하지만 Rx를 사용하게 되면 일관성 있는 비동기 코드 작성이 가능하고, 가독성이 높아집니다.

다양한 지원

18개의 언어와 3개의 프레임워크

Rx는 한 프레임워크에 종속되는 라이브러리가 아닌 개념적인 라이브러리입니다. 그래서 많은 언어와 여러 플랫폼에서 사용할 수 있습니다. 언어마다 약간의 차이는 있지만 Rx의 개념을 안다면 쉽게 적응할 수 있습니다. 실제로 저도 RxJava를 시작으로 공부했고 이를 RxSwift와 RxDart로까지 적용해 보았습니다.

 

장점이 있다면 단점도 있는 법. 그렇다면 단점은 뭐가 있을까요?

Rx의 단점

쉽지만은 않은 러닝커브

사람마다 느끼는 러닝커브는 다르겠지만 처음 진입이 매우 힘듭니다. 코드를 봐도 이게 무슨 코드인지 이해가 안 되기도 하고, 여러 Operator들과 Observable의 특성이 처음 배우고자 하는 사람에겐 힘들 수 있습니다.

언어 고유 특성과는 다른 이질감

이건 개인적으로 Flutter/Dart를 하면서 느낀 건데, RxDart는 Dart 언어와는 좀 생뚱맞게 논다는 느낌이 들었습니다. Dart에는 기본적으로 Stream과 Future, async와 await 개념이 있어서 그런지, RxDart를 굳이 사용해야 될까라는 생각이 강했습니다. 거기에 Rx는 개념적인 부분이 강하다 보니 특정 언어를 하는 것이 아닌 Rx라는 새로운 언어를 하는 느낌이 가끔씩 들기도 했습니다.


이렇게 Rx에 대해 알아보았습니다. Rx의 개념에 대해 설명한 거고, Observable, Single, Subject, Relay, Operator 같은 여러 세부적인 부분은 차차 포스팅해 보겠습니다.

'CS 지식' 카테고리의 다른 글

OOP에 대해 알아보자  (0) 2023.02.08