JavaScript에서 나만의 커스텀 프로미스 만들기: 쉽게 배우는 단계별 가이드
2024-12-27 03:19:51JavaScript 비동기 처리의 핵심, 프로미스를 직접 구현해보자! 🌟
JavaScript 개발자라면 비동기 처리에서 중요한 역할을 하는 프로미스(Promise)를 한번쯤은 다뤄 보셨을 겁니다. 프로미스는 비동기 코드를 읽기 쉽게 만들어주고 다양한 콜백을 체인으로 연결하게 도와줍니다. 그러나 이를 직접 구현해본다면, 우리는 프로미스의 작동 원리를 더 잘 이해할 수 있습니다. 이번 블로그에서는 가장 기본적인 형태의 커스텀 프로미스를 구현해보고, 그 활용법과 함께 다양한 확장 방법에 대해 살펴보겠습니다.
프로미스의 핵심 구성 요소는 무엇일까? 🔧
프로미스는 '미래의 어떤 값'을 나타내며, 이를 다루는 데 있어 가장 중요한 두 가지 구성 요소는 상태 관리자와 콜백입니다.
상태 관리자
- Pending (대기 중) ⏳: 아직 작업이 완료되지 않은 상태입니다.
- Fulfilled (성공) ✅: 작업이 성공적으로 완료된 상태입니다.
- Rejected (실패) ❌: 작업이 실패한 상태입니다.
콜백 처리
성공 시 호출되는 then 콜백과 실패 시 호출되는 catch 콜백은 프로미스의 상태변화에 따라 적절히 호출됩니다.
나만의 커스텀 프로미스 만들기 🏗️
이제부터는 직접 프로미스를 구현해 봅시다. 이 과정은 프로미스의 기본적인 작동 원리를 이해하는 데 큰 도움이 될 것입니다.
기본 커스텀 프로미스 구현하기
// 커스텀 프로미스 생성자
class CustomPromise {
constructor(executor) {
this.state = 'pending'; // 가능한 상태: 'pending', 'fulfilled', 'rejected'
this.value = undefined; // 결과 값 또는 오류
this.successCallbacks = [];
this.errorCallbacks = [];
try {
console.log("프로미스를 실행합니다... 🎯");
executor(this._resolve, this._reject);
} catch (error) {
this._reject(error);
}
}
// 커스텀 resolve 함수
_resolve = (value) => {
if (this.state === 'pending') {
this.state = 'fulfilled';
this.value = value;
console.log(`프로미스가 성공적으로 완료되었습니다: ${value} ✅`);
this.successCallbacks.forEach(callback => callback(this.value));
}
}
// 커스텀 reject 함수
_reject = (error) => {
if (this.state === 'pending') {
this.state = 'rejected';
this.value = error;
console.log(`프로미스가 실패하였습니다: ${error} ❌`);
this.errorCallbacks.forEach(callback => callback(this.value));
}
}
// 성공 처리를 위한 then 메서드
then(successCallback) {
if (this.state === 'fulfilled') {
successCallback(this.value);
} else if (this.state === 'pending') {
this.successCallbacks.push(successCallback);
}
return this;
}
// 실패 처리를 위한 catch 메서드
catch(errorCallback) {
if (this.state === 'rejected') {
errorCallback(this.value);
} else if (this.state === 'pending') {
this.errorCallbacks.push(errorCallback);
}
return this;
}
}
커스텀 프로미스 사용해보기 🖥️
이제 위에서 구현한 커스텀 프로미스를 실제로 사용해보고 그 결과를 확인해봅시다.
const myCustomPromise = new CustomPromise((resolve, reject) => {
setTimeout(() => {
const success = true; // 이 값을 false로 바꿔서 실패 시나리오를 테스트하세요
if (success) {
resolve("커스텀 프로미스가 성공적으로 완료되었습니다! 🎉");
} else {
reject("커스텀 프로미스가 실패하였습니다! 😔");
}
}, 2000); // 2초의 지연
});
myCustomPromise
.then((message) => {
console.log("then 내부:", message);
})
.catch((error) => {
console.error("catch 내부:", error);
});
예상 결과
성공 시:
프로미스를 실행합니다... 🎯
프로미스가 성공적으로 완료되었습니다: Custom promise resolved successfully! 🎉
then 내부: Custom promise resolved successfully! 🎉
실패 시:
프로미스를 실행합니다... 🎯
프로미스가 실패하였습니다: Custom promise was rejected! 😔
catch 내부: Custom promise was rejected! 😔
커스텀 프로미스 확장하기 🔧
커스텀 프로미스를 기본적으로 구현한 후, 여기서 더 나아가 프로미스를 확장해보도록 하겠습니다.
1. 체이닝 지원
프로미스 체이닝은 연속적인 비동기 작업을 효과적으로 처리할 수 있도록 도와줍니다. 우리는 then 메서드를 새 프로미스를 반환하도록 개선할 수 있습니다.
then(successCallback) {
const newPromise = new CustomPromise((resolve, reject) => {
const handleSuccess = (value) => {
try {
const result = successCallback(value);
if (result instanceof CustomPromise) {
result.then(resolve).catch(reject);
} else {
resolve(result);
}
} catch (error) {
reject(error);
}
};
if (this.state === 'fulfilled') {
handleSuccess(this.value);
} else if (this.state === 'pending') {
this.successCallbacks.push(handleSuccess);
}
});
return newPromise;
}
2. finally 메서드 추가하기 🧹
finally 메서드는 프로미스가 성공하거나 실패 시 모두 실행되어야 할 코드를 처리하는 데 유용합니다.
finally(callback) {
return this.then(
(value) => {
callback();
return value;
},
(reason) => {
callback();
throw reason;
}
);
}
마무리
JavaScript에서 프로미스를 이해하는 것은 비동기 프로그래밍의 기초를 다지는 데 매우 중요합니다. 이번 포스팅에서는 가장 기본적인 형태의 커스텀 프로미스를 만들어보고, 이를 확장하는 방법까지 따라해 보았습니다. 계속해서 응용해보며 더 복잡한 비동기 로직도 문제없이 처리할 수 있도록 연습해보세요!