Promise 객체

Frontend/JavaScript

Promise 객체의 필요성

자바스크립트에서 비동기 작업을 처리하는 가장 기본적인 방법은 콜백함수를 사용하는 것이다.

 

자바스크립트 비동기 처리

자바스크립트에서 비동기 처리는 여러 작업을 효율적으로 처리하기 위한 핵심 개념이다.동기와 비동기의 차이를 이해하고, 자바스크립트가 싱글 스레드 환경에서 어떻게 비동기 작업을 처리하

devmark.tistory.com

 

setTimeout를 이용하면 작업을 비동기적으로 처리할 수 있다. setTimeout은 콜백함수와 ms 단위의 지연 시간을 매개변수로 받는다.

 

아래는 workA, workB, workC 함수를 비동기 함수로 작성하고, workD는 동기적으로 작성한 예시이다.

const workA = (value, callback) => {
  setTimeout(() => {
    callback(value);
  }, 5000);
};
const workB = (value, callback) => {
  setTimeout(() => {
    callback(value);
  }, 3000);
};
const workC = (value, callback) => {
  setTimeout(() => {
    callback(value);
  }, 10000);
};
const workD = (value, callback) => {
    callback(value);
};

workA("workA", (res) => {
  console.log(res);
});
workB("workB", (res) => {
  console.log(res);
});
workC("workC", (res) => {
  console.log(res);
});
workD("workD", (res) => {
  console.log(res);
});

 

콜백 지옥

이 코드를 다음과 같이 바꿔보자.

  1. workA에서 매개변수로 받은 값에 5를 더한다.
  2. 그 결과값을 workB에서 전달받아 3을 뺀다.
  3. 그 결과값을 workC에서 전달받아 10을 더한다.
const workA = (value, callback) => {
  setTimeout(() => {
    callback(value + 5);
  }, 5000);
};
const workB = (value, callback) => {
  setTimeout(() => {
    callback(value - 3);
  }, 3000);
};
const workC = (value, callback) => {
  setTimeout(() => {
    callback(value + 10);
  }, 10000);
};
const workD = (value, callback) => {
    callback(value);
};

workA(10, (resA) => {
  console.log(`1. ${resA}`);
  workB(resA, (resB) => {
    console.log(`2. ${resB}`);
    workC(resB, (resC) => {
      console.log(`3. ${resC}`);
    });
  });
});
workD("workD", (res) => {
  console.log(res);
});

이렇게 비동기 작업은 순차적으로 처리하기 위해 콜백함수를 중첩해서 사용하면 코드의 들여쓰기가 깊어지고 가독성이 떨어진다.

이를 콜백지옥(Callback Hell)이라고 한다.

 

Promise 객체란?

프로미스 객체는 비동기 작업의 완료 또는 실패를 나타내는 객체이다. 콜백지옥 문제를 해결하고 비동기 코드를 더 깔끔하게 작성할 수 있게 해준다.

const promise = new Promise();

 

프로미스 객체를 만들 때에는 인수로 executor라는 실행 함수를 전달하는데, 이 실행 함수는 프로미스 생성자에 반드시 들어가야 하는 함수로 작업을 비동기로 처리한다.

const exeutor = (resolve, reject) => {
  // 코드
}

const promise = new Promise();

 

아래의 코드를 실행하면 '3초만 기다리세요'라는 문장이 출력된다.

const executor = (resolve, reject) => {
  setTimeout(() => {
    console.log('3초만 기다리세요');
  }, 3000)
}

const promise = new Promise(executor);

 

이처럼 executor함수는 프로미스 객체를 생성함과 동시에 실행되는 실행 함수이다.

 

resolve와 reject

excutor의 매개변수인 resolve와 reject는 자바스크립트에서 자체적으로 제공하는 콜백함수이다.

  • resolve: 비동기 작업이 성공했을 때 호출
  • reject: 비동기 작업이 실패했을 때 호출

 

Promise 내부 프로퍼티

프로미스 객체는 state와 result 이렇게 두 가지의 내부 프로퍼티를 갖는다.

Promise의 3가지 상태

위 그림과 같이 프로미스 객체의 상태는 resolve와 reject를 통해 변하는데, 한 번 변경된 상태는 더 이상 변하지 않는다.

따라서 처리가 끝난 프로미스 객체에 resolve나 reject를 호출하면 무시된다.

 

resolve와 reject 사용하기

resolve 사용

const executor = (resolve, reject) => {
  setTimeout(() => {
    resolve('성공');
  }, 3000)
}

const promise = new Promise(executor);
promise.then((res) => {
  console.log(res);
})

프로미스 객체가 생성되면서 동시에 executor함수가 실행되고, executor함수에서는 매개변수로 받은 콜백함수 중 resolve함수를 사용해 '성공'이라는 값을 전달한다.

 

3초 후 '성공'이 출력된다.

 

reject 사용

const executor = (resolve, reject) => {
  setTimeout(() => {
    reject('실패');
  }, 3000)
}

const promise = new Promise(executor);
promise.then((res) => {
  console.log(res);
}).catch((err) => {
  console.log(err);
})

reject함수가 실행되었기 때문에 프로미스의 객체의 state는 pending에서 rejected로, result는 undefined에서 '실패'로 변경된다.

 

3초 후 '실패'가 출력된다.

 

콜백지옥을 해결하는 Promise 객체

위에서 겪었던 콜백지옥 함수를 프로미스 객체를 사용해 다시 작성해보자.

 

먼저 각 함수가 Promise를 반환하도록 수정한다.

const workA = (value) => {
  const promise = new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve(value + 5);
    }, 5000)
  });
  return promise;
};

const workB = (value) => {
  const promise = new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve(value - 3);
    }, 3000);
  });
  return promise;
};

const workC = (value) => {
  const promise = new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve(value + 10);
    }, 10000);
  });
  return promise;
};

 

이제 이 함수들을 사용해보자

workA(10).then((resA) => {
  console.log(`1. ${resA}`);
  workB(resA).then((resB) => {
    console.log(`2. ${resB}`);
    workC(resB).then((resC) => {
      console.log(`3. ${resC}`);
    });
  });
});

코드가 많이 깔끔해지긴 햇지만 여전히 콜백지옥의 코드와 많이 닮아있다.

 

then메서드를 다른 방식으로 사용하면 위 코드를 더 깔끔하게 작성할 수 있다.

프로미스 체이닝

이번에는 then메서드의 콜백함수 안에서 workB를 return해보자.

workA(10).then((resA) => {
  console.log(`1. ${resA}`);
  return workB(resA);
}).then((resB) => {
  console.log(`2. ${resB}`);
  return workC(resB);
}).then((resC) => {
  console.log(`3. ${resC}`);
});

이렇게 workB함수가 반환되게 하면, workB함수의 반환값인 프로미스 객체가 반환되는 것이기 때문에 다시 then을 사용할 수 있게 된다.

위와 같이 계속해서 프로미스 객체를 반환하며 then 메서드를 연속으로 사용하는 것을 프로미스 체이닝(Promise Chaining)이라고 한다.

 

프로미스 체이닝을 사용하면 코드를 아래쪽으로 계속 작성할 수 있기 때문에 더 깔끔해지고, 직관적인 코드해석이 가능해진다.

'Frontend > JavaScript' 카테고리의 다른 글

Vanilla JS 컴포넌트 설계 패턴  (0) 2025.11.10
화살표 함수와 객체  (0) 2025.11.09
API 호출  (0) 2025.10.31
async와 await  (0) 2025.10.31
자바스크립트 비동기 처리  (0) 2025.10.31
'Frontend/JavaScript' 카테고리의 다른 글
  • 화살표 함수와 객체
  • API 호출
  • async와 await
  • 자바스크립트 비동기 처리
고견
고견
개발 자국 남기기
  • 고견
    개발자국
    고견
  • 전체
    오늘
    어제
    • 분류 전체보기 (157) N
      • Frontend (29)
        • Next.js (16)
        • JavaScript (7)
      • CS (19) N
        • 자료구조 (9)
        • 알고리즘 (5)
        • 운영체제 (4) N
        • 네트워크 (1) N
      • TIL (93)
      • Dev Log (16)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    인터페이스
    제네릭
    react
    함수 타입
    App Router
    CS
    javascript
    페이지 라우터
    자료구조
    클래스
    algorithm
    트러블 슈팅
    문자열
    Pages Router
    useState
    ai 감성 일기장
    Next.js
    타입 좁히기
    알고리즘
    앱 라우터
    Spa
    memory
    cs50
    배열
    generic
    Trouble Shooting
    바닐라 자바스크립트
    emotion diary
    typescript
    C
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.5
고견
Promise 객체
상단으로

티스토리툴바