2부 Chapter 01. RxJS란 무엇인가?
1.1. RxJS란?
RxJS는 Observable을 사용하여 비동기 및 이벤트 기반 프로그램을 작성하기 위한 라이브러리
- 비동기 컬렉션 데이터를 다루는 라이브러리
1.2. RxJS 시작하기
1.2.1. RxJS 첫 번째 예제
- 페이지를 클릭했을 경우 event.currentTarget 정보를 콘솔로 출력
const eventHander = event => {
console.log(event.currentTarget);
};
document.addEventListener('click', eventHander);
- 이벤트 핸들러를 만들고
-
핸들러를 addEventListener를 통해 등록
- 동일한 기능을 RxJS로 작성
- 이벤트를 Observable로 변환하는 fromEvent 함수를 제공
- Observable의 subscribe 메소드를 이용하면 observer가 Observable을 구독할 수 있음
- Observable에서 전달된 데이터를 observer가 소비
const { fromEvent } = rxjs;
const click$ = fromEvent(document, 'click') // Observable
const observer = event => {
console.log(event.currentTarget);
};
click$.subscribe(observer);
- 이벤트 핸들러 -> observer
- addEventListener -> subscribe
-
이벤트 정보를 Observable로 변환하는 작업이 추가 됨
- RxJS는 다양한 모듈 타입에서 사용이 가능 - 자세히보기
1.2.2. RxJS 첫번째 예제 개선하기
- 실제 우리가 필요한 정보는 click이 아니라 click 될 때의 currentTarget 정보
- pluck 오퍼레이터를 이용하면 이 의도를 더욱 코드에 명확히 나타낼 수 있음
pluck(properties:…string):Observable
pluck은 사전적으로 ‘~을 뽑다’라는 의미
추출할 속성들을 문자열로 지정
- RxJS에서 오퍼레이터를 적용하기 위해서는 반드시 pipe 오퍼레이터를 통해 적용
- pipe 오퍼레이터는 파라미터로 전달된 오퍼레이터들이 적용된 새로운 Observable 인스턴스를 반환
pipe(operations:…):Observable
RxJS 5.5 부터 적용된 오퍼레이터, 처리해야 할 작업(operator)들을 순차적으로 받아서 처리
5.5까지는 도트 체이닝을 사용 했으나 6.0 부터는 pipe 오퍼레이터만 제공
오퍼레이터를 적용하기 위해서는 반드시 pipe 오퍼레이터를 사용
6.0에서 도트 체이닝을 사용하려면 rxjs-compat 모듈을 추가로 사용
// 도트체이닝 방식
ajax$
.switchMap(data => ...)
.filter(user => ...)
.map(user => ...);
// pipe 오퍼레이터
ajax$
.pipe(
switchMap(data => ...),
filter(user => ...),
map(user => ...)
);
- 다음 코드는 pluck 오퍼레이터를 사용하여 코드의 의도를 더욱 분명하게 변경한 예
const { fromEvent } = rxjs;
const { pluck } = rxjs.operators;
const currentTarget$ = fromEvent(document, 'click')
.pipe(
pluck('currentTarget')
); // Observable
const observer = currentTarget => {
console.log(currentTarget);
};
currentTarget$.subscribe(observer);
- click이 발생하면 currentTarget$은 event 객체의 currentTarget을 전달
- observer는 currentTarget$을 구독함으로서 currentTarget 데이터를 전달 받음
1.2.3. RxJS 두 번째 예제
- 동기적인 작업을 RxJS로 구현
- 사용자 정보 배열에서 촉나라 사람만 추출
- array의 filter 메소드를 통해 원하는 사용자만 추출
const users = [
{
name: '유비',
birthYear: 161,
nationality: '촉'
},
{
name: '손권',
birthYear: 182,
nationality: '오'
},
{
name: '관우',
birthYear: 160,
nationality: '촉'
},
{
name: '장비',
birthYear: 168,
nationality: '촉'
},
{
name: '조조',
birthYear: 155,
nationality: '위'
},
{
name: '손권',
birthYear: 182,
nationality: '오'
}
].filter(user => user.nationality == '촉');
const log = user => console.log(user);
users.forEach(log);
- 동일한 기능을 RxJS로 작성
- Array -> from 메소드
const { from } = rxjs;
const { filter } = rxjs.operators;
const users$ = from([
{
name: '유비',
birthYear: 161,
nationality: '촉'
},
{
name: '손권',
birthYear: 182,
nationality: '오'
},
{
name: '관우',
birthYear: 160,
nationality: '촉'
},
{
name: '장비',
birthYear: 168,
nationality: '촉'
},
{
name: '조조',
birthYear: 155,
nationality: '위'
},
{
name: '손권',
birthYear: 182,
nationality: '오'
}
]).pipe(
filter(user => user.nationality == '촉')
);
const observer = user => console.log(user);
users$.subscribe(observer);
- log -> observer
- forEach -> subscribe
- Array 객체를 Observable로 변환, pipe를 이용하여 filter 오퍼레이터를 적용
1.3. RxJS 4대 천왕
RxJS의 중요 개념
- Observable
- 오퍼레이터
- Observer
- Subscription
- Subject
- Scheduler
이 장에서는 중요한 4가지, Observable / 오퍼레이터 / Observer / Subscription 개념을 집중적으로 살펴 봄
1.3.1. Observable
- 시간을 축으로 연속적인 데이터를 저장하는 컬렉션을 표현한 객체
- Observable은 데이터를 제공하는 소스를 Observer에게 전달 - 스트림
1.3.2. 오퍼레이터
- Observable을 생성 및 조작하는 함수
- Observable을 생성하기도 하고 연결하기도 하며 분리하거나 합치기도 함
- 오퍼레이터는 현재의 Observable 인스턴스를 기반으로 항상 새로운 Observable 인스턴스를 반환
1.3.3. Observer
- Observable에 의해 전달된 데이터를 소비하는 주체
- Observer는 next, error, complete 함수 객체를 가르킴
- next : 데이터가 전달될 때 호출
- error : 에러가 발생했을 때 호출
- complete : 데이터 전달이 완료됐을 때 호출
- subscribe 메소드를 통해 Observable과 연결
Observable.prototype.subscribe
subscribe는 Observer를 파라미터로 받음
- Observer 객체를 전달하는 subscribe 사용 예
const observer = {
next: x => console.log('Observer가 Observable로 부터 받은 데이터:' + x),
error: err => console.log('Observer가 Observable로 부터 받은 에러 데이터:' + err),
complete: () => console.log('Observer가 Observable로 부터 종료되었다는 알림을 받은 경우')
}
click$.subscribe(observer); // observer 객체를 파라미터로 받음
- next 콜백 함수를 전달하는 subscribe 사용 예
click$.subscribe(x => console.log('Observer가 Observable로 부터 받은 데이터:' + x));
- next, error, complete 콜백 함수를 전달하는 subscribe 사용 예
// observer의 next, error, complete 함수를 파라미터로 받음
click$.subscribe(
x => console.log('Observer가 Observable로 부터 받은 데이터:' + x),
err => console.log('Observer가 Observable로 부터 받은 에러 데이터:' + err),
() => console.log('Observer가 Observable로 부터 종료되었다는 알림을 받은 경우')
);
1.3.4. Subscription
- Observable.prototype.subscribe의 반환값
- 등록된 Observable의 데이터를 더이상 받고 싶지 않을 때는 unsubscribe 메소드를 호출하여 자원을 해제
// ...
const subscription = currentTarget$.subscribe(observer);
// unsubscribe으로 자원 해제가 가능
subscription.unsubscribe();
1.4. RxJS 개발 방법
예제를 RxJS의 4가지 개념으로 표현하면 다음과 같음
- 이벤트를 Observable로 변환
- pluck, fliter 오퍼레이터를 이용하여 데이터를 변경
- 데이터를 처리할 Observer를 만들고
- Observable의 subscribe 메소드를 통해 Observer를 등록
RxJS를 사용해서 개발할 경우의 프로세스
- 데이터 소스를 Observable로 변경
- 오퍼레이터를 통해 데이터를 병합, 추출, 분리, 나눔
- 원하는 데이터를 받아 처리하는 Observer를 만듬
- Observable의 subscribe를 통해 Observer를 등록
- Observable 구독을 정지하고 자원을 해지