[JavaScript] RxJS(Reactive Extensions For JavaScript)란?

어느 개발자·2021년 4월 1일
0

JavaScript

목록 보기
3/3
post-thumbnail

RxJS란?

RxJS는 Reactive Extensions For JavaScript 라이브러리이다.
Reactive Extensions는 ReactiveX 프로젝트에서 출발한 리액티브 프로그래밍을 지원하기 위해 확장했다는 뜻이다.
ReactiveX는 Observer 패턴, Iterator 패턴, 함수형 프로그래밍을 조합하여 제공한다.
RxJS는 이벤트 스트림을 Observable이라는 객체로 표현한 후 비동기 이벤트 기반의 프로그램 작성을 돕는다.
이벤트 처리를 위한 API로 다양한 연산자를 제공하는 함수형 프로그래밍 기법도 도입되어 있다.

RxJS 퀵 스타트 책에서는 RxJS를 다음과 같이 소개하고 있다.

RxJS is a library for composing asynchronous and event-based programs by using observable sequences.
(RxJS는 Observable을 사용하여 비동기 및 이벤트 기반 프로그램을 작성하기 위한 라이브러리이다.)

Reactive Programming이란?

그렇다면 리액티브 프로그래밍이란 무엇일까?
리액티브 프로그래밍이란 이벤트나 배열 같은 데이터 스트림을 비동기로 처리해 변화에 유연하게 반응하는 프로그래밍 패러다임이다.

외부와 통신하는 방식은 Pull과 Push 시나리오가 있는데, 리액티브 프로그래밍은 Push 시나리오를 채택하고 있다.

Pull 시나리오

외부에서 명령하여 응답받고 처리한다.
데이터를 가지고 오기 위해서는 계속 호출해야 한다.

Push 시나리오

외부에서 명령하고 기다리지 않고, 응답이 오면 그때 반응하여 처리한다.
데이터를 가지고 오기 위해서 구독해야 한다.

비동기 이벤트 예시

대표적인 비동기 이벤트인 클릭 이벤트를 살펴보자.

function someEvent() {...}

const el = document.getElementById('Button');
el.addEventListener('click', someEvent)

targetElement를 가져와서 addEventListenr로 'click' 이벤트를 구독하였다.
사용자가 마우스를 클릭하지 전까지는 event function이 발생되지 않는다.
이러한 방식이 리액티브 프로그래밍의 개념 중 하나인 Observer Pattern이다.

Observer Pattern은 객체의 상태 변화를 관찰하는 옵저버들의 목록을 객체에 등록하여 상태 변화가 있을 때마다 메서드 등을 통해 객체가 직접 목록의 각 옵저버에게 통지하도록 하는 디자인 패턴이다.

서론이 길었지만, RxJS를 정리하자면

비동기 코드가 많아지면 그 만큼 제어의 흐름이 복잡하게 얽혀 코드를 예측하기 어려워진다.

RxJS는 비동기 프로그래밍의 문제를 해결하는데 도움을 주는 라이브러리이다.
RxJS는 Observer 패턴을 적용한 Observable 이라는 객체를 중심으로 동작한다.

RxJS Obersvable

Observable은 특정 객체를 관찰하는 Observer에게 여러 이벤트나 값을 보내는 역할을 한다.

Observable.create(
  (observer) => {
    try {
      observer.next('item');
    } catch (error) {
      observer.error(error);
    } finally {
      observer.complete();
    }
  }).subscribe(
    (x) => console.log(x),
    (error) => console.error(error),
    () => console.log('complete')
)

observer에는 3가지 메서드가 존재한다.

1. next : Observable 구독자에게 데이터를 전달한다.
2. complete : Observable 구독자에게 완료되었음을 알린다. next는 더 이상 데이터를 전달하지 않는다.
3. error : Observable 구독자에게 에러를 전달한다. 이후에 next 및 complete 이벤트가 발생하지 않는다.

RxJS Observable 라이프 사이클

1. 생성

Observable.create()

생성 시점에는 어떠한 이벤트도 발생되지 않는다.
2. 구독

Observable.subscribe()

구독 시점에 이벤트를 구독할 수 있다.
3. 실행

observer.next()

실행 시점에 이번트를 구독하고 있는 대상에게 값을 전달한다.
4. 구독 해제

observer.complete()
Observable.unsubscribe()

구독 해제 시점에 구독하고 있는 모든 대상의 구독을 종료한다.

RxJS Subject

RxJS에서는 Subject를 지원한다.
Subject는 많은 Observer에게 값을 다중 캐스트 할 수 있는 Observable의 특별한 유형 중 하나이다.

  • Observable : 유니 캐스트, Observer가 각각 독립적으로 실행되는 Observable을 가짐 
  • Subject : 다중 캐스트

Subject는 여러 Observer에서 구독이 가능하며, Subject에서 전달하는 값을 Observer들이 전달받는다.

const subject = new Subject();

subject.subscribe(
  (item) => console.log('a', item),
  (err) => console.error(err),
  () => console.log('a complete')
);

subject.subscribe(
  (item) => console.log('b', item),
  (err) => console.error(err),
  () => console.log('b complete')
);

subject.next('item');
subject.complete();

// 실행 결과
// -----------
// a item
// b item
// a complete
// b complete

RxJS Scheduler

RxJS는 Scheduler를 지원한다.
자바스크립트는 싱글 스레드, 이벤트 루프로 동작하기 때문에 RxJS에서의 Scheduler는 이벤트 루프에 어떤 순서로 처리될 지 구현되었다.

스케줄러에는 3가지 종류가 존재한다.

  1. AsyncScheduler
    setTimeout과 비슷하다.
asyncScheduler.schedule(() => console.log('async'), 2000);
  1. AsapScheduler
    다음 이벤트 루프에 실행
asapScheduler.schedule(() => console.log('asap'));
  1. QueueScheduler
    스케줄러에 전달된 state를 처리한다.
queueScheduler.schedule(function(x) {
  if (state) {
    this.schedule(state-1);
  }
  console.log(state);
}, 0, 3);

// 실행 결과
// -----------
// 3
// 2
// 1
// 0

Example

1부터 10까지 수에서 짝수를 구하여 1을 더하라.

range(1, 10).pipe(
  tap(
    (x) => console.log('tap: ' + x),
    (err) => console.error(err),
    () => console.log('tap complete')
  ),
  filter(x => !(x % 2)),
  map(x => x + 1)
).subscribe(
  (x) => console.log('subscribe: ' + x),
  (err) => console.error(err),
  () => console.log('complete')
);

// 실행 결과
// -------------
// tap:1
// tap:2
// subscribe:3
// tap:3
// tap:4
// subscribe:5
// tap:5
// tap:6
// subscribe:7
// tap:7
// tap:8
// subscribe:9
// tap:9
// tap:10
// subscribe:11
// tap complete
// complete
  1. tap에서는 값을 읽기만 하고 변경 없이 그대로 보낸다.
  2. filter로 짝수를 거른다.
  3. map으로 누적 합을 구한다.
  4. 위의 과정을 모두 거친 값만 subscribe에 잡힌다.

0개의 댓글