[javascript 자바스크립트] Promise 프로미스 란?

resilient

·

2021. 7. 21. 13:58

728x90
반응형

 

이번 시간에는 '프로미스 객체'에 대해서 알아보려고 한다. 프로미스 객체란 무엇일까?

 

자바스크립트와 노드에서는 주로 비동기를 접한다.

프로미스는 자바스크립트 비동기 처리에 사용되는 객체이다. 여기서 자바스크립트의 비동기 처리란 ‘특정 코드의 실행이 완료될 때까지 기다리지 않고 다음 코드를 먼저 수행하는 자바스크립트의 특성’을 의미한다

비동기 처리 시 이벤트 리스너를 이용할 때 콜백 함수를 자주 사용한다. ES2015부터는 자바스크립트와 노드의 API들이 콜백 대신 프로미스(Promise) 기반으로 재구성되어 우리가 흔히 말하는 '콜백 지옥' 현상을 극복했다고 한다. 

 

프로미스를 쉽게 설명하자면 실행은 바로 하되, 결괏값은 나중에 받는 객체라고 할 수 있다.

프로미스를 사용하기 위해서는 먼저 프로미스 객체를 생성해야 한다. 아래 예시를 보자.

 

const condition = true; // true면 resolve, false면 reject
const promise = new Promise((resolve, reject) => {
  if (condition) {
    resolve('성공');
  } else {
    reject('실패');
  }
});
// 다른 코드가 들어갈 수 있음
promise
  .then((message) => {
    console.log(message); // 성공(resolve)한 경우 실행
  })
  .catch((error) => {
    console.error(error); // 실패(reject)한 경우 실행
  })
  .finally(() => { // 끝나고 무조건 실행
    console.log('무조건');
  });
  • new Promise로 프로미스를 생성할 수 있고, 그 내부에는 resolve()와 reject()를 매개변수로 갖는 콜백 함수를 넣는다.
  • 이렇게 만든 Promise변수에 then과 catch메서드를 붙이면 되는데, resolve가 호출되면 then이 실행되고, reject가 호출되면 catch가 실행된다.
  • finally 부분은 성공/실패 여부와 상관없이 실행된다.
  • 결괏값은 실행이 완료된 후, then이나 catch 메서드를 통해 받는다. 

 

한 번 더 예시를 보자.

promise
  .then((message) => {
    return new Promise((resolve, reject) => {
      resolve(message);
    });
  })
  .then((message2) => {
    console.log(message2);
    return new Promise((resolve, reject) => {
      resolve(message2);
    });
  })
  .then((message3) => {
    console.log(message3);
  })

  .catch((error) => {
    console.error(error);
  });

 

처음 then에서 return값을 Promise객체로 넘긴 후, message를 resolve 한다.

다음 then이 나오면 message2로 받을 수 있다. 다시  return값을 Promise객체로 넘긴 후, message2를 resolve 하면

다음 then에서는 message3으로 받는다. 

 

콜백 함수를 프로미스로 바꾸는 과정을 보자.

 

아래 코드는 콜백을 쓰는 패턴 중 하나이다. 콜백 함수가 3번 중첩되어 있어서 코드의 깊이가 깊어지고 콜백 함수마다 에러도 따로따로 처리해줘야 한다.

 

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

 

위에 코드를 프로미스 객체를 사용해서 바꾸면 아래와 같다.

 

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

 

코드의 깊이가 세 단계 이상 깊어지지 않는다. 

 

위 예제 코드는 findOne과 save메서드가 내부적으로 프로미스 객체를 가지고 있다고 가정했기에 가능한 것이지 모든 콜백 함수를 프로미스 객체를 사용해서 바꿀 수 있는 것은 아니다.

 

 

이번엔 프로미스의 3가지 상태(State)에 대해서 알아보자.

 

프로미스를 사용할 때 가장 기본적인 개념 중 하나가 프로미스의 상태(states)이다. 여기서 말하는 상태란 프로미스의 처리 과정을 의미한다. new Promise()로 프로미스를 생성하고 종료될 때까지 3가지 상태를 갖는다.

  • Pending(대기) : 비동기 처리 로직이 아직 완료되지 않은 상태
  • Fulfilled(실행 완료) : 비동기 처리가 완료되어 프로미스가 결과 값을 반환해준 상태
  • Rejected(실패) : 비동기 처리가 실패하거나 오류가 발생한 상태

 

Pending(대기)

 

먼저 new Promise()로 메서드를 호출하면 Pending 상태가 된다. new Promise() 메서드를 호출할 때, 콜백 함수를 선언할 수 있고, 인자는 위에서 설명했던 것처럼 resolve, reject이다.

 

Fulfilled(실행 완료)

 

위에서 언급한 new Promise()의 콜백 함수의 인자인 resolve를 실행하면 실행(Fulfilled) 상태가 된다.

 

Rejected(실패)

 

위에서 언급한 new Promise()의 콜백 함수의 인자인 reject를 실행하면 실행(Rejected) 상태가 된다.

실패 상태가 되면 에러 로그를 catch()로 받을 수 있다.

 

사진출처:MDN

반응형