Angular 4 프로젝트에서 RxJS Observable 실전 활용

배경

Angular 2에서 4로 업그레이드하면서 HTTP 서비스가 전면 Observable 기반으로 변경되었다. 기존 AngularJS에서 Promise를 주로 사용했던 팀원들이 어려워해서 실무 패턴을 정리했다.

기본 HTTP 요청

import { Injectable } from '@angular/core';
import { Http } from '@angular/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';

@Injectable()
export class UserService {
  constructor(private http: Http) {}

  getUsers(): Observable<User[]> {
    return this.http.get('/api/users')
      .map(res => res.json())
      .catch(this.handleError);
  }

  private handleError(error: any): Observable<any> {
    console.error('에러 발생:', error);
    return Observable.throw(error);
  }
}

자주 사용하는 패턴

1. 검색 디바운싱

사용자 입력마다 API를 호출하지 않고 300ms 대기 후 요청한다.

import 'rxjs/add/operator/debounceTime';
import 'rxjs/add/operator/distinctUntilChanged';
import 'rxjs/add/operator/switchMap';

this.searchTerm
  .debounceTime(300)
  .distinctUntilChanged()
  .switchMap(term => this.searchService.search(term))
  .subscribe(results => this.results = results);

2. 병렬 요청 처리

import 'rxjs/add/observable/forkJoin';

Observable.forkJoin(
  this.userService.getUser(id),
  this.orderService.getOrders(id)
).subscribe(([user, orders]) => {
  this.user = user;
  this.orders = orders;
});

마이그레이션 팁

Promise의 .then().subscribe()로, .catch()는 두 번째 파라미터나 .catch() 오퍼레이터로 처리한다. 중요한 차이는 Observable은 lazy하다는 점이다. subscribe를 호출하기 전까지 실제로 실행되지 않는다.

팀 내부적으로 Observable을 Promise로 변환하는 .toPromise() 사용은 지양하기로 했다. 결국 RxJS를 제대로 익히는 게 장기적으로 유리하다.