본문 바로가기

Web + APP/Angular

RxJS가 해결하려고 했던 문제 1

반응형
SMALL

https://ggodong.tistory.com/281

 

RxJS를 시작하기 전에

안녕하세요. 꼬동입니다. Angular를 공부하다보면, 피할 수 없는 RxJS를 공부하고 있습니다. 뭐... Angular가 RxJS를 좋아한다고 했기 때문에, 공부를 하는 감도 있지만, 사실 fetch와 같은 메소드를 써도

ggodong.tistory.com

이 전 글에서 RxJS가 해결하려고 했던 문제를 3가지 말했습니다.

  1. 입력 오류
  2. 상태 오류
  3. 로직 오류

여기서 입력 문제를 RxJS는 어떻게 해결하려 했는지를 알아봅시다.


간단한 게시판 애플리케이션을 생각해보면, 아래와 같은 Data Flow를 상상할 수 있습니다.

  1. 목록화면과 조회화면은 서버로부터 데이터를 불러와 브라우저에 전달
  2. 브라우저에 전달된 정보를 브라우저의 UI 객체에 전달
  3. 편집화면은 브라우저 UI 객체를 통해 입력을 받고 이를 다시 UI 객체나 브라우저 객체로 전달
  4. 사용자가 작성한 정보를 브라우저 UI 객체나 브러우저 객체를 이용하여 서버로 전달

1, 2 과정에서 입력값은 서버로부터 전달받은 게시글 데이터가 됩니다.

 

두 과정의 입력값이 동일 할지라도 입력값을 받는 브라우저와 브라우저 UI 객체는 서로 다른 시점에 입력값을 전달받습니다.

 

1과정이 Ajax로 JSON 데이터를 받아와 브라우저의 객체로 저장하는 경우라면 비동기 호출로 데이터를 받기까지 시간이 걸립니다.

let result;
const xhr = new XMLHttpRequest();
xhr.onload = function(e) {
	result = JSON.parse(xhr.responseText);
}
xhr.open("GET", url);
xhr.send();

반면 브라우저 UI 객체는 이미 브라우저에 존재하는 JSON 데이터를 받기 때문에 동기 호출로 바로 결과 데이터를 얻을 수 있습니다.

Array.from(document.querySelectorAll("li")).forEach((v, i) => {
	v.innerText = result.list[i];
});

마찬가지로 3과 4의 과정도 입력값은 사용자의 입력이 되지만 전달된 입력값을 처리하는 시점은 상황에 따라 각각 다릅니다.

 

즉, 데이터가 동기방식, 비동기방식으로 불명확하게 전달되기 때문에 개발자가 잘 판단하에 코드를 작성해야합니다.

 

그렇다면 이 두 가지 방식을 함께 사용할 수밖에 없을까요?

 

RxJS는 여기에 대해 고민을 했습니다. 단, 하나의 방식으로 일원화를 했죠. 오류 발생 빈도를 낮추고, 생산성 향상에 도움을 줍니다.

 

RxJS의 두 차이를 시간이라는 개념을 도입함으로써 해결했습니다.

 

시간 축으로 따지고 봤을 땐, 이벤트와 동기 방식의 함수 호출도 전부 순서대로 이뤄지기 때문에, 시간을 인덱스를 둔 컬렉션으로 생각할 수 있으며, RxJS는 이를 스트림(stream)이라고 표현합니다.

시간을 인덱스로한 배열로 표현이 가능한 스트림(stream)

RxJS에서는 이런 스트림(stream)을 표현하는 Observable 클래스를 제공합니다.

Observable

Observable은 시간을 인덱스로 둔 컬렉션을 추상화한 클래스입니다. 동기나 비동기의 데이터를 하나의 컬렉션으로 바라볼 수 있게 해주죠.

 

그렇기 때문에 개발자는 어떤 형태로 전달되는지에 대한 고민을 할 필요가 없고, 단지, Observable을 통해 데이터를 받기만 하면 됩니다.

 

모든 데이터는 Observable 인스턴스로 만들 수 있습니다.

 

그렇기 때문에 키보드 입력 데이터, 마우스 데이터, Ajax / fetch 데이터 등 동기든 비동기든 모든 데이터 타입을 동일한 형태로 사용할 수 있습니다.

 

RxJS는 Observable을 만들기 위해 다양한 함수를 제공하는데, event의 경우엔 fromEvent

const { fromEvent } = rxjs;
const key$ = fromEvent(document, "keydown");
const click$ = fromEvent(document, "click");

배열 같은 iterable이나 array-like, Promise 데이터를 Observable로 만들 땐 from

const { from } = rxjs;
const arrayFrom$ = from([10, 20, 30]);
const iterableFrom$ = from(new Map([[1, 2], [2, 4], [4, 8]]));
const ajaxPromiseFrom$ = from(fetch("./api/some.json"));

단일 데이터를 연속으로 전달하는 경우엔 of를 이용합니다.

const { of } = rxjs;
const numberOf$ = of(10, 20, 30);
const stringOf$ = of("a", "b", "c");

여기까지 언급한 함수는 Observable 생성자를 이용하여 만든 팩토리 메소드입니다.

Observable 객체의 변수명은 관용적으로 접미서 $를 붙입니다.
Observable 객체는 스트림(stream)이기 때문에 Stream과 유사한 $를 사용합니다.

정리

웹 애플리케이션의 입력 데이터가 어떻게 전달되는지에 따라 개발을 해야하는 문제점이 존제했는데, RxJS는 이 문제를 시간을 인덱스로 둔 컬레션으로 추상화시킴으로써 하나의 스트림이라는 개념으로 접근할 수 있게 했습니다.

 

그 구현체가 바로 Observable 클래스이며, 모든 데이터를 표현할 수 있는 일원화된 데이터 구조입니다.

 

그렇기에 개발자는 더이상 어떤 형태로 데이터가 전달되어야 하는지를 고민할 필요가 없게되었습니다.


이상 RxJS가 해결하려고 했던 문제 1였습니다. ^_^

반응형
LIST