드림코딩 유튜브 채널의 의 자바스크립트 강의를 보고 공부한 내용입니다!
출처 :
https://www.youtube.com/watch?v=s1vpVCrT8f4
https://www.youtube.com/watch?v=JB_yU6Oe2eE&t=676s
https://www.youtube.com/watch?v=aoQSOZfz3vQ&t=11s
앞의 비동기 처리 [1], [2] 를 하며 공부를 많이 하고 블로그도 많이 돌아다녔는데요! [3]쯤 오니까 드디어 감이 잡힙니다. [1]과 [2]에서 제가 글에 쓰는걸 빠트리고 넘어간 부분도 많구요.
2023.04.04 - [백엔드/javaScript] - [Js] 비동기 처리 [1] 비동기 처리를 알아보자!(setTimeout)
2023.04.05 - [분류 전체보기] - [Js] 비동기 처리 [2] callback과 promise를 알아보자!
그래도 차근차근 공부해서! 전보다는 아는게 많은 제가 되었습니다! 헤헷
자바스크립트 비동기 처리에 대해 이야기를 다시 해보자면!
1. 자바 스크립트는 싱글 스레드로, 자바 스크립트 코드 자체는 동기적으로 실행됩니다.
위에서부터 아래로 쭉~ 순서대로 실행됩니다.
2. 따라서 자바스크립트 코드 중간에 시간이 오래걸리는 함수가 끼어있으면 사용자는 그 시간을 오롯이 기다려야합니다.
예를들어, 사용자의 정보를 받아오고 화면을 보여주는 코드가 있다고 했을 때, 아무것도 없는(?) 순수한(?) 자바스크립트 코드에서는 먼저 사용자의 정보을 받아온 후에야 화면을 볼 수 있습니다. 그래서 사용자의 역할을 받아오는 데 10초가 걸린다면, 사용자는 10초동안 텅 빈 화면만을 보고 있어야 합니다. 화면을 보여주는 코드가 뒤에 있으니까요.
3. 사용자가 10초동안 빈 화면만 보고 있지 않으려면 화면을 출력하는 코드가 먼저 나오게 해야합니다. 이때 사용하는 게 비동기처리입니다. webAPI로 비동기 함수를 옮겨놓으면, 이벤트 루프가 비동기 함수를 큐에 넣어두고, 콜 스택에 아무것도 없을 때 콜 스택으로 보냅니다.
이 순서에 관한 내용은 비동기 처리 [1]에 있습니다.
4. 그러면 사용자는 사용자의 정보를 받는 동안에도 화면을 볼 수 있습니다.
1~4까지의 과정을 비동기 처리라고합니다.
[1]과 [2]에서는 callback, setTimeout, promise를 살펴봤습니다. [3]에서는 그 유명한! async/await를 알아보려고 합니다!!
async/await는 그 유명한 쓰임새에 비해 적용 방법이 아주 간단합니다! 별거 없다고 주위에서도 강의에서도 그러던데... 정말 개념 자체는 별거 없더라구요... 별거 없는데... async/await까지 다져야 할 개념이 너무 많다는게... 또륵,,🥲
사용법은! 믿기지 않겠지만! function 앞에 async를 붙이면 됩니다. 벌써 반이나 지났어요! async가 promise를 생성해주는데, 우리는 이 프로미스를 await를 통해 적절하게 처리해주기만 하면 됩니다. 사용방법 끝! 참,,, 쉽,,,긴,,,하,,죠.....?😭
예제를 통해 차근차근 async/await를 살펴봅시다.
async/await의 기본 문법은 다음과 같습니다.
function firstFunction() {
// promise를 반환
return new Promise((resolve, reject) => {
//resolve일때 할 동작
const firstResult = ['1. resolve 일때 promise를 반환']
resolve(firstResult);
}
);
};
async function secondFunction() {
const secondResult = await firstFunction();
const thridResult = ['+ second로 first를 받아서 third에 넣음'];
// firstFunction의 promise를 받은 후에 할 동작들
return [secondResult + thridResult];
};
secondFunction().then(console.log);
// 결과 : [ '1. resolve 일때 promise를 반환+ second로 first를 받아서 third에 넣음' ]
콘솔창에 [1. resolve 일때 promise를 반환+ second로 first를 받아서 third에 넣음]을 확인할 수 있습니다.
사실 이렇게 보면 async await만의 특별한 점을 찾기가 힘들어보입니다. 그냥 promise를 쓰는것과 큰 차이가 없어 보여서요. 아주 간단한 기본 형태라서 그렇습니다. 하지만 좀 더 복잡하게 비동기처리를 해야하면 어떨까요? 위의 코드에 setTimeout 함수까지 추가해봅시다.
function firstFunction() {
return new Promise((resolve, reject) => {
setTimeout(() => {
const firstResult = ['1. resolve 일때 promise를 반환']
resolve(firstResult);
}, 3000)
}
);
};
async function secondFunction() {
const secondResult = await firstFunction();
const thridResult = ['+ second로 first를 받아서 third에 넣음'];
return [secondResult + thridResult];
};
secondFunction().then(console.log);
// 결과 : 3초 뒤에 [ '1. resolve 일때 promise를 반환+ second로 first를 받아서 third에 넣음' ] 가 등장
비동기 처리를 한 함수기때문에 firstFunction이 끝날 때까지 secnodFuctionr이 동작할 수 없습니다. 그래서, 결과는 3초 뒤에 나옵니다!
pormise보다 조금 더 간결하게 쓸 수 있는 느낌적인...느낌... ,,, 저같은 코딩 뉴비에겐 거기서 거기인거 같기두,,,,,머쓱,
예를들어서 코드를 더 짜보면... 강의내용을 참고한 코드로 살펴봅시다! 아침으로 사과와 고구마를 먹습니다. 사과와 고구마를 가져오는데 (말도 안되지만🥸) 1초씩 걸린다고 가정합니다. async/await를 적용해서 코드를 만들면 다음과 같습니다.
function delay(ms) {
return new Promise(reslove => setTimeout(reslove, ms));
};
async function getApple() {
await delay(1000);
// throw 'error';
return '🍏';
};
async function getGoguma() {
await delay(2000);
return '🍠';
};
function pickFruits() {
return getApple()
.then(apple => {
return getGoguma()
.then( goguma => `${apple} + ${goguma}`);
});
}
pickFruits().then(console.log);
// 🍏+🍠
콘솔창에 3초 뒤 결과로 🍏+🍠 를 볼 수 있습니다.
... 근데 왜 3초가 걸릴까요? 라고 물어보신다면, 비동기 처리 때문에 pickFruits는 apple을 가져오는데 1초를 먼저 쓰고, 그 다음 goguma를 가져오는데 2초를 쓰기 때문입니다. 비동기 처리 덕에 우리는 마치 동기 프로그래밍처럼 움직이는 코드를 봅니다.
async를 붙인 함수는 자동으로 promise를 생성합니다. 그리고 await는 .then 없이도 promise를 받습니다.
정확하게 말하자면, async는 함수 앞에 선언해서, 해당 함수가 비동기 함수임을 말해줍니다. 그 후 async 함수는 promise 객체를 반환해 promise 객체에 비동기 작업의 결과를 나타내는 값이나 에러를 줍니다.
await는 async에서부터 온 promise 객체가 fufilled될 때까지 함수의 실행을 잠시 중단합니다. promise를 기다리는 동안 (이벤트 루프? 스레드? 이 주체를 누구라고 해야할까용... 누군지 모르겠는데.... 암튼 누군가가... 통칭 컴퓨터가...😇)다른 작업을 처리할 수 있습니다. promise 객체가 실행되면 await는 그 결과를 반환합니다.
위의 설명을 바탕으로 pickFruits()코드를 좀 더 깔끔하게 async/await로 정리하면 다음과 같습니다.
async function pickFruits() {
const apple = await getApple();
const goguma = await getGoguma();
return `${apple} + ${goguma}`;
};
pickFruits().then(console.log);
// 🍏+🍠
async function인 getApple과 getGoguma가 올 때까지, 거기서 프로미스를 줄 때까지 기다리는 await 두개를 생성합니다. 그리고 await의 결과값을 return 해줍니다! 콘솔창의 결과는 같습니다. 걸리는 시간도 똑같습니다.
. then이 아니라 그냥 console.log로 결과값을 바로 확인하려고 하면 콘솔창에 promise <pending> 이라는 결과를 볼 수 있는데 그래도 결과는 똑같이 나오긴 합니다. 저런 말이 콘솔창에 등장하는 이유는, console.log만으로는 프로미스를 받을 수 없기 때문입니다. await가 반환하는 것이 promise의 결과값이기 때문에 promise의 결과를 받을 수 있는 .then으로 확인해야 합니다.
너무 간단한거 같은데... async / await의 전부입니다... 네 저도 당황스럽지만 진짜입니다. 그냥 Promise를 쓰는 것과 큰 차이가 없어 보이지만, 코드가 길고 복잡해질때 async/await가 더 유용합니다. 코드의 가독성이 높아지고 깔끔해지기 때문입니다. ㅠㅠ 프로젝트에서 이를 잘 적용해서 사용하는 건... 우리의 몫입니다... 개념 다지기는 정말 이걸로 끝입니다...
마지막으로... 제가 [1] 에서, 비동기 처리가 우선순위를 정해주는 것 같다... 라고 말을 했었는데, async/await에 대해 챗GPT는 동기적으로 움직이도록 하는거라고 하네요... async/await를 쓰면서 이해가 안가는게 많아서 챗 GPT한테 물어봤거든요. 그런데 아직 한국어 완벽 패치가 안된 챗 GPT라서... 좀 어려운 내용에 대해 꼬치꼬치 캐물으면 답변이 점점 산으로 가는 것 같아요.
저기 검은색으로 밑줄 친 부분입니다. 비동기 처리를 동기처럼 처리한다! 는 좀 섣부른 일반화라고 생각했는데... 아닌가봐요... 그냥 동기 프로그래밍처럼 하게 해주는걸로 생각해도 되나? 머쓱,.,,.. 역시 배움이 짧고 지식이 없으니 모자란 게 많네요. 마지막 [4] 에서는 [2] promise에서 짠 코드를 async/await를 적용해보는 걸로 마무리 하겠습니다!
[Js] 비동기 처리 [2] callback과 promise를 알아보자! (0) | 2023.04.05 |
---|---|
[Js] 비동기 처리 [1] 비동기 처리를 알아보자!(setTimeout) (0) | 2023.04.04 |