티스토리 뷰

Language/TypeScript

[TypeScript] Promise

뱃싸공 2023. 3. 14. 15:58
Promise의 목적

Promise는 JavaScript를 사용하면 마주치게 되는 콜백지옥 문제를 해결하기 위해 등장했다.
Promise는 비동기 연산이 종료된 이후, 연산의 결과 값이나 실패에 대한 처리기를 연결할 수 있는데, 비동기 메서드가 마치 동기 메서드처럼 값을 반환하는 것처럼 사용할 수 있다. 다만 최종 결과를 반환하는 것이 아니고, 미래의 어떤 시점에 결과를 제공하겠다는 '약속'을 하는 것처럼 사용한다. 

async function calculate(flag: boolean, successCallback: any, failureCallback: any) {
    if (flag) {
        successCallback();
    } else {
        failureCallback();
    }
}

function successCallback() {
    console.log("SUCCESS!!");
}

function failureCallback() {
    console.log("FAIL!!");
}

calculate(true, successCallback, failureCallback);

예를 들어 위와 같이 비동기로 연산을 수행하는 calculate 메서드가 있다고 가정해 보자.
이 함수는 flag라는 값을 넘겨받고, 두 가지 콜백 함수를 넘겨받는다. 하나는 flag가 true일 때 수행되는 successCallback 메서드고, 다른 하나는 flag가 false일 때 수행되는 failureCallback 함수이다.

예시로 사용한 코드는 굉장히 짧기에 큰 문제가 없어 보이지만, 실제 비즈니스 로직을 작성할 때는 이 콜백 depth가 매우 길어질 수 있다. 그리고 이를 흔히 '콜백 지옥'이라고 부른다.

Modern JavaScript 함수들은 위와 같이 콜백들을 전달하지 않고, 콜백을 붙여 사용할 수 있게 해주는 Promise를 지원한다. 예를 들어 위의 calculate 메서드가 Promise를 반환하도록 수정한다면, 아래와 같이 간단하게 콜백 함수들을 사용할 수 있게 된다.

const calculate = (flag: boolean) => new Promise<void>((resolve, reject) => {
    if (flag) {
        resolve();
    } else {
        reject();
    }
})

function successCallback() {
    console.log("SUCCESS!!");
}

function failureCallback() {
    console.log("FAIL!!");
}

calculate(true)
.then(successCallback)
.catch(failureCallback);

이 코드를 통해, Promise의 상태는 아래의 3가지로 구성된다는 것을 쉽게 알 수 있다.

  • 대기(pending): 이행하지도, 거부하지도 않은 초기 상태.
  • 이행(fulfilled): 연산이 성공적으로 완료됨.
  • 거부(rejected): 연산이 실패함.

그리고 콜백 함수를 전달해 주는 고전적인 방식과는 달리, Promise는 아래와 같은 장점을 제공한다.

  • 콜백은 자바스크립트 Event Loop가 현재 실행 중인 콜 스택을 완료하기 이전에는 절대 호출되지 않는다.
  • then()을 여러 개 사용하여, 여러 콜백을 추가할 수 있다. 그리고 각각의 콜백은 주어진 순서대로 하나하나 실행한다.
  • chaining
Chaining

Chaining은 Promise의 가장 큰 장점 중 하나이다.
JavaScript를 사용하면 두 개 이상의 비동기 작업을 순차적으로 실행해야 하는 상황이 흔히 발생하는데, 이러한 상황은 각각의 작업이 이전 단계의 비동기 작업이 성공하고 나서, 그다음 비동기 작업을 수행해야 하는 상황을 말한다. promise chaining을 사용하면 이러한 상황을 아주 쉽게 대처할 수 있게 된다.

우선 Promise를 사용하지 않는 고전 JavaScript 코드를 사용해 보면 아래와 같은 '콜백 피라미드'가 만들어진다.

doSomething(function(result) {
  doSomethingElse(result, function(newResult) {
    doThirdThing(newResult, function(finalResult) {
      console.log('Got the final result: ' + finalResult);
    }, failureCallback);
  }, failureCallback);
}, failureCallback);

콜백 함수가 추가될수록 depth가 깊어질 수밖에 없는 구조이다. 여기서 Promise chaining을 사용하면 아래와 같이 개선할 수 있다.

doSomething()
.then(result => doSomethingElse(result))
.then(newResult => doThirdThing(newResult))
.then(finalResult => {
  console.log(`Got the final result: ${finalResult}`);
})
.catch(failureCallback);
Error Propagation

위의 코드를 보면,  failureCallback이 3번 사용된 것을 볼 수 있다. 반면 Promise chaining을 사용하면 단 한 번만 발생하는 것을 볼 수 있다. 이것이 가능한 이유는, 기본적으로 promise chain에서 예외가 발생하면 멈추고, chain의 아래에서 catch를 찾는 방식으로 동작하기 때문이다.

Ref : 

 

JavaScript | MDN

JavaScript (JS)는 가벼운, 인터프리터 혹은 just-in-time 컴파일 프로그래밍 언어로, 일급 함수를 지원합니다. 웹 페이지를 위한 스크립트 언어로 잘 알려져 있지만, Node.js, Apache CouchDB, Adobe Acrobat처럼

developer.mozilla.org

 

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/01   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함