본문 바로가기
프론트엔드/Javascript

[Javascript] Promise 와 Callback 의 차이

by jinwanseo 2021. 2. 8.
728x90

자바스크립트에서 비동기 처리를 위해

Promise와 Callback 함수가 자주 등장하는데,

Promise의 사용을 Callback 사용보다 더 권장하는 이유는

코드가 훨씬 간결해져 가독성이 좋아지기 때문이다.

 

 

샘플 예제 ↓

샘플 예제로 간단한 로그인을 구현하는 스크립트 예제를 만들어 보았다.

간단하게 아이디, 비밀번호를 물어보고,

아이디와 비밀번호가 맞으면, 회원등급을 조회 후 

메일을 발송하는 예제이다.

서버 측 처리는 setTimeOut을 통해 딜레이를 설정하였다.

 

[Javascript : Callback함수 사용]

//사용자 로그인 예제 :by Callback

class Login {   //로그인 객체

    logUser(id,pw,onSuccess,onError){
        setTimeout(() => {
            //로그인
            if(id==='gildong' && pw === '1234'){
                onSuccess(id);
            }else{
                onError(new Error('아이디와 비밀번호를 확인해주세요'));
            }
        }, 2000);
    }

    getRoles(id, pw, onSuccess, onError){
        setTimeout(() => {
            if(id === 'gildong' && pw === '1234'){
                onSuccess(id);
            }else{
                onError(new Error(`${id}님은 등급이 존재하지 않습니다.`));
            }
        }, 1500);
        //등급 조회
    }

    sendEmail(id, pw, emailAddress, onSuccess, onError){
        setTimeout(()=>{
            if(id === 'gildong' && pw === '1234'){  
                onSuccess(emailAddress);
            }else{
                onError(new Error(`이메일을 보낼수 없습니다.`));
            }
        },2000);
    }

    writeContents(emailAddress, onSuccess){
        setTimeout(() => {
            prompt('내용을 입력해주세요');
            onSuccess(emailAddress);
        }, 1000);
    }
}

//로그인
const userInfo = new Login();
const id = prompt('아이디를 입력 해주세요.');
const pw = prompt('비밀번호를 입력 해주세요.');

userInfo.logUser(
    id,
    pw,
    (user)=>{   //onSuccess
        console.log(`${user}님 환영합니다.`);
        userInfo.getRoles(
            id,
            pw,
            (user)=>{   //onSuccess
                console.log(`${user}님의 등급은 Green 등급입니다`);

                if(confirm('이메일을 보내시겠습니까?')){
                    const mailAddress = prompt('보내실 Email 주소를 작성해주세요');
                    userInfo.sendEmail(
                        id,
                        pw,
                        mailAddress,
                        (mailAddress)=>{   //onSuccess
                            userInfo.writeContents(
                                mailAddress,
                                (add)=>{
                                    alert(`${add}님께 메일 발송 완료`);
                                });
                        },
                        (errMsg)=>{   //onError
                            console.log(errMsg);
                        });
                } else {
                    alert('로그아웃 하였습니다.');
                }
            },
            (errMsg)=>{   //onError
                console.log(errMsg);
            });
    },
    (err)=>{   //getRoles
        console.log(err);
    });

 

위 코드를 보면, Callback 함수로 인해 

코드의 가독성이 얼마나 떨어지는지 알수 있는데,

'이를 콜백 지옥이라고 부르기도한다'

 

[콜백지옥 예시]

() => {
        () => {
              () => {
                       ()=>{
                               ()=>{
                                       ()=>{
                                               ()=>{ }
                                        }

                                }

                        }

                }

        }

}

 

위와같은 콜백지옥을 해결할수 있는 방법이 

Promise()인데, 위의 예제를 하단에 Promise를 사용한 예로 바꿔 보았다.

 

[Javascript : Promise() 사용]

//사용자 로그인 예제 :by Callback

class Login {   //로그인 객체

    logUser(id, pw){
        //로그인
        return new Promise((resolve,reject)=>{
            setTimeout(() => {
                if(id==='gildong' && pw === '1234'){
                    resolve(id);
                }else{
                    reject(new Error('아이디와 비밀번호를 확인해주세요'));
                }
            }, 2000);
        });
    }

    getRoles(id, pw){
        //등급 조회
        return new Promise((resolve,reject)=>{
            setTimeout(() => {
                if(id === 'gildong' && pw === '1234'){
                    resolve(id);
                }else{
                    reject(new Error(`${id}님은 등급이 존재하지 않습니다.`));
                }
            }, 1500);
        });
    }

    sendEmail(id, pw, emailAddress){
        return new Promise((resolve,reject)=>{
            setTimeout(()=>{
                if(id === 'gildong' && pw === '1234'){  
                    resolve(emailAddress);
                }else{
                    reject(new Error(`이메일을 보낼수 없습니다.`));
                }
            },2000);
        });
    }

    writeContents(emailAddress){
        return new Promise((resolve)=>{
            setTimeout(() => {
                prompt('내용을 입력해주세요');
                resolve(emailAddress);
            }, 1000);
        });
    }
}

//로그인
const userInfo = new Login();
const id = prompt('아이디를 입력 해주세요.');
const pw = prompt('비밀번호를 입력 해주세요.');

userInfo.logUser(id,pw)
.then(user => {
    console.log(`${user}님 환영합니다.`);
    userInfo.getRoles(id,pw)
    .then(userId=>{
        console.log(`${userId}님의 등급은 Green 등급입니다`);
        if(confirm('이메일을 보내시겠습니까?')){
            const mailAddress = prompt('보내실 Email 주소를 입력하세요');
            userInfo.sendEmail(id,pw,mailAddress)
            .then(mail=>{
                userInfo.writeContents(mail)
                .then(sendUser=>alert(`${sendUser}님께 발송 완료`));
            })
            .catch(console.log);
        }
    })
    .catch(console.log)
})
.catch(console.log);

 

예외처리까지 그전 코드와는 확연히 차이가 난다.

사실 싱글스레드로 구동되는 자바스크립트라는 언어 내에서

실제 구동되는 내부 로직의 효율성 그 자체는 모르긴 몰라도 별차이 없을수 있다.

하지만 깔끔함이 갖추어진 간결한 코드는

사람이 하는 유지보수나 개발의 효율을 훨씬 높일수 있다.

728x90

댓글