본문 바로가기
프로그래밍/javascript

[프로그래밍] Javascript Promise

by 개발 까마귀 2021. 7. 15.
반응형

Javascript Promise

안녕하세요. 날씨가 가면 갈수록 정말 덥네요. 다들 여름 날씨 조심하시고 힘내시길 바랍니다.

오늘 알려드릴거는 Javascript의 Promise 대해서 알려드리도록 하겠습니다.
우선 Promise를 알기전 callback을 알아야합니다. callback은 다른 코드의 인수로서 넘겨주는 실행 가능한 함수 입니다. 일단 Promise async/await가 나오기전 callback으로 개발 패턴을 짰습니다.
하지만 callback으로 하면 callback 지옥이라는게 기다리고있죠

무서워도 알아야하는 callback!

function processing() {
    console.log('start');

    function callback(data) {
        function dataProcessingCallback(data) {
            console.log(data); console.log('end');
        }
        if (data) {
            dataProcessing(dataProcessingCallback);
        }
    }

    time(callback);
} 

function dataProcessing(callback) {
    setTimeout(() => {
        callback('data processing');
    }, 1000)
}

function time(callback) {
    setTimeout(() => {
        callback('data');
    }, 3000);
}

processing();

네 대충 이런식입니다. setTimeOut 들어간게 백엔드에서는 데이터베이스 query 통신이나 ajax 통신이라고 생각하시면 됩니다. 만약 query나 통신이 다중이라면? 정신을 차릴 때 쯤 code editor 아래에 좌우로 움직이는 바가 하나 생깁니다.

그래서 생각해낸 방법이 있는데 그 방법은

function dataProcessingCallback(data) {
    console.log(data); console.log('end');
}

function callback(data) {
    if (data) { dataProcessing(dataProcessingCallback); }
}

function processing() { 
    console.log('start'); time(callback); 
}

function dataProcessing(callback) { 
    setTimeout(() => { 
        callback('data processing'); 
    }, 1000); 
}

function time(callback) { 
    setTimeout(() => { 
        callback('data'); 
    }, 3000); 
} 

processing();

callback 함수들을 위로 옮기는 겁니다. 뭐 이러면 보기에는 좋아지지만 그래도 부족합니다. callback 함수와 caller 함수의 구분이 확실이 안가고 헷갈립니다.

*다른 함수의 인자로써 이용되는 함수를 콜백(callback) 함수라고 하고 콜백함수를 호출하는 함수를 콜러(caller)함수라고 합니다.*

구원의 Promise?


자 그러면 무슨 방법이 있을까요? 바로 Promise가 있습니다. Promise로 하면 한결 더 깔끔해진 코드를 작성할 수 있죠

function processing() {
    console.log('start');
    dataProcessing().then(() => {
        console.log('data processing end!');
    })
}

function dataProcessing() {
    return new Promise((res, rej) => {
        setTimeout(() => {
            console.log('data processing');
            res();
        }, 1000)
    })
}

processing();

코드가 매우 깔끔해 졌네요. 그럼 예외처리는 어떻게 할까요?

function processing() {
    console.log('start');
    dataProcessing()
        .then(() => {
            console.log('data processing end!');
        })
        .catch((e) => {
            console.log(e);
        })
} 

function dataProcessing() {
    return new Promise((res, rej) => {
        setTimeout(() => {
            rej('data processing error!!!!');
            console.log('data processing'); res();
        }, 1000)
    })
}

processing();

이렇게 예외처리를 할 수 있습니다. res, rej 뭔지 알겠죠? rej는 문제가 발생했을 때 사용하고 res는 데이터를 전달 및 작업이 완료됐을때의 응답입니다. 그거를 then으로 수행을 하고 문제가 발생했을 때는 catch로 넘어가게 되죠
then은 여러번 쓰이는게 가능합니다. 첫번째 then에서 수행이 완료되면 그 다음에 then으로 가고 또 그 다음 then으로 가는 식입니다. 마침 사슬처럼요. 만약 에러가 나도 꼭 실행해야하는 코드가 있다면?

function processing() {
    console.log('start');
    
    dataProcessing()
        .then(() => {
            console.log('data processing end!');
        })
        .catch((e) => {
            console.log(e);
        })
        .finally(() => {
            console.log("죽더라도 실행은 하고 죽는다..");
        })
}

processing();

이렇게하면 catch에 에러가 나도 finally가 실행이됩니다.

Promise는 "상태" 라는게 있습니다.

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

하지만 promise도 쓰다보면 callback 지옥에 빠지기도합니다.

function processing() {
    console.log('start');
    dataProcessing()
        .then(() => {
            console.log('data processing end!');
            
            time()
                .then(() => {
                    console.log('time end');
                })
        })
}

function dataProcessing() {
    return new Promise((res, rej) => {
        setTimeout(() => {
            console.log('data processing');
            res();
        }, 1000);
    })
}

function time() {
    return new Promise((res, rej) => {
        setTimeout(() => {
            console.log('time');
            res();
        }, 1000);
    })
}

processing();

대충 감이 오시죠? 이렇게 promise도 쓰다보면 callback 지옥에 빠지고 무조건 then에서만 놀아야됩니다.
그렇기 때문에 async/await이 편한겁니다. 코드 보기에도 좋고 쓰기도 간편합니다. 하지만 async/await이 짱이야! 새로워! 짜릿해! 이러면서 async/await으로만 짜는거는 아닙니다. 어떨 때는 callback 패턴으로 짤때도 있습니다. 그리고 여러분들이 쓰는 web api나 함수들은 기본적으로 callback입니다. callback이 뭔지 제대로 아셔야지 promise나 async/await이 뭔지를 제대로 알고 어떨 때 쓰이지는 알 수 있습니다.

다음에는 async/await과 promise 보충 설명이 있겠습니다.

감사합니다.

반응형

댓글