이미지09
Coding Story/JAVASCRIPT

[ JavaScript ] 자바스크립트 프로미스 Promise

반응형

 

 

프로미스(Promise)란?

JavaScript 에서 코드가 순차적으로 일어나는 처리를 동기 처리라 하며,

 

특정 코드가 처리될 때 까지 기다리지 않고 다음 코드를 먼저 처리하는 걸 비동기 처리라 한다.

 

이러한 비동기 처리에서 콜백 지옥(Callback Hell) 등의 문제를 해소하기 위해 사용하는 객체,

 

비동기 처리에서 순차적 처리를 행하기 위해 사용되는 객체가 프로미스(Promise)이다.

 

 

Promise 를 꼭 사용해야 하는가?

꼭 그런 건 아니다. 굳이 따지면 비동기 처리 때 Promise 를 사용하지 않는 사용자가 대부분일 것이다.

 

하지만 앞서 언급했 듯 비동기 처리순차적으로 처리하지 않는다는 특징이 있는데,

 

경우에 따라 비동기 처리를 사용함에도 이를 순차적으로 처리해주어야 할 때가 있다.

 

예를 들어 비동기 처리 A 가 성공했을 때 B 를 비동기 처리하고, B 가 성공하면 C 를 처리한다 가정할 때,

 

이렇게 순차적으로 비동기 함수를 호출해야하는 경우가 있을 때 아래와 같은 형태를 지니게 된다.

function test() {
    $.ajax({
        url: '...',
        data: '...,
        type: 'post',
        success: function(response) {
            $.ajax({
                url: '...',
                data: '...',
                type: 'post',
                success: function(response) {
                    $.ajax({
                        url: '...',
                        data: '...',
                        type: 'post',
                        success: function(response) {
                            //...
                        },
                        error: function(error) {
                        }
                    });
                },
                error: function(error) {
                }
            });
        },
        error: function(error) {
        }
    });
}
    

 

이는 error 를 관리하기 힘들 뿐더러 코드 가독성도 떨어지는 콜백 지옥(Callback Hell)에 빠지기 쉽상이다.

 

이럴 때 Promise 를 사용하면 보다 코드를 간결하게 만들어 주고 처리의 성공과 실패를 쉽게 관리할 수 있게 해준다.

 

이것이 Promise 를 비동기 처리에서 사용하는 이유인 것이다.

 

 

 

 

Promise 의 처리 상태 3 가지

지금 껏 말한 Promise 를 사용하기 위해선 3 가지 처리 상태를 숙지해야 한다.

 

Promise 는 Pending(대기), Fulfilled(이행), Rejected(실패) 처리 상태를 가지며  각 상태의 설명은 다음과 같다.

⊙ Pending(대기) : Promise 객체를 생성하고, 처리 성공 또는 처리 실패 이전까지의 미완료 상태
⊙ Fulfilled(이행) : 처리가 성공적으로 이루어져 Promise 결과 값을 return 해준 상태
⊙ Rejected(실패) : 처리가 실패해 오류가 발생한 상태

 

각 처리 상태에 대해 순서대로 살펴보자.

 

 

Pending(대기)

Promise 객체를 생성했고, 아직 성공이나 실패와 같은 처리 결과가 이루어지지 않은 진행 전 상태를 말한다.

 

new Promise( ) 로 Promise 객체를 생성하며 인자 값으로 콜백 함수를 넣는다.

 

이 때 콜백 함수는 처리 성공 때 쓰이는 resolve처리 실패 때 쓰이는 reject 를 인자로 받는다.

//Promise 를 new 로 생성하면 Pending(대기) 상태가 된다
new Promise(function(resolve, reject) {
   //...
});

 

 

Fulfilled(이행)

방금 말한 콜백 함수에서 어떠한 처리를 수행할테고, 이 처리가 성공하면 인자 값인 resolve 를 수행한다.

new Promise(function(resolve, reject) {

    //... 처리 로직 A
    
    //처리 로직 A 가 성공하면 resolve 를 실행 
    resolve();
    
});

 

이렇게 resolve( ) 를 수행하게 되면 Promise 객체는 Fulfilled(이행) 상태가 되는데,

 

Fulfilled(이행) 상태가 되면 아래와 같이 then( ) 을 이용해 처리 결과를 받아올 수 있다.

function getText() {
    return new Promise(function(resolve, reject) {
        var text1 = "Hello";
        var text2 = "World";
        var returnText = text1 + text2 ;
        
        //Fulfilled(이행) 상태가 된다
        resolve(returnText);
    });
}

//then() 으로 값을 받아온다
getText().then(function(returnText) {
    console.log(returnText); //"HelloWorld"
});

 

 

Rejected(실패)

