Promise

프로미스는 자바스크립트 비동기 처리에서 사용되는 객체이다. 프로미스는 콜백 지옥을 해결하기 위하여 es6에 도입된 문법이다. 이제 천천히 프로미스에 대해 알아보자


콜백 지옥 vs 프로미스

프로미스가 나오기 이전에 우리는 비동기 처리를 순차적으로 처리하기 위하여 콜백을 사용하였다. 하지만 이것은 가독성이 떨어지는 문제가 있었고 어떤 함수가 먼저 실행되는지 한눈에 알아보기 힘들다는 점이 단점이였다. 이런 문제를 해결해주기 위하여 es6에서는 프로미스가 등장한 것이다.

다음은 프로미스와 콜백 지옥에 차이점을 코드로 표현한 것이다.

const arr = ['배가 고프다', '고기를 굽자', '쌈을 사먹자']

//콜백
const hungry = (x, callback) => {
    setTimeout(_ => {
        callback(arr[x])
    }, 1 * 1000)
}

hungry(0, result => {
    console.log(0, result)

    hungry(1, result => {
        console.log(1, result)

        hungry(2, result => {
            console.log(2, result)
        })
    })
})

//프로미스
const hungryP = (x) => {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve(arr[x])
        }, 1000)
    })
}

hungryP(0).then(result => {
    console.log(0, result)
    return hungryP(1)
}).then(result => {
    console.log(1, result)
    return hungryP(2)
}).then(result => {
    console.log(2, result)
})

결과는 두 개 모두 같게 나오지만 확실히 프로미스를 사용한 것이 가독성 측면에서 좋다는 것을 알 수 있다.


프로미스의 상태

이제 프로미스를 콜백 지옥을 탈출하기 위해서 사용한 다는 것은 이제 알겠는데 정확히 어떤 원리로 동작하는 궁금할 것이다. 프로미스 원리에 대하여 차근차근 알아보자

다음은 프로미스를 크게 세 부분으로 나누어 작성한 코드이다.

const funcP = (x) => {
    return new Promise((resolve, reject) => {
        if(x % 2 === 1) {
            reject(new Error('홀수를 입력 받음'))
        }
        resolve(x)
    })
}

funcP(2).then(x =>{
    console.log(x)
    return funcP(4)
}).then(x => {
    console.log(x)
    return funcP(6)
}).then(x =>{
    console.log(x)
    return funcP(7)
}).then(x => {
    console.log(x)
    return funcP(10)
}).catch(err => {
    console.error(err)
})

우선 프로미스의 구조는 크게 new Promise(), resolve, reject로 구분되어 있다. 프로미스는 함수를 실행하고 항상 Promise객체를 반환한다.

Promise객체를 반환하면 총 3가지 상태를 가질 수 있다.

  • 대기 : promise객체는 반환하는 즉시 대기 상태로 진입한다.

  • 이행 : resolve를 이용하여 대기 상태의 프로미스 객체를 다음 순서로 이행한다

  • 실패 : reject를 이용하여 대기 상태의 프로미스 객체를 에러 처리한다. catch로 에러를 잡자


여러 프로미스 한번에 실행하기

여러개의 비동기 작업을 존재하고 이들이 모두 완료된 후 작업을 진행하고 싶으면 Promise.all을 사용하면 된다.

다음은 Promise.all을 이용한 코드이다.

const promise1 = new Promise((resolve, reject) => {
    setTimeout(_ => {
        console.log('국밥을 먹습니다.')
        resolve('promise1')
    }, 3000)
})

const promise2 = new Promise((resolve, reject) => {
    setTimeout(_ => {
        console.log('치킨을 먹습니다.')
        resolve('promise2')
    }, 5000)
})

Promise.all([promise1, promise2]).then(values => {
    console.log('모두 완료', values)
})

최종적으로 Promise.all의 values는 배열이고 promise1과 promise2를 가지고 있다.

Last updated