공부 중 생긴 궁금증
Promise를 사용하다가 이런 코드 구조를 마주쳤다.
new Promise((resolve, reject) => {
// 여기서 비동기 로직을 수행한다
if (/* 실패 상황 */) {
reject("에러 발생");
return;
}
resolve("성공");
});
처음에는 아무렇지 않게 썼지만, 곰곰이 생각해보니 이 구조가 매우 독특하게 느껴졌다.
- resolve, reject는 내가 만든 함수가 아닌데, 어디서 온 걸까?
- 왜 핵심 로직(예: 타이머, API 호출 등)은 Promise 외부에서 정의할까?
- 어떤 디자인 패턴인가?
그래서 Promise를 직접 클래스 형태로 구현해보며 구조를 뜯어봤다.
직접 구현한 Promise
class MyPromise {
constructor(executor) {
this.state = 'pending';
this.value = null;
this.reason = null;
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 (err) {
reject(err);
}
}
}
- resolve, reject는 생성자 내부에서 정의됨
- 그러나 이걸 호출하는 타이머나 API 호출 등의 핵심 로직은 외부에서 정의됨
- 이 구조는 일반적인 "클래스 내부에서 모든 걸 다 처리하는 방식"과 전혀 다름
이건 어떤 디자인 패턴일까?
1. 제어의 역전 (Inversion of Control, IoC)
일반적인 클래스는 내부에서 제어 흐름을 정의하지만, Promise는 다르다.
실행 흐름을 외부 함수 (executor)에게 넘기며, 내부는 단순히 "성공/실패 처리기" 역할만 한다.
즉, 내부는 도구, 제어는 외부가 한다. 이게 바로 제어의 역전이다.
이를 통해 어떤 비동기 작업을 하든 상관없이, Promise는 동일한 방식으로 처리된다.
- 타이머든,
- API 호출이든,
- 파일 읽기든,
핵심 비동기 작업만 바꿔서 사용할 수 있다.
2. 공개 디자인 패턴 (Public Constructor Pattern)
내가 느낀 가장 인상 깊은 점
- 내부는 도구(resolve, reject)만 제공
- 실행은 외부에서 제어
- 생성자에서 한 번만 실행되고 상태는 불변
이런 구조는 단순히 코드의 분리뿐 아니라,
유연함, 재사용성, 안정성을 모두 고려한 설계라는 걸 알게 되었다.
마무리
처음엔 그냥 썼던 new Promise((resolve, reject) => {...}) 구조가
사실은 매우 정교하게 설계된 디자인 패턴의 결과라는걸 깨달았다.
내부는 도구만 제공하고, 로직은 외부에서 결정하자
'React' 카테고리의 다른 글
Vite 로컬 개발 시 모바일 테스트하는 방법 (0) | 2025.03.26 |
---|---|
Jest 환경설정 - Jest가 css 파일을 불러오지 못할 때 (0) | 2025.02.19 |
React에서 "key" props란? (3) | 2024.10.05 |