본문 바로가기
쿤즈 Dev/JS HTML CSS

[Javascript] 프로미스(Promise) 비동기 함수 사용 방법

by :)Koon 2021. 5. 28.

지난 포스팅들에서는 비동기의 작동 방법과 대표적인 함수인 setTimeout() 함수, 그리고 콜백 함수를 사용하는 방법까지 알아보았습니다.

2021.05.23 - [쿤즈 Dev/JS HTML CSS] - [Javascript] 비동기(Asynchronous) 사용해보기

2021.05.26 - [쿤즈 Dev/JS HTML CSS] - [Javascript] 콜백 (Callback) 함수 사용 방법

비동기와 콜백의 개념과 사용을 알고 있어야만 이번 포스팅에서 진행할 프로미스(Promise)에 대해서 이해하실 수 있습니다.

이번 포스팅에서는 프로미스(Promise)를 사용하는 방법에 대해서 알아보도록 하겠습니다.


 

프로미스(Promise)란 무엇인가

프로미스는 비동기 함수를 보다 편리하게 다룰 수 있는 Object입니다. 비동기 연상의 종료된 이후에 성공 혹은 실패를 손쉽게 처리하고 연결할 수 있습니다.

 

비동기 함수를 사용하는 것이 어려운 이유는 바로 콜백 때문입니다. 콜백이 많아지면 많아질수록 관리가 어려워질 수 있습니다. 하지만 프로미스는 비동기를 동기처럼 구현해서 사용할 수 있다는 장점이 있습니다.

 

프로미스(Promise)는 아래 세 가지 상태를 가지게 됩니다.

  • Pending: 계속 진행하거나 거부되지 않은 초기 상태
  • Fulfilled: 정상적으로 성공함
  • Rejected: 실패함

프로미스가 실행되고 나면 fullfiled 혹은 rejected 상태를 반환합니다. 이에 따라서 then() 함수를 실행하든, catch() 함수를 실행할 수 있습니다.

 

Promise의 프로토타입을 보면 Promise.prototype.then(), Promise.prototype.catch() 함수가 있습니다. 또 이 함수의 반환 값은 다시 프로미스이므로 계속적인 연결이 가능합니다.

 

역시 소스코드로 보고 진행을 해야 이해가 더 쉽기 때문에 간단하게 소스코드를 짜보겠습니다.


프로미스(Promise) 사용 방법

프로미스를 사용하기 위해서는 new 연산자를 이용해서 Promise Object를 생성해 줍니다. 이렇게 생성된 프로미스를 실행할 때에는 다음 세 가지로 결과를 실행할 수 있습니다.

  • then(): resolved handler callback
  • catch(): rejection handler callback
  • finally(): handler to the promise

then()의 경우는 resolve()로 반환된 값을 가져올 수 있습니다.

catch()는 reject()로 반환된 값을 가져올 수 있습니다.

finally()는 반환과 상관 없이 항상 마지막에 실행하는 함수입니다.

const addFunc = new Promise((resolve, reject) => {
    const ret = 1 + 1;
    if (ret == 2) {
        resolve('Success');
    } else {
        reject('Failed');
    }
});

addFunc
    .then(ret => {
        console.log('then ' + ret);
    })
    .catch(ret => {
        console.log('catch ' + ret);
    })
    .finally(() => {
        console.log('finally');
    })

Promise의 콜백으로 받을 함수의 parameter는 2개, resolve와 reject입니다. 만약 내부 로직이 성공하면 resolve() 함수에 parameter를 넘겨주시면 되고, 실패라면 reject() 함수에 parameter를 넘겨주시면 됩니다.

 

마지막으로 프로미스 함수로 만든 addFunc를 실행할 때에는 .then() 혹은 .catch()로 값을 받고 이때 넘어오는 값은 parameter 1개로만 사용할 수 있습니다.

 

그럼 조금 더 복잡한 함수를 프로미스 함수로 만들어 보겠습니다.

const testOdd = true;
const testEven = true;

