본문 바로가기

개발 공부

Promise 와 Observable

여러 비동기 작업을 동시에 처리하기 위해 PromiseObservable을 많이 사용합니다.

 

Promise

Promise는 비동기 작업을 수행한 후, 작업의 완료 여부(성공 또는 실패)에 따라 결과를 반환하는 객체입니다.

이를 통해 비동기 작업의 결과를 처리하거나 오류를 쉽게 관리할 수 있습니다.

Promise의 구조와 동작 원리

Promise는 pending (대기), fulfilled (성공), rejected (실패)라는 세 가지 상태를 갖습니다.

  • pending: 비동기 작업이 아직 완료되지 않은 상태
  • fulfilled: 작업이 성공적으로 완료된 상태로, 결과 값이 제공됨
  • rejected: 작업이 실패한 상태로, 오류가 발생함
function fetchData(url: string): Promise<string> {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      if (url === "https://api.example.com/data") {
        resolve("Data fetched successfully!");
      } else {
        reject("Invalid URL");
      }
    }, 1000);
  });
}

// 사용 예시
fetchData("https://api.example.com/data")
  .then((data) => {
    console.log("Success:", data);
  })
  .catch((error) => {
    console.error("Error:", error);
  });

 

fetchData 함수가 주어진 URL에 따라 데이터를 가져옵니다.

올바른 URL이 제공되면 데이터를 성공적으로 반환하고(resolve), 그렇지 않으면 오류를 반환합니다(reject)

 

 


 

Observable

ObservableRxJS(Reactive Extensions for JavaScript) 라이브러리를 통해 제공되며, 다수의 값을 연속적으로 전달할 수 있는 비동기 처리 방법입니다.

Observables는 단일 이벤트뿐만 아니라 여러 이벤트를 시간에 따라 스트림 형태로 처리할 때 유용합니다.

Observable의 구조와 동작 원리

Observable은 ObserverSubscriber 개념을 통해 작동합니다.

subscribe 메서드를 호출하면 데이터를 구독(관찰)할 수 있고, 필요에 따라 데이터를 중단할 수도 있습니다.

 

import { Observable } from "rxjs";

const observable = new Observable<string>((subscriber) => {
  subscriber.next("First data");
  setTimeout(() => subscriber.next("Second data"), 1000);
  setTimeout(() => subscriber.next("Third data"), 2000);
  setTimeout(() => subscriber.complete(), 3000);
});

// 구독 예시
observable.subscribe({
  next: (data) => console.log("Received:", data),
  complete: () => console.log("Stream completed"),
});

 

  • next 콜백은 Observable이 새로운 데이터를 발행할 때마다 호출됩니다.
  • 매번 Observable에서 값을 발행할 때마다 next 콜백으로 전달되므로, 이 데이터를 실시간으로 처리할 수 있습니다.
  • 여기서 data는 발행된 데이터 값이며, console.log("Received:", data)는 이를 콘솔에 출력하는 역할을 합니다.

예를 들어, 버튼 클릭 이벤트를 Observable로 설정한 경우, 사용자가 버튼을 누를 때마다 next 콜백이 실행되어 클릭 수를 기록하거나, 클릭에 따라 변하는 화면을 업데이트할 수 있습니다.

 

  • complete 콜백은 Observable이 더 이상 데이터를 발행하지 않을 때 실행됩니다.
  • Observable 스트림이 완전히 종료되었음을 알려주므로, 이를 통해 구독 종료 이후의 작업을 정의할 수 있습니다.
  • 여기서는 console.log("Stream completed")가 호출되며, 데이터를 모두 수신한 뒤 마무리 작업으로 사용될 수 있습니다.

예를 들어, 서버로부터 실시간 데이터 스트림을 받다가 더 이상 데이터가 없거나 서버가 연결을 끊었을 때, complete 콜백을 사용하여 구독을 종료하고 마지막 정리 작업을 수행할 수 있습니다.

 

주어진 코드에서 Observable이 데이터를 발행하고, 구독자가 이를 수신하는 순서는 아래와 같습니다:

  1. 즉시: subscriber.next("First data")가 실행되어 **"First data"**가 발행됩니다.
  2. 1초 후: setTimeout에 의해 1초 후 subscriber.next("Second data")가 실행되어 **"Second data"**가 발행됩니다.
  3. 2초 후: 또 다른 setTimeout에 의해 2초 후 subscriber.next("Third data")가 실행되어 **"Third data"**가 발행됩니다.
  4. 3초 후: 마지막 setTimeout에 의해 3초 후 subscriber.complete()가 실행되어 스트림이 종료됩니다.

Promise와 Observable을 함께 사용하기

import { from, Observable } from "rxjs";

function fetchWithPromise(url: string): Promise<string> {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve(`Data from ${url}`);
    }, 1000);
  });
}

// Promise를 Observable로 변환하기
const observableFromPromise: Observable<string> = from(fetchWithPromise("https://api.example.com"));

// 구독
observableFromPromise.subscribe({
  next: (data) => console.log("Observable from Promise:", data),
  complete: () => console.log("Observable completed"),
});

 

  • from 연산자를 통해 Promise를 Observable로 변환해 다양한 비동기 처리 방식의 결합이 가능합니다.
  • from 연산자는 RxJS에서 제공하는 유틸리티 함수로, Promise와 같은 여러 유형의 데이터 소스를 Observable로 변환하는 기능을 제공합니다.
  • 이렇게 변환된 Observable은 구독할 수 있는 형태로, 데이터를 발행하고 완료 이벤트를 처리할 수 있습니다.
  • 이 코드에서 from을 사용해 Promise를 Observable로 변환하여 구독하게 되면, Promise의 결과가 next 콜백에 전달되며, 이후에는 complete 콜백이 자동으로 호출되어 Observable이 종료됩니다.