Fulfilled(이행) 상태와는 반대로 콜백 함수에서 어떠한 처리를 수행할 때

 

처리가 실패되면 reject ( ) 를 수행하여 Rejected(실패) 상태로 들어가게 된다.

 

Fulfilled(이행) 상태는 then( ) 로 받았다면 Rejected(실패) 상태는 catch( ) 로 결과 값을 받아올 수 있다.

function getText() {
    return new Promise(function(resolve, reject) {
        
        //... 처리로직
        
        //Rejected(실패) 상태가 된다
        reject(new Error("처리 실패"));
    });
}

//catch() 로 값을 받아온다
getText().then().catch(function(returnError) {
    console.log(returnError); //"처리 실패"
});

 

그럼 이러한 Promise 의 예제들을 살펴보도록 하자.

 

 

Promise 예제 ( 1 )

ajax 통신 사용 예제

서론에서 언급한 ajax 통신의 콜백 지옥을 아래와 같이 탈출할 수 있다.

function test1() {
    return new Promise(function(resolve, reject) {
        $.ajax({
            url: '...',
            data: '...',
            type: 'post',
            success : function(response) {
                resolve(); //통신 성공하면 resolve()
            },
            error: function(error) {
                reject();  //통신 실패하면 reject()
            }
        }); 
    });
}
    
function test2() {
    return new Promise(function(resolve, reject) {
        $.ajax({
            url: '...',
            data: '...',
            type: 'post',
            success : function(response) {
                resolve(); //통신 성공하면 resolve()
            },
            error: function(error) {
                reject();  //통신 실패하면 reject()
            }
        });
    }); 
}
 
function test3() {
    return new Promise(function(resolve, reject) {
        $.ajax({
            url: '...',
            data: '...',
            type: 'post',
            success : function(response) {
                resolve(); //통신 성공하면 resolve()
            },
            error: function(error) {
                reject();  //통신 실패하면 reject()
            }
        });
    });
}

//처리 성공 함수
function testSuccess() {
    console.log("성공");
    return false;
}

//처리 실패 함수
function testError() {
    console.log("실패");
    return false;
}

test1()            //test1 실행
.then(test2)       //test1 성공하면 test2 실행
.then(test3)       //test2 성공하면 test3 실행
.then(testSuccess) //test3 성공하면 처리성공함수 실행
.catch(testError); //test1, test2, test3 에서 각각 처리 실패할 때마다 처리실패함수 실행

 

이 예제 코드의 전체 흐름은 다음과 같다. 

- test1( ) 을 실행하고 처리 로직을 성공하면 test2( ) 를 수행한다.

- test2( ) 을 실행하고 처리 로직을 성공하면 test3( ) 를 수행한다.

- test3( ) 을 실행하고 처리 로직을 성공하면 testSuccess( ) 를 수행한다.

- 이 과정 중 처리 실패가 발생하면 testError( ) 를 수행한다.

 

 

Promise 예제 ( 2 )

setTimeout( ) API 사용 예제

new Promise(function(resolve, reject){
    setTimeout(function() {
        resolve(1);
    }, 3000);
})
.then(function(num) {
    if(num % 2 == 0) {
        console.log("넘어온 num 은 짝수이다");
    }
    console.log(num); // 1
    return result + 1;
})
.then(function(num) {
    if(num % 2 == 0) {
        console.log("넘어온 num 은 짝수이다");
    }
    console.log(num); // 2
    return result + 1;
})
.then(function(num) {
    if(num % 2 == 0) {
        console.log("넘어온 num 은 짝수이다");
    }
    console.log(num); // 3
    return result + 1;
});

//실행결과
//1
//"넘어온 num 은 짝수이다"
//2
//3

 

짝수인 num 을 받아올 때 "넘어온 num은 ..." 로그를 찍는 코드인데

 

첫 번째 then( ) 에서 받아온 num 은 1 이기에 "넘어온 num은 ..." 로그가 안찍히고,

 

두 번째 then( ) 에서 받아온 num 은 2 이기에 "넘어온 num은 ..." 로그가 찍힐 것이다.

 

 

 

지금까지 Promise 객체에 대해 알아보았다.

 

요악하자면 Promise 객체비동기 처리때 사용되고 대기, 이행, 실패 처리 상태를 가지고 있다.

 

처리 성공resolve 를 수행이행 상태로 바꾸고 이러한 이행 상태의 처리 결과는 then( ) 으로 받는다.

 

반대로 처리 실패reject 를 수행실패 상태로 바꾸고 이 처리 결과는 catch( ) 로 받는다.

 

이 부분만 숙지하면 Promise 를 사용하는 데에 큰 문제 없다고 생각되어진다.

 

 

 

반응형