const complexCallback = (callback, error) => {
    if (!testOdd) {
        error({
            testOdd: testOdd            
        })
    } else if (!testEven) {
        error({
            testEven: testEven
        })
    } else {
        callback('Success');
    }
}

complexCallback((result) => {
    console.log(result);
}, (error) => {
    console.log(error);
})

위 함수는 parameter를 2개 받습니다. callback 함수와 error입니다. 내부에서는 testOdd와 testEven 두 값 모두 true여야만 Sucess를 내보내는 함수를 만들었습니다.

 

이제 이 함수를 Promise 함수로 바꿔보겠습니다.

const testOdd = true;
const testEven = false;

const complexPromise = () => {
    return new Promise((resolve, reject) => {
        if (!testOdd) {
            reject({
                testOdd: testOdd            
            })
        } else if (!testEven) {
            reject({
                testEven: testEven
            })
        } else {
            resolve('Success');
        }
    });
}

complexPromise()
    .then(result => console.log(result))
    .catch(error => console.log(error));

함수 내부에서 new 연산자를 이용해서 프로미스를 return 값으로 만들어 주시면 됩니다. 그리고 성공일 때는 resolve() 함수를, 실패일 때는 reject() 함수를 이용해서 반환하면 프로미스 함수로 이용할 수 있습니다.

 

이렇게 프로미스 함수로 만든 이후에 사용할 때에는 .then() 또는 .catch()를 이용해서 반환된 값을 이용할 수 있습니다.


프로미스(Promise) 연결

프로미스는 여러 가지 함수들이 존재합니다. 이러한 함수들 중에서 프로미스를 여러 개 넣는 함수들을 보도록 하겠습니다.


Promise.all([ ... ])

첫 번째로 all() 함수입니다. 이 함수는 프로미스를 배열로 받습니다. 이렇게 받아서 함수를 실행하면 배열에 담긴 여러 개의 프로미스가 모두 종료될 때까지 기다렸다가 한꺼번에 다시 배열로 리턴값을 줍니다.

const promise1 = new Promise((resolve, reject) => {
    setTimeout(()=>resolve('promise1'), 3000); // 3s delay
})

const promise2 = new Promise((resolve, reject) => {
    resolve('promise2');
})

const promise3 = new Promise((resolve, reject) => {
    resolve('promise3');
})

Promise.all([
    promise1,
    promise2,
    promise3
]).then(result => {
    console.log(result);
})

이 경우에 결과는 3초의 시간이 걸립니다. 이유는 첫 번째 프로미스 때문인데요. 모든 프로미스가 종료될때까지 기다렸다가 결과를 배열로 반환합니다.

["promise1", "promise2", "promise3"]

Promise.race([ ... ])

프로미스의 race 함수는 말 그대로 레이스입니다. 여러 개의 배열로 넘어온 프로미스중 가장 먼저 끝난 프로미스의 결과만 반환합니다.

const promise1 = new Promise((resolve, reject) => {
    setTimeout(()=>resolve('promise1'), 3000);
})

const promise2 = new Promise((resolve, reject) => {
    setTimeout(()=>resolve('promise2'), 1000);
})

const promise3 = new Promise((resolve, reject) => {
    resolve('promise3');
})

Promise.race([
    promise1,
    promise2,
    promise3
]).then(result => {
    console.log(result);
})

동일한 예제에서 all() 함수에서 race() 함수로 바꿨습니다. promise1은 3초, promise2는 1초의 시간을 줬을 때, 결과는 promise3가 나오게 됩니다.


이번 포스팅에서는 프로미스(Promise)에 대해서 알아보았습니다. 비동기 함수를 접근하는 자체가 어렵기 때문에 프로미스부터 이해하기는 쉽지 않습니다. 다만 비동기를 이해하고 나면 프로미스의 사용은 정말 쉽습니다. 도움이 되셨으면 합니다. 이상입니다.

 

2021.05.23 - [쿤즈 Dev/JS HTML CSS] - [Javascript] 비동기(Asynchronous) 사용해보기

2021.05.26 - [쿤즈 Dev/JS HTML CSS] - [Javascript] 콜백 (Callback) 함수 사용 방법

 

댓글