재우니의 블로그

Observable 개념 이해하기 - 비동기 데이터 다루기 & RxJS 기초 - 데이터 스트림과 구독하기 실습 (Angular 16 기준)

서론

Angular 16에서는 비동기 데이터 처리를 위해 Observable RxJS 라이브러리를 활용합니다. Observable은 비동기 데이터를 처리하는 강력한 도구로, 이벤트, HTTP 요청, 타이머 등에서 데이터를 스트림 형태로 전달받아 관리할 수 있게 합니다. 이번 글에서는 Observable의 개념을 이해하고, RxJS의 기초적인 사용법을 통해 Observable을 생성하고 구독하는 실습을 코드 위주로 상세히 알아보겠습니다.


본론

1. Observable이란 무엇인가?

Observable의 개념

Observable은 비동기적으로 발생하는 데이터 스트림을 다룰 수 있는 객체입니다. Observable은 데이터 스트림을 생성하여 시간이 지남에 따라 발생하는 여러 데이터를 한 번에 수신할 수 있도록 합니다. Observable의 장점은 구독(Subscribe)과 같은 방식을 통해 필요할 때만 데이터를 수신할 수 있다는 점입니다.

Observable의 기본 흐름

Observable은 보통 다음의 흐름을 가집니다:

  1. Observable 생성: Observable 객체를 생성하여 데이터 스트림을 정의합니다.
  2. 구독(Subscription): 구독자를 통해 Observable의 데이터를 수신하고 반응합니다.
  3. 데이터 스트림 전송: Observable이 데이터를 방출하면, 구독자가 이를 받아 처리합니다.
  4. 종료: 스트림이 완료되면 종료됩니다.

2. RxJS와 Observable 기초 실습

Angular에서 Observable을 활용하려면 RxJS 라이브러리의 Observable 클래스와 다양한 연산자를 사용합니다. 이번 실습에서는 Observable을 직접 생성하고 구독하여 데이터 스트림을 처리하는 과정을 실습해보겠습니다.

1) Observable 생성 및 구독 실습

먼저, Observable을 사용해 기본적인 데이터 스트림을 생성하고 구독해보겠습니다. 이를 위해 rxjs의 Observable 클래스를 임포트하여 숫자를 방출하는 간단한 Observable을 만들고, 이 Observable을 구독하여 데이터를 처리해보겠습니다.

Observable 생성 및 구독 코드 예제

// app.component.ts
import { Component, OnInit } from '@angular/core';
import { Observable, Subscription } from 'rxjs';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
  observableData: number[] = [];  // Observable로부터 받은 데이터를 저장
  subscription: Subscription | undefined;

  ngOnInit() {
    // Observable 생성: 1초마다 숫자를 방출
    const numberObservable = new Observable<number>((observer) => {
      let count = 1;
      const intervalId = setInterval(() => {
        observer.next(count++);  // 다음 숫자를 방출
      }, 1000);

      // Observable 종료 시 클린업
      return () => clearInterval(intervalId);
    });

    // Observable 구독
    this.subscription = numberObservable.subscribe({
      next: (value) => {
        this.observableData.push(value);
        console.log('수신된 데이터:', value);
      },
      error: (error) => console.error('오류 발생:', error),
      complete: () => console.log('Observable 완료')
    });
  }

  ngOnDestroy() {
    // 컴포넌트가 파괴될 때 구독 해제
    if (this.subscription) {
      this.subscription.unsubscribe();
      console.log('Observable 구독 해제');
    }
  }
}
  • Observable 생성: numberObservable은 1초마다 숫자를 방출하는 Observable입니다. observer.next(count++)를 사용해 카운트 값을 방출합니다.
  • 구독(Subscribe): numberObservable.subscribe를 통해 Observable을 구독하고, next 콜백으로 데이터를 수신하여 observableData 배열에 추가합니다.
  • 구독 해제(Unsubscribe): 컴포넌트가 파괴될 때 ngOnDestroy()에서 구독을 해제하여 메모리 누수를 방지합니다.

이 코드를 실행하면 1초마다 다음 숫자가 출력되고 observableData에 추가됩니다.

2) RxJS 연산자 사용하여 데이터 변환하기

RxJS에서는 연산자(Operators)를 통해 Observable 데이터를 가공할 수 있습니다. 이번에는 map 연산자를 사용하여 숫자를 방출하는 Observable의 데이터를 제곱한 값으로 변환하는 예제를 만들어보겠습니다.

RxJS 연산자 map 예제

