Promise
2025-04-23 TIL-Promise
Promise
자바스크립트의 Promise
는 비동기 작업을 관리하고, 해당 작업의 성공 또는 실패 결과를 나중에 사용할 수 있도록 하는 객체입니다. 정리하자면, Promise는 비동기 작업의 완료 여부를 약속해주는 개념이라고 할 수 있다.
자바스크립트는 비동기 처리를 위한 콜백 함수를 많이 사용한다. 하지만 콜백 함수는 코드가 복잡해짐에 따라 콜백이 중첩되는 “콜백 지옥” 문제를 야기할 수 있다. Promise는 이러한 비동기 처리의 가독성을 높이고, 코드의 흐름을 명확하게 관리할 수 있도록 도와주는 방식이다.
Promise의 상태
- Pending: 비동기 작업이 아직 완료되지 않은 초기 상태
- Fulfilled: 비동기 작업이 성공적으로 완료되어 값을 반환한 상태
- Rejected: 비동기 작업이 실패하여 오류를 반환한 상태
Promise 객체는 비동기 작업을 수행할 함수를 인자로 받아서 실행하며, 이 함수는 resolve()
와 reject()
라는 두 가지 콜백을 받는다.
resolve(value)
는 비동기 작업이 성공했을 때 호출되어 Promise를Fulfilled
상태로 전환하며, 결과 값을 전달한다.reject(error)
는 비동기 작업이 실패했을 때 호출되어 Promise를Rejected
상태로 전환한다.
Pending
상태에서 Fulfilled
또는 Rejected
상태로 전환되면, 이후에는 다른 상태로 전환되지 않는다. 이로 인해 해당 작업의 최종 결과를 안정적으로 처리할 수 있다.
Promise 메서드와 흐름 제어
Promise는 아래와 같은 메서드들을 통해 비동기 작업의 흐름을 제어할 수 있다:
-
then(onFulfilled, onRejected)
: 작업이 성공했을 때와 실패했을 때 각각 실행할 콜백을 등록할 수 있다. 중요한 점은then()
메서드는 항상 새로운 Promise를 반환하기 때문에, 이를 연속적으로 체이닝하여 사용할 수 있다. -
catch(onRejected)
:then()
에서 발생한 에러를 처리하기 위한 메서드이다. 에러 핸들링을 깔끔하게 분리할 수 있다. -
finally(onFinally)
: 작업의 성공 여부와 상관없이 마지막에 항상 실행되는 콜백을 등록할 수 있다. 정리 작업 등에 유용하다.
여러 개의 Promise를 동시에 다루기
자바스크립트는 여러 비동기 작업을 동시에 처리할 수 있는 메서드들도 제공한다:
Promise.all([p1, p2, ...])
: 모든 Promise가 Fulfilled될 때까지 기다리며, 하나라도 Rejected되면 전체가 실패한다.Promise.allSettled([p1, p2, ...])
: 모든 Promise가 완료될 때까지 기다리며, 성공/실패 여부에 상관없이 각각의 결과를 객체 형태로 반환한다.Promise.race([p1, p2, ...])
: 가장 먼저 종료되는 하나의 Promise 결과만 반환한다. 성공이든 실패든 가장 빠른 결과가 리턴된다.
Promise의 단점
Promise는 많은 장점을 제공하지만, 몇 가지 단점도 존재한다:
-
에러 처리의 복잡성
단순한 then-catch 구조에서는 문제가 없지만, 여러 단계의 체이닝 또는 분기 처리가 복잡해지면 특정 단계에서의 에러를 세밀하게 처리하기가 어렵다. 에러 흐름을 정확히 추적하고 관리하려면 코드가 복잡해질 수 있다. -
콜백 지옥을 완전히 해결하지는 못함
then().then().then()
처럼 체인을 계속 사용하면 여전히 들여쓰기가 많아지고, 로직이 복잡해지면 가독성이 떨어질 수 있다. 즉, Promise는 콜백보다는 낫지만 완벽한 해결책은 아니다.
async/await과의 관계
이러한 단점을 보완하기 위해 등장한 것이 async/await
이다. 이 문법은 Promise를 기반으로 하면서도, 비동기 코드를 마치 동기 코드처럼 작성할 수 있게 도와준다. 예외 처리도 try...catch
문을 통해 더 직관적이고 간결하게 다룰 수 있다. 그래서 복잡한 비동기 로직을 다룰 때는 async/await
이 훨씬 가독성 좋고 유지보수도 쉽다.