Promise란?
자바스크립트를 처음 입문하는 입장에서, 기본적인 문법을 훑고나면 '비동기'에 대한 개념이 등장한다. 그와 동시에 소개 되는 것이 바로 promise인데, ECMAScript 2015에서 본격적으로 추가된 문법이라고 한다. 비동기는 어렵게 풀자면 한도 끝도 없겠지만, 입문자의 입장에서 이해한 바로는 하나의 코드가 실행되는 중에 다른 코드가 실행될 수 있는 것이다. 물론 자바스크립트 자체는 싱글 스레드에 동기적인 언어지만, web API 등의 도움을 받아 자바스크립트는 비동기적인 수행을 할 수 있다.
promise, 왜 생겨났는가?
promise의 문법이 아직 제공되지 않을 때는 모든 걸 콜백으로 처리했다고 한다. 단순하게 생각해서, 3초 뒤 특정 코드를 실행하고 싶은데, 실행이 되면 수행할 내용, 에러가 나면 수행할 내용을 모두 콜백 함수의 형태로 넘기고, 또 그 안에서 예외 사항이나 조정이 필요하면 또 콜백 함수를 넘기고... 아무튼 복잡해지기 쉬운 상황이었고, 이런 것을 소위 콜백 지옥으로 부른다.
updatedEntry.forEach(function(entry) {
entry.save(function(error, savedEntry) {
if(error) { console.log(error); }
fetchClientsUsingSavedEntry(savedEntry, function(error, clients) {
if(error) { console.log(error); }
clients.forEach(client) {
client.sendUpdate(function(error, sentEntry) {
if(error) { console.log(error); }
});
}
});
});
});
위의 medium 포스팅에서 소개하고 있는 콜백지옥 함수.
사실 콜백 지옥의 문제는 작동이 되는가 안 되는가의 문제는 아니다. 즉, promise라는 것이 기존에 구현되지 않은 기능이라기보다는, 가독성의 문제가 심각하여 등장하게 된 셈이다. 이제는 어떤 코드를 실행하고, 이것이 성공적으로 완료되었을 때, 실패했을 때 등으로 나누어 조금 더 synchronous, 즉 동기적으로 코드를 작성할 수 있는 것이다.
promise 사용법
const promise = new Promise( (resolve, reject) = > {
// some code
});
promise자체는 Promise() 생성자를 활용하여 손쉽게 생성할 수 있다. 이 때 콜백 함수(executor) 하나를 넘겨주는데, 이 함수가 실행되면서 의도대로 성공하면 resolve, 그 외 오류로 인해 실패하는 경우 reject 를 활용하여 분기를 만들 수 있다. promise 는 성공, 실패, 처리중 이 3가지로 나뉘는데, 결국 성공이면 resolve, 실패면 reject, 처리 중이면 pending이 된다. 여기서 주의할 점은, Promise 객체 생성 시 그 안의 콜백함수는 바로 실행된다는 점이다.
현재 특정 promise의 상태를 알고 싶다면 console.log를 해볼 수 있다.
console.log(promise);
아래는 Treehouse의 비동기 강의에서 예시로 사용되었던 코드로, 성공과 실패, 그리고 넘겨 받은 값을 then과 catch를 이용해 어떻게 사용하는지 보여주고 있다.
const order = false;
const breakfastPromise = new Promise( (resolve, reject) => {
setTimeout(() => {
if (order)
resolve('Your order is ready. Come get it!');
else
reject(Error('Oh no there was a problem!'));
}, 3000);
});
breakfastPromise
.then( val => console.log(val) )
.catch( error => console.log(error));
.finally(() => {
console.log("finally");
});
breakfastPromise라는 promise는 3초 뒤 order가 true라면(즉 의도한 대로 무언가 동작했다는 것을 의미할 것이다) 'Your order is ready. Come get it!' 이라는 문자열을 반환할 것이다. 이렇게 성공하여 반환된 코드는 then이 받아서 넘겨받는 콜백함수에 적용한다. 실패한다면 catch가 받게된다. finally는 성공과 실패 여부와 상관 없이 실행되는 부분이다.
체이닝
fetchNumber
.then((num) => num * 2)
.then((nu) => num * 3)
.then((num) => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(num - 1);
}, 1000);
});
})
.then((num) => console.log(num));
https://www.youtube.com/watch?v=JB_yU6Oe2eE
유튜브를 통해 듣게 된 드림코딩 엘리님의 채널 강의에서 참고한 코드로, promise는 이렇게 체이닝 해서 사용할 수도 있다고 한다. 즉, then을 통해 뱉어낸 값이 단순한 값일 수도 있고, 또 다른 promise일 수도 있다는 것.
then함수의 return value와 관련해서 조금 더 상세한 설명은 이곳에서도 찾아볼 수 있다.
그래서 promise같은 걸 도대체 언제 쓰는가, 하는 의문이 생길 수 있는데, 주로 네트워크 통신이나 파일을 읽어오는 등의 시간이 오래 걸리는 부분에 프로미스&비동기적으로 처리하는 것이 좋다고 한다. 그럼 이런 걸 하고 있는 도중에도 웹사이트는 얼마든지 로딩 될 수 있고, 유저의 입장에선 유기적인 경험을 할 수 있을 것이다.
'JavaScript > 문법 공부' 카테고리의 다른 글
async, await, promise로 비동기 동기 처리하기 (0) | 2020.08.16 |
---|---|
Node JS 표준 입력 받기 (2) | 2020.07.27 |