Promise 이해하기

Promise는 JavaScript에서 비동기 연산의 최종 완료(또는 실패) 및 그 결과값을 나타내는 객체입니다. 비동기 작업을 더 쉽고 효율적으로 관리할 수 있게 해 주며, 콜백 지옥(callback hell)을 피하는 데 유용합니다.

 

Promise의 기본 구조

Promise 객체는 비동기 작업을 수행하고, 그 작업이 성공적으로 완료되었을 때와 실패했을 때의 처리 로직을 담고 있습니다.

 

기본 구조

const myPromise = new Promise((resolve, reject) => {
  // 비동기 작업을 여기에 구현
  if (/* 작업 성공 */) {
    resolve(value);  // 성공 결과를 반환
  } else {
    reject(error);  // 실패 이유를 반환
  }
});
  • resolve: 비동기 작업이 성공적으로 완료되었을 때 호출됩니다. 이 함수를 호출하며 비동기 작업의 결과를 전달할 수 있습니다.
  • reject: 비동기 작업이 실패했을 때 호출됩니다. 실패의 이유(에러)를 전달합니다.

예제 1: 간단한 Promise 생성과 사용

const checkNumber = new Promise((resolve, reject) => {
  const number = Math.floor(Math.random() * 100);
  setTimeout(() => {
    if (number % 2 === 0) {
      resolve(`Even number: ${number}`);
    } else {
      reject(`Odd number: ${number}`);
    }
  }, 2000);
});

checkNumber.then(message => {
  console.log("Success:", message);
}).catch(error => {
  console.error("Error:", error);
});

 

이 예제에서 checkNumber는 0에서 99까지의 무작위 수를 생성하고, 그 수가 짝수이면 성공 메시지를, 홀수이면 오류 메시지를 반환합니다. .then()과 .catch() 메서드를 사용하여 각각 성공과 실패 시의 로직을 처리합니다.

 

예제 2: Promise 체이닝

 

Promise는 .then()을 사용하여 여러 비동기 작업을 순차적으로 연결할 수 있습니다. 각 .then() 메서드는 새로운 Promise를 반환합니다.

function doubleNumber(num) {
  return new Promise((resolve, reject) => {
    setTimeout(() => resolve(num * 2), 1000);
  });
}

doubleNumber(5)
  .then(result => {
    console.log(result);  // 10
    return doubleNumber(result);  // 결과를 다시 두 배로
  })
  .then(result => {
    console.log(result);  // 20
    return doubleNumber(result);
  })
  .then(result => {
    console.log(result);  // 40
  });

 

이 예제에서는 숫자를 받아 1초 후에 그 수를 두 배로 증가시키는 doubleNumber 함수를 정의했습니다. 이 함수는 Promise를 반환하며, 이를 통해 연속적으로 숫자를 두 배로 증가시키는 작업을 수행합니다.

 

예제 설명

 

위 예제들은 Promise의 기본적인 사용 방법을 보여줍니다. Promise를 사용함으로써 비동기 작업을 보다 세련되게 관리할 수 있으며, 코드의 가독성과 유지 보수성이 향상됩니다. 다음 강의에서는 Promise를 활용한 더 복잡한 시나리오와 async/await 구문을 배울 예정입니다.

 

왜 Promise가 콜백 지옥(callback hell)을 피하는 데 유용한가?

Promise가 콜백 지옥을 피하는 데 유용한 이유는 주로 그 구조와 특성 때문입니다. 콜백 지옥은 복잡한 비동기 JavaScript 코드에서 흔히 발생하는 문제로, 여러 콜백 함수가 중첩되고, 그로 인해 코드의 가독성과 유지 보수성이 현저히 저하되는 현상을 말합니다. 이 문제를 Promise를 통해 해결할 수 있는 이유는 다음과 같습니다.

 

1. 플랫한 코드 구조

Promise는 중첩된 콜백 함수 대신 연쇄적인 .then() 메소드를 사용하여 결과를 처리합니다. 각 .then()은 비동기 연산의 결과를 기다리는 대기열과 같은 역할을 하며, 이전 연산의 결과를 다음 연산으로 전달합니다. 이로 인해 코드가 수평적으로 확장되어 가독성이 크게 향상됩니다.

 

예제: 콜백 지옥

getData(function(a){
    getMoreData(a, function(b){
        getMoreData(b, function(c){ 
            getMoreData(c, function(d){ 
                getMoreData(d, function(e){ 
                    // 콜백 지옥
                });
            });
        });
    });
});

 

예제: Promise 사용

getData()
  .then(a => getMoreData(a))
  .then(b => getMoreData(b))
  .then(c => getMoreData(c))
  .then(d => getMoreData(d))
  .then(e => {
    // 더 깔끔하고 가독성이 좋음
  });

 

2. 오류 처리의 단순화

콜백 지옥에서는 각 콜백 함수마다 개별적으로 오류를 처리해야 하기 때문에 오류 처리 코드가 복잡해집니다. 반면, Promise는 .catch() 메소드를 사용하여 연쇄된 모든 비동기 연산에서 발생할 수 있는 오류를 한 곳에서 처리할 수 있게 합니다. 이는 오류 처리 로직을 중앙화하여 코드를 더욱 깔끔하게 만들어 줍니다.

getData()
  .then(a => getMoreData(a))
  .then(b => getMoreData(b))
  .catch(error => {
    // 모든 단계에서 발생할 수 있는 예외 처리
    console.error(error);
  });

 

3. 상태 관리

Promise 객체는 세 가지 상태를 가집니다: 대기(pending), 이행(fulfilled), 거부(rejected). 이 상태들은 Promise의 수명 동안 한 번만 변경될 수 있으며, 상태에 따라 적절한 처리가 자동으로 이루어집니다. 이는 비동기 작업의 상태를 명확하게 관리할 수 있게 해 주며, 불필요한 조건문을 줄여줍니다.

 

이러한 이유들로 Promise는 복잡한 비동기 코드를 보다 체계적이고 관리하기 쉽게 만들어 주며, 콜백 지옥에서 발생하는 문제들을 효과적으로 해결할 수 있는 강력한 도구입니다.

+ Recent posts