// app.component.ts
import { Component, OnInit } from '@angular/core';
import { Observable, Subscription } from 'rxjs';
import { map } from 'rxjs/operators';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
  transformedData: number[] = [];
  subscription: Subscription | undefined;

  ngOnInit() {
    const numberObservable = new Observable<number>((observer) => {
      let count = 1;
      const intervalId = setInterval(() => {
        observer.next(count++);
      }, 1000);

      return () => clearInterval(intervalId);
    });

    // `map` 연산자를 사용해 데이터 변환
    const squaredObservable = numberObservable.pipe(
      map((value) => value * value)  // 값을 제곱하여 변환
    );

    // 변환된 Observable 구독
    this.subscription = squaredObservable.subscribe({
      next: (value) => {
        this.transformedData.push(value);
        console.log('제곱된 데이터:', value);
      },
      error: (error) => console.error('오류 발생:', error),
      complete: () => console.log('Observable 완료')
    });
  }

  ngOnDestroy() {
    if (this.subscription) {
      this.subscription.unsubscribe();
      console.log('Observable 구독 해제');
    }
  }
}
  • map 연산자: map 연산자는 방출된 값을 변환하며, 여기서는 숫자를 제곱하여 데이터를 가공합니다.
  • Observable 파이프라인: pipe 메서드를 사용해 연산자를 연결하여 데이터 스트림을 가공합니다.
  • 구독: 변환된 데이터가 transformedData 배열에 추가됩니다. 매 1초마다 숫자의 제곱이 출력됩니다.

3) from 연산자로 배열을 Observable로 변환하기

RxJS는 배열이나 객체를 Observable로 변환하는 from 연산자도 제공합니다. 이 연산자를 사용하여 배열을 Observable로 변환하고 데이터를 스트림으로 처리하는 방법을 살펴보겠습니다.

from 연산자 예제

// app.component.ts
import { Component, OnInit } from '@angular/core';
import { from, Subscription } from 'rxjs';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
  subscription: Subscription | undefined;

  ngOnInit() {
    const dataArray = [1, 2, 3, 4, 5];  // 배열 데이터
    const arrayObservable = from(dataArray);  // 배열을 Observable로 변환

    // Observable 구독
    this.subscription = arrayObservable.subscribe({
      next: (value) => console.log('배열 요소:', value),
      error: (error) => console.error('오류 발생:', error),
      complete: () => console.log('Observable 완료')
    });
  }

  ngOnDestroy() {
    if (this.subscription) {
      this.subscription.unsubscribe();
      console.log('Observable 구독 해제');
    }
  }
}
  • from 연산자: from(dataArray)는 배열 dataArray를 Observable로 변환하여 각 요소를 스트림으로 방출합니다.
  • 구독: Observable을 구독하여 배열의 각 요소가 개별적으로 출력됩니다.

이 코드 실행 시 [1, 2, 3, 4, 5] 배열의 각 요소가 순차적으로 출력됩니다.


결론

이번 글에서는 Angular 16에서 Observable의 개념 RxJS를 사용해 데이터를 스트림으로 처리하는 방법을 실습했습니다. Observable은 Angular에서 비동기 데이터를 다룰 때 중요한 개념으로, RxJS의 다양한 연산자를 활용해 데이터 가공과 비동기 처리를 유연하게 구성할 수 있습니다. 앞으로 RxJS 연산자를 활용해 더 복잡한 데이터 스트림을 효율적으로 관리해보세요.


Q&A 섹션

  • Q1: Observable과 Promise의 차이점은 무엇인가요?
    A1: Observable은 여러 값을 방출할 수 있는 반면, Promise는 단일 값만 반환합니다. 또한 Observable은 구독자가 필요할 때만 데이터를 요청할 수 있고, RxJS 연산자를 통해 다양한 비동기 로직을 처리할 수 있습니다.
  • **Q2: map 연산자는 주로 어떤 경우

에 사용되나요?**
A2: map 연산자는 데이터 스트림의 각 값을 변환할 때 사용되며, 데이터를 가공하여 특정 형식이나 값을 변경할 때 유용합니다.

  • Q3: Observable의 구독을 해제하지 않으면 어떤 문제가 발생하나요?
    A3: 구독을 해제하지 않으면 메모리 누수가 발생할 수 있습니다. 특히 컴포넌트가 파괴된 후에도 구독이 유지되면 불필요한 자원이 사용되므로 반드시 해제해야 합니다.

관련 태그

  • #angular-observable
  • #rxjs
  • #데이터-스트림
  • #비동기-데이터
  • #angular-16

이미지 프롬프트

  1. Observable 구독 코드 예제: Angular에서 생성한 Observable과 구독 예제.
  2. RxJS 연산자 사용 예제: map 연산자를 사용해 데이터 스트림을 가공하는 코드.
  3. 데이터 스트림 결과 화면: Observable의 데이터를 구독하여 화면에 출력하는 Angular 애플리케이션.