이렇게 생각해보면 이해하기 쉬워요
정도가 되겠습니다.
- 비동기 작업은
성공
혹은실패
한다.- 비동기 작업은
요청
하는 쪽과처리
하는 쪽이 구분되어있다.- 프로미스의
resolve
,reject
는 비동기 작업의처리
과정에서성공
/실패
를 구분하는 방법이다.
자바스크립트 공부를 막 시작했을 무렵 어디를 가도 프로미스
라는 단어가 따라왔다.
딱봐도 엄청 중요한 거 같으니까 공부를 해봐야지!
콜백헬이 어쩌고....pending..fulfilled...rejected.. 체이닝이 가능....
"아 그렇구나~" (모름)
"콜백이 별로라서 만든거라는데 이것도 그냥 콜백아니야?" (아님)
"근데 이걸 어떻게 쓰라는거야?" (진짜 모름)
당시 나의 머리속
- 콜백은 나쁜거!
- 프로미스는 좋은거!
- pending, fulfilled, rejected? 3가지 상태? 이름겁나 헷갈리네
promise.then(result=>{})
이렇게 쓰는거라고?new Promise((resolve,reject)=>{})
? 얘는 왜 모양이 달라?setTimeout
===뇌정지
- 코드 보면 이해는 되는데
(아님)
이걸 어떻게 써야되지?
공부를 하면 할수록 이해가 되기는 커녕 머리속은 뒤죽박죽이 되어갔다.
그렇다고 프로미스를 안 쓸 수도 없는 노릇이니
겉핥기 수준의 이해도를 가지고 프로젝트에서 프로미스를 사용하기 시작했고,
삽질에 삽질을 거듭한 끝에 어느정도 활용할 수는 있게되었다.
조금이나마 경험이 쌓였고, 프로미스 관련 글을 읽으면 바로 이해할 수 있게 됐으니 해피한 엔딩인가? 아니다.
할 줄 아는 것
과 누군가에게 알려줄 수 있는 것
은 다르다. 내가 알고 있(다고 착각하)는 내용을 정리할 겸,
뭘 모르는지 모르는 상태
에서 도움이 될 만한. 모르는 사람의 입장에서
쓰여진 안내서를 쓰고싶은 생각이 들었다.
그래서 쓰게 된 글이고, 굉장히 두서가 없이 쓰인 글이라ㅎㅎ 읽다가 화가 나는 사람이 없기를 빈다.
안 읽어도 되는 서문까지 읽어주셔서 감사하다는 인사를 드리며 앞서 말한대로 두서없이 시작하도록 하겠다.
프로미스에 대해서 막 공부를 시작했을 때, 이런 생각을 했었다.
promise.then(result=>{})
이렇게 쓰는거라고?new Promise((resolve,reject)=>{})
? 얘는 왜 모양이 달라?
분명히 봤던 내용인데, 매번 볼 때마다 까먹고 헷갈렸다.
then()
은 눈에 익었는데, resolve, reject
는 예제 말고는 본 적이 없어서 그런지 봐도 봐도 처음보는 거 같았다.
지금 생각해보면 전혀 어려운 게 아니었는데 왜 그렇게 헷갈렸을까?
기본적인 내용을 잊고, 달을 가리키는데 손가락만 보았기 때문이다.
콜백 함수
부터 제대로 이해하자.내가 했던 실수는 콜백 함수를 알고있다
고 착각한 것이다.
- 비동기 요청과 함께
콜백 함수
를 전달한다.- 비동기 요청이 처리된다.
- 전달한
콜백 함수
가 실행된다.
너무도 당연한 말이지만, 당연한 것 만큼 잊기 쉬운 것도 없다.
콜백을 이용해 비동기 처리를 몇번 해보면, 비동기 처리를 "요청"하는 입장
에서만 생각하게 된다.
내가 작성한 콜백함수를 누군가 실행한다
는 사실은 자연스럽게 잊게 되고, 결국 프로미스의 생성
과 사용
이 헷갈리게 되는 원인이된다.
간단한 예제를 통해서 비동기 요청을 "처리"하는 입장
을 고려해보자.
콜백 함수
는 어떻게 실행될까?주의 : 사용된 예제 코드는 실제로 동작하지 않습니다.
콜백함수를 이용해 비동기 작업을 요청하는 예시를 보자.
// App.js
import DB from './DB.js';
DB.getAllUsers( function myCallback(error, users) {
if(error) {
console.log('에러 발생!');
console.log(error);
return;
}
console.log('성공!');
console.log(users);
})
DB에 모든 유저의 정보
를 요청한 뒤, 그대로 출력하는 간단한 코드다.
error
도 받는다.정도만 신경써보자.
DB는 어떻게 myCallback()
을 처리할까?
// DB.js
const user_list = ['철수', '영희', '삼식이', '봉식이'];
function getAllUsers (callback_function) {
if(user_list.length === 0) {
callback_function(new Error('아무도 없다!'), undefined);
return;
}
callback_function(undefined, user_list);
}
getAllUsers라는 함수는 callback_function이라는 인자를 받아서,
유저가 없으면 callback_function( 에러, undefined )
유저가 있으면 callback_function( undefined, 유저목록 )
형태로 실행한다.
첫 번째에는
에러
를, 두 번째에는유저목록
을 넣어서 실행하는 것은하나의 약속
이다.
이 약속만 지킨다면 누구든지
function myCallback(error, users) {
// 하고 싶은 일
}
위와 같은 형태로 콜백함수를 작성하여 DB.js에 비동기 작업을 요청할 수 있다.
작은 결론
- 비동기 요청은
성공
혹은실패
한다.- 비동기 작업을 요청하는 사람은
성공하는 경우
/실패하는 경우
를 고려해야 한다.- ★ 비동기 작업을 처리하는 사람도
성공하는 경우
/실패하는 경우
를 고려해야 한다.
3번의 상황을 고려해야, Promise 객체의 resolve
, reject
를 헷갈리지 않고 이해할 수 있다.
// 아무 생각없이 아래 코드를 보면 헷갈리기만 한다.
new Promise((resolve, reject)=>{
if(조건) {
resolve('성공!');
}
reject('실패');
})
DB.js를 콜백 방식
에서 프로미스 방식
으로 바꾸는 예제를 보면서 확인해보자.
// DB.js
const user_list = ['철수', '영희', '삼식이', '봉식이'];
// 콜백 방식
function getAllUsers (callback_function) {
if(user_list.length === 0) {
callback_function(new Error('아무도 없다!'), undefined);
return;
}
callback_function(undefined, user_list);
}
// 프로미스 방식
function getAllUsers () {
return new Promise((resolve, reject)=>{
if(user_list.length === 0) {
// 실패
reject(new Error('아무도 없다!'))
} else {
// 성공
resolve(user_list)
}
})
}
코드를 이해못해도 괜찮다.
콜백 방식이 성공
/실패
를 구분하는 방법은 콜백함수의 인자 위치
(순서)이고
프로미스 방식은 성공
/실패
가 resolve
/reject
호출로 구분된다는 것만 확인하면 된다.
- 비동기 작업은
성공
혹은실패
한다.- 비동기 작업은
요청
하는 쪽과처리
하는 쪽이 구분되어있다.- 프로미스의
resolve
,reject
는 비동기 작업의처리
과정에서성공
/실패
를 구분하는 방법이다.
뜬구름잡는 얘기처럼 들릴 수도 있겠다.
하지만 프로미스는 비동기 작업
과 연관이 깊고, 비동기 작업은 요청하는 쪽
과 처리하는 쪽
이 나뉘어져 있기 때문에 반드시 구분해서 생각을 해야 정확하게 이해할 수 있다.
어려운 내용일수록 기본에 충실해야 편안하게 이해할 수 있다. 봐도봐도 모르겠다면 내가 놓치고 있는 기본적인 부분이 없는지 차분하게 생각해보자!
아,,,이제야,,,이런 좋은 글을 보다니 ㅠ ㅠ항상 의미없이 쓰던코드가 이제야 눈에 확들어옵니다, 너무 설명 잘해주셔서 금방이해갔습니다 ㅠ ㅠ 감사합니다
new Promise((resolve, reject) => {
pool.getConnection()
.then(conn => {
글 잘 읽어보았습니다. 저도 생각해보니 콜백에 대해서 명확히 이해하지 못한 상태였던거 같습니다.
아직도 그렇거 같구요 ㅎㅎ 질문 하나 드려도 될까요?
위 코드에서 (resolve, reject) 부분은 익명 콜백 함수인거죠..?
마찬가지로 아래에 getConnection 을 성공했을때 (then) 뒤에 인자로 오는 conn 도 콜백함수의 인자인거구요. 저런 형태들이 모두 콜백함수로 이해했는데 맞는지 모르겠네요. 다만 resolve 든 conn 이든 인자의 값들은 각각 정해진 다른 형태로 되어있구요.
Promise 가, 옛날에 처음 봤을땐 이게 뭐지 싶었는데
코드를 직접 몇번 작성해봐야 이해되더라구요!