자체 구현된 Promise의 상태 변화 처리
실제로 Promise를 직접 구현하면서 상태 전이 로직을 어떻게 설계할지 고민해보겠습니다. 먼저 공식 문서에 정의된 Promise의 동작 방식을 분석해 보고, 이를 바탕으로 자신의 클래스를 설계합니다.
// 공식 Promise 사용 예시
new Promise((resolve, reject) => {
resolve(1);
});
이 코드에서 알 수 있듯이 Promise는 자바스크립트 엔진 내부에 이미 구현된 클래스입니다. 따라서 우리가 구현할 MyPromise도 이와 유사한 구조를 가져야 합니다.
1. 기본 클래스 생성
class MyPromise {
constructor(executor) {
// 실행자 함수를 즉시 호출
executor(this._resolve, this._reject);
}
// 성공 시 호출되는 메서드 (내부용)
_resolve(value) {
console.log('성공 데이터:', value);
}
// 실패 시 호출되는 메서드 (내부용)
_reject(reason) {
console.log('실패 이유:', reason);
}
}
여기서 주목해야 할 점은 executor 함수가 두 개의 인수(resolve, reject)를 받는다는 것입니다. 이 둘은 함수 타입이며, 각각 성공과 실패를 처리하는 역할을 합니다. 우리는 이 두 함수를 클래스의 내부 메서드로 정의하고, 외부에서 직접 접근하지 못하도록 제한합니다.
2. 상태 관리 추가: 상태 전이 규칙 적용
Promise는 세 가지 상태를 가집니다:
pending: 초기 상태, 아직 결과 없음fulfilled: 성공적으로 완료됨rejected: 실패함
또한 상태 전이는 단방향만 허용됩니다:
pending→fulfilledpending→rejected
반대로는 불가능하며, 이미 완료된 상태(fulfilled 또는 rejected)는 다시 변경될 수 없습니다.
이러한 규칙을 반영하기 위해 상태를 저장할 변수를 도입합니다.
class MyPromise {
constructor(executor) {
this._state = 'pending'; // 초기 상태
this._value = undefined; // 성공 시 값 저장
this._reason = undefined; // 실패 시 원인 저장
// 내부 메서드로 상태 전이 제어
const resolve = (value) => {
if (this._state === 'pending') {
this._state = 'fulfilled';
this._value = value;
}
};
const reject = (reason) => {
if (this._state === 'pending') {
this._state = 'rejected';
this._reason = reason;
}
};
// 실행자에게 내부 메서드 전달
try {
executor(resolve, reject);
} catch (error) {
reject(error);
}
}
// 성공 콜백 등록 (미래에 확장 가능)
then(onFulfilled) {
if (this._state === 'fulfilled') {
onFulfilled(this._value);
}
return this;
}
// 실패 콜백 등록 (미래에 확장 가능)
catch(onRejected) {
if (this._state === 'rejected') {
onRejected(this._reason);
}
return this;
}
}
3. 상태 전이 테스트
const task = new MyPromise((resolve, reject) => {
resolve(42); // 상태: pending → fulfilled
reject('오류 발생'); // 무시됨 (이미 상태 변경됨)
});
task.then(result => {
console.log('결과:', result); // 출력: 결과: 42
});
task.catch(err => {
console.log('에러:', err);
});
위 코드에서 resolve 이후 reject가 호출되더라도 상태가 이미 변경되었기 때문에 무시됩니다. 이는 상태 전이의 일관성과 비가역성을 보여줍니다.
핵심 요약
resolve와reject는 외부에서 직접 호출되지 않도록 내부 메서드로 캡슐화- 상태는
pending→fulfilled또는pending→rejected로만 변경 가능 - 상태 변경 후 재설정 불가
- 에러 처리는
try/catch로 감싸서 안정성 확보
이처럼 상태 전이 로직은 Promise의 핵심 기능 중 하나이며, 이를 올바르게 구현하려면 단일 책임 원칙과 불변성을 유지하는 것이 중요합니다.