[CS] JavaScript - Promise

ZenTechie·2023년 5월 9일
0

Javascript

목록 보기
4/5

Promise(프로미스)

자바스크립트와 Node는 비동기 프로그래밍으로 이벤트 주도 방식을 활용하면서 콜백 함수를 많이 사용하게 된다. 콜백 함수 자체가 복잡한 것도 있고, 이해하기 어려운 자바스크립트 내용 중 하나이기도 하다.

이에 ES2015부터는 콜백 대신 API들이 프로미스 기반으로 재구성되고 있다. 따라서 프로미스에 대해 잘 이해하고 사용하게 된다면, 복잡한 콜백 함수의 지옥에서 벗어날 수 있으니 확실히 알고 있어야 한다.

Promise 객체 구조는 다음과 같다.

const condition = true;
 
const promise = new Promise((resolve, reject) => {
    if (condition){
        resolve('성공');
    } else {
        reject('실패');
    }
});
 
promise
    .then((message) => {
        console.log(message);
    })
    .catch((error) => {
        console.log(error);
    });

new PromisePromise 를 생성할 수 있다. 그리고 안에 resolvereject 를 매개변수로 갖는 콜백 함수를 넣는 방식이다.

이제 선언한 Promise 변수에 thencatch 메소드를 붙일 수 있다.

resolve 가 호출되면 then 이 실행되고, reject 가 호출되면 catch 가 실행된다.

이제 resolvereject 에 넣어준 인자는 각각 thencatch 의 매개변수에서 받을 수 있다.

즉,

  • condition === true 라면, resolve('성공') 이 호출되어 message'성공' 이 들어가 콘솔에 출력된다.
  • condition === false 라면, reject('실패') 가 호출되어 catch 문이 실행되고 error'실패' 가 들어가 콘솔에 출력된다.

이러한 방식을 활용해서 콜백을 프로미스로 바꿔보자.

function findAndSaveUser(Users) {
    Users.findOne({}, (err, user) => { // 첫번째 콜백
        if(err) {
            return console.error(err);
        }
        user.name = 'kim';
        user.save((err) => { // 두번째 콜백
            if(err) {
                return console.error(err);
            }
            Users.findOne({gender: 'm'}, (err, user) => { // 세번째 콜백
                // 생략
            });
        });
    });
}

보통 콜백 함수를 사용하는 패턴은 이와 같이 작성한다. 현재는 콜백 함수가 3번 중첩된 모습을 볼 수 있다.

즉, 콜백 함수가 나올 때 마다 코드가 길어지고 깊어지며, 각 콜백 함수마다 에러도 따로 처리해줘야 한다.

하지만, Promise 를 활용하면 다음과 같이 작성할 수 있다.

function findAndSaveUser1(Users) {
    Users.findOne({})
        .then((user) => {
            user.name = 'kim';
            return user.save();
        })
        .then((user) => {
            return Users.findOne({gender: 'm'});
        })
        .then((user) => {
            // 생략
        })
        .catch(err => {
            console.error(err);
        });
}

then 을 활용해 코드가 깊어지지 않도록 만들었다. 이때 then 메소드들은 순차적으로 실행된다.

에러는 마지막 catch 를 통해 한번에 처리할 수 있다. 하지만 모든 콜백 함수를 이처럼 고칠 수 있는 것은 아니고, findsave 메소드가 Promise 방식을 지원하기 때문에 가능하다.

Promise 방식을 지원하지 않는 콜백 함수는 util.promisify 를 통해 가능하다.

Promise 여러 개를 한번에 실행할 수 있는 방법도 존재하는데, Promise.all 을 사용한다.

const promise1 = Promise.resolve('성공1');
const promise2 = Promise.resolve('성공2');
 
Promise.all([promise1, promise2])
    .then((result) => {
        console.log(result);
    })
    .catch((error) => {
        console.error(err);
    });

promise.all 에 해당하는 모든 Promiseresolve 상태 여야 then 으로 넘어간다.
만약, 하나라도 reject 가 있다면 catch 문 으로 넘어간다.

기존의 콜백을 활용한다면, 여러 번 중첩해서 구현해야 하지만 Promise 를 사용하면 깔끔하게 코드 작성이 가능하다.

정리

Promise 패턴 을 사용하면 비동기 작업들을 순차적으로 진행하거나, 병렬로 진행하는 등 컨트롤이 보다 수월해진다. 또한, 내부적으로 예외처리에 대한 구조가 존재하기 때문에 오류 처리 등에 대해 보다 가시적으로 관리할 수 있다.

Promise 패턴은 ECMAScript6 스펙에 정식으로 포함되었다.

profile
데브코스 진행 중.. ~ 2024.03

0개의 댓글