1. Promise

JavaScript는 비동기 처리를 할 때 콜백 함수를 사용한다. 하지만 함수 호출이 중첩되면서 가독성이 떨어져 코드를 이해하는데 어려움이 생기고 복잡도가 증가하였다. 콜백 지옥에서 벗어날 수 있도록 ES6에서 Promise가 등장했다. 프로미스는 성공적으로 수행된다면 그 결괏값을, 실패한다면 에러를 전달한다. 코드를 간결하게 만들어 처리의 성공과 실패를 더욱 쉽게 관리할 수 있기 때문에 프로미스를 사용한다.

프로미스는 제작 코드와 소비 코드로 이루어져 있다. **제작 코드(Producing code)**는 정보를 전달하는 코드로 네트워크에서 사용자 데이터를 로드하는 코드이다. **소비코드(Consuming code)**는 생산 코드가 전달한 정보를 받는 코드로 로드된 사용자 데이터를 받는 코드이다.

예를 들어 놀이동산에 갔다고 가정해보자. 인기 있는 놀이기구는 기다리는 줄이 길어 몇 시간씩 기다려야 한다고 한다. 그래서 시간별로 예약받는데 휴대폰 번호를 적고 가면 탑승 가능한 시간에 알림을 보내준다고 한다.

Untitled

예약한 손님이 탑승할 수 있는 시간까지 시간이 걸리는 ‘놀이기구’가 제작코드이다. 놀이기구를 탈 수 있다고 알림을 받는 ‘손님’이 소비코드이다. 예약한 손님의 차례가 왔을 때 탑승 알림을 보내는 것이 프로미스로 제작코드와 소비코드를 연결해 준다.

1.1 Promise의 생성

const 프로미스 = new Promise(function(resolve, reject) {
	// 실행함수
});

먼저 new 연산자를 사용해 프로미스 객체를 만든다. 생성자 함수 new Promise()의 매개변수로 작성하는 함수를 **실행 함수(excutor)**라고 한다. 실행 함수는 resolve(), reject()를 매개변수로 받는다. 따로 만들지 않은 resolve()reject()가 어떻게 사용될 수 있나 싶지만, Promise가 만들어질 때 자바스크립트 엔진에 의해 자동으로 실행된다. resolve()는 비동기 작업이 성공적으로 처리되었을 때 결괏값(최종 데이터)과 함께 호출되고, reject()는 실패했을 때 에러 객체를 전달한다.

const 프로미스 = new Promise(function(resolve, reject) {
	resolve('🍓');
	resolve('🍌');
});

console.log(프로미스);

Untitled

반드시 실행 함수는 resolve(), reject() 둘 중 하나를 호출해야 한다. resolve()나 reject()를 각각 중복해서 호출하면 처음 호출한 게 적용되고 그 이후의 호출된 함수들은 무시된다.

1.2 Promise의 상태

프로미스 객체는 비동기 작업에 대한 상태와 결과를 관리한다. 프로미스가 생성된 직후에는 보류, 즉 pending이라는 상태를 갖는다. 그 이후 비동기 작업의 성공 여부에 따라 fulfilled 혹은 rejected라는 상태를 갖게 된다. 비동기 처리가 성공적으로 이행되어 resolve()가 호출되면 pending에서 fulfilled 상태로 전환되며, 만약 처리 도중 에러가 발생해 reject()가 호출되면 pending에서 rejected 상태로 전환된다. 이렇게 pending에서 fulfilled 혹은 rejected로 바뀌면 settled(해결된, 안정된) 상태가 되었다고 말하며, 한번 상태가 정해지면 다른 상태로 절대 변경될 수 없다. 프로미스는 하나의 결과를 갖기 때문이다.

Untitled

프로미스의 상태와 결과는 콘솔창에서 내부 슬롯을 통해 확인할 수 있다.