๐ ์๋ฐ์คํฌ๋ฆฝํธ Async/Await ๊ฐ๋ & ๋ฌธ๋ฒ ์ ๋ณต
์๋ฐ์คํฌ๋ฆฝํธ ๋น๋๊ธฐ ์ฒ๋ฆฌ 3๊ฐ์ง ๋ฐฉ์
์๋ฐ์คํฌ๋ฆฝํธ๋ ์ฑ๊ธ ์ค๋ ๋ ํ๋ก๊ทธ๋๋ฐ ์ธ์ด๊ธฐ ๋๋ฌธ์ ๋ฉํฐ ์์ ์ ํ๊ธฐ ์ํด์ ๋น๋๊ธฐ ์ฒ๋ฆฌ ๋ฐฉ์์ด ์์ฃผ ์ฐ์ธ๋ค. ๋น๋๊ธฐ ์ฒ๋ฆฌ๋ ๋ฐฑ๊ทธ๋ผ์ด๋๋ก ๋์๋๊ธฐ ๋๋ฌธ์ ๊ทธ ๊ฒฐ๊ณผ๊ฐ ์ธ์ ๋ฐํ๋ ์ง ์์ ์์ด, ์๋ฃ๋๋ฉด ๊ฒฐ๊ณผ๋ฅผ ๋ฐ์ ์ฒ๋ฆฌํ๊ธฐ ์ํด ์ฌ์ฉ๋๋ ๋ํ์ ์ธ ๋ฐฉ๋ฒ์ผ๋ก ์ฝ๋ฐฑ ํจ์(Callback) ์ ์ด๋ฅผ ๊ฐ์ ํ ํ๋ก๋ฏธ์ค ๊ฐ์ฒด(Promise)๊ฐ ์๋ค. ํ์ง๋ง ์๋น์ค ๊ท๋ชจ๊ฐ ์ปค์ง ์๋ก ์ฝ๋๊ฐ ๋ณต์กํด์ง์ ๋ฐ๋ผ ์ฝ๋๋ฅผ ์ค์ฒฉํด์ ์ฌ์ฉํ๋ค๊ฐ ๊ฐ๋ ์ฑ์ด ๋จ์ด์ง๊ณ ์ ์ง๋ณด์๊ฐ ์ด๋ ค์์ง๋ ์ํฉ์ด ๋ฐ์๋๊ฒ ๋๋๋ฐ, ์ด๋ฅผ Callback Hell, Promise Hell ์ด๋ผ๊ณ ๋ถ๋ฆฌ์ด๋ค.
/* Callback Hell */
getData (function (x) {
getMoreData (x, function (y) {
getMoreData (y, function (z) {
...
});
});
});
/* Promise Hell */
fetch('https://example.com/api')
.then(response => response.json())
.then(data => fetch(`https://example.com/api/${data.id}`))
.then(response => response.json())
.then(data => fetch(`https://example.com/api/${data.id}/details`))
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error(error));
์์ ์ฝ๋๋ฅผ ๋ณด๋ฉด ์ ์ ์๋ฏ์ด ์ฝ๋ฐฑ ํฌ์ ์ฝ๋๊ฐ ํ์ฒ๋ผ ๊ตฝ์ด ๋ณด๊ธฐ๊ฐ ์์ฑํด์ง๊ณ , ํ๋ก๋ฏธ์ค ํฌ๋ ์ง๋์น then ํธ๋ค๋ฌ ๋จ์ฉ์ผ๋ก ์ธํด ๊ตฌํํ๊ณ ์ ํ๋ ์๋๋ฅผ ํ๋ฒ์ ํ์ ํ ์๊ฐ ์๋ค.
์๋ฐ์คํฌ๋ฆฝํธ async ์ await ๋ ์ด๋ฐ ๋ฌธ์ ๋ค์ ํด๊ฒฐํ๊ธฐ ์ํด ํ์ํ์์ผ๋ฉฐ, ๋ฌธ๋ฒ์ ์์ด์๋ ํจ์ฌ ๋จ์ํด์ ธ ๊ฐ๋ ์ฑ๊ณผ ์ ์ง๋ณด์์ฑ์ ํฅ์ ์์ผ์ค๋ค.
async function getData() {
const response = await fetch('https://example.com/api');
const data = await response.json();
const response2 = await fetch(`https://example.com/api/${data.id}`);
const data2 = await response2.json();
const response3 = await fetch(`https://example.com/api/${data.id}/details`);
const data3 = await response3.json();
console.log(data3);
}
getData();
์ ์ฝ๋๋ฅผ ๋ณด๋ฉด ์ฝ๋ฐฑ ํฌ๊ณผ ๊ฐ์ ํ๋ฆฌ ๊ตฝ์ ์ฝ๋๋ ์์ผ๋ฉฐ, ํ๋ก๋ฏธ์ค ํฌ๊ณผ ๊ฐ์ ์ง๋์น then ํธ๋ค๋ฌ ๋จ์ฉ์ผ๋ก ์ธํ ๊ฐ๋ ์ฑ ํํฅ๋ ์๋ค. ๋ง์น ํจ์์ ๋ฆฌํด๊ฐ์ ๋ณ์๊ฐ ๋ฐ๋ ์ ์๋ฌธ ํ์๋๋ก ๋์ด ์์ด ์ฝ๋๊ฐ ์๋ํ๊ณ ์ ํ๋ ๋ฐ๋ฅผ ๋์ผ ์ฝ๋ ๋ ๋ฒจ ๋ผ์ธ์์ ์์๊ฐ ์์ด ํจ์ฌ ํธํ๋ค.
์๋ฐ์คํฌ๋ฆฝํธ async / await
async/await๋ ES2017์ ๋์ ๋ ๋ฌธ๋ฒ์ผ๋ก์, Promise ๋ก์ง์ ๋ ์ฝ๊ณ ๊ฐ๊ฒฐํ๊ฒ ์ฌ์ฉํ ์ ์๊ฒ ํด์ค๋ค. ์ ์ํด์ผ ํ ์ ์ด async/await๊ฐ Promise๋ฅผ ๋์ฒดํ๊ธฐ ์ํ ๊ธฐ๋ฅ์ด ์๋๋ผ๋ ๊ฒ์ด๋ค. ๋ด๋ถ์ ์ผ๋ก๋ ์ฌ์ ํ Promise๋ฅผ ์ฌ์ฉํด์ ๋น๋๊ธฐ๋ฅผ ์ฒ๋ฆฌํ๊ณ , ๋จ์ง ์ฝ๋ ์์ฑ ๋ถ๋ถ์ ํ๋ก๊ทธ๋๋จธ๊ฐ ์ ์ง๋ณด์ํ๊ฒ ํธํ๊ฒ ๋ณด์ด๋ ๋ฌธ๋ฒ๋ง ๋ค๋ฅด๊ฒ ํด์ค ๋ฟ์ด๋ผ๋ ๊ฒ์ด๋ค.
๋ง์น ์๋ฐ์คํฌ๋ฆฝํธ์์ prototype๊ณผ class ๋ฌธ๋ฒ์ ์ฐจ์ด๋ผ๊ณ ๋ด๋ ๋ฌด๋ฐฉํ๋ค. ์๋ฐ์คํฌ๋ฆฝํธ๋ฅผ ์๋ฐ์ ๊ฐ์ด ํด๋์ค ํ์์ ๋ฌธ๋ฒ์ ์ง์ํ๋๋ผ๊ณ ๋ด๋ถ์ ์ผ๋ก๋ ์ฌ์ ํ ํ๋กํ ํ์ ํ์์ผ๋ก ๊ฐ์ฒด ์งํฅ์ ์ฒ๋ฆฌํ๋ฏ์ด, async/await๋ ๋ด๋ถ์ ์ผ๋ก๋ ํ๋ก๋ฏธ์ค ๋ฐฉ์์ผ๋ก ๋น๋๊ธฐ๋ฅผ ์ฒ๋ฆฌํ์ง๋ง, ๋ฌธ๋ฒ ํํ๋ง ์ข ๋ ๊ฐํธํ ์คํ์ผ๋ก ์ถ๊ฐํ ๊ฒ์ผ๋ก ๋ณด๋ฉด ๋๋ค.
async / await ๊ธฐ๋ณธ ์ฌ์ฉ๋ฒ
async ์ await ๋ ์ ์ฐจ์ ์ธ์ด์์ ์์ฑํ๋ ์ฝ๋์ ๊ฐ์ด ์ฌ์ฉ๋ฒ๋ ๊ฐ๋จํ๊ณ ์ดํดํ๊ธฐ๋ ์ฝ๋ค. function ํค์๋ ์์ async ๋ง ๋ถ์ฌ์ฃผ๋ฉด ๋๊ณ , ๋น๋๊ธฐ๋ก ์ฒ๋ฆฌ๋๋ ๋ถ๋ถ ์์ await ๋ง ๋ถ์ฌ์ฃผ๋ฉด ๋๋ค.
๋ค์์ setTimeout ๋น๋๊ธฐ ํจ์๋ฅผ ์ด์ฉํด delay ๊ธฐ๋ฅ์ ๊ตฌํํ ํ๋ก๋ฏธ์ค ๊ฐ์ฒด ๋น๋๊ธฐ ํจ์๋ฅผ ๊ธฐ์กด Promise.then() ๋ฐฉ์๊ณผ async/await ๋ฐฉ์์ผ๋ก ๋๊ฐ์ด ์ฒ๋ฆฌํ์ง๋ง ๋ค๋ฅด๊ฒ ์ฝ๋๋ฅผ ๊ตฌํํ ์์ ์ด๋ค.
// ํ๋ก๋ฏธ์ค ๊ฐ์ฒด ๋ฐํ ํจ์
function delay(ms) {
return new Promise(resolve => {
setTimeout(() => {
console.log(`${ms} ๋ฐ๋ฆฌ์ด๊ฐ ์ง๋ฌ์ต๋๋ค.`);
resolve()
}, ms);
});
}
// ๊ธฐ์กด Promise.then() ํ์
function main() {
delay(1000)
.then(() => {
return delay(2000);
})
.then(() => {
return Promise.resolve('๋');
})
.then(result => {
console.log(result);
});
}
// ๋ฉ์ธ ํจ์ ํธ์ถ
main();
// async/await ๋ฐฉ์
async function main() {
await delay(1000);
await delay(2000);
const result = await Promise.resolve('๋');
console.log(result);
}
// ๋ฉ์ธ ํจ์ ํธ์ถ
main();
์์ ์ฝ๋๋ฅผ ๋ณด๋ฉด promise๋ then ๋ฉ์๋๋ฅผ ์ฐ์์ ์ผ๋ก ์ฌ์ฉํ์ฌ ๋น๋๊ธฐ ์ฒ๋ฆฌ๋ฅผ ํ์ง๋ง, async/await๋ await ํค์๋๋ก ๋น๋๊ธฐ ์ฒ๋ฆฌ๋ฅผ ๊ธฐ๋ค๋ฆฌ๊ณ ์๋ค๋ ๊ฒ์ ์ง๊ด์ ์ผ๋ก ํํํ๊ณ ์์์ ๋ณผ ์ ์๋ค. async/await์ ์ฅ์ ์ ๋น๋๊ธฐ์ ์ ๊ทผ๋ฐฉ์์ ๋๊ธฐ์ ์ผ๋ก ์์ฑํ ์ ์๊ฒ ํด์ฃผ์ด ์ฝ๋๊ฐ ๊ฐ๊ฒฐํด์ง๋ฉฐ ๊ฐ๋ ์ฑ์ ๋์ฌ์ ธ ์ ์ง๋ณด์๋ฅผ ์ฉ์ดํ๊ฒ ํด์ค๋ค.
async ํค์๋
async ํค์๋๋ ์ด๋ ต๊ฒ ์๊ฐํ ํ์์์ด await๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํ ์ ์ธ๋ฌธ ์ ๋๋ก ์ดํดํ๋ฉด ๋๋ค. ์ฆ, function ์์ async์ ๋ถ์ฌ์ค์ผ๋ก์จ, ํจ์๋ด์์ await ํค์๋๋ฅผ ์ฌ์ฉํ ์ ์๊ฒ ๋๋ค. ์ด๋ ๋ฐ๋๋ก ๋งํ๋ฉด await ํค์๋๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํด์ ๋ฐ๋์ async function ์ ์๊ฐ ๋์ด ์์ด์ผ ํ๋ค๋ ๋ง๊ณผ ๊ฐ๋ค.
// ํจ์ ์ ์ธ์
async function func1() {
const res = await fetch(url); // ์์ฒญ์ ๊ธฐ๋ค๋ฆผ
const data = await res.json(); // ์๋ต์ JSON์ผ๋ก ํ์ฑ
}
func1();
// ํจ์ ํํ์
const func2 = async () => {
const res = await fetch(url); // ์์ฒญ์ ๊ธฐ๋ค๋ฆผ
const data = await res.json(); // ์๋ต์ JSON์ผ๋ก ํ์ฑ
}
func2();
async ๋ฆฌํด๊ฐ์ Promise ๊ฐ์ฒด
์ด๋ ๊ฒ async ํค์๋๋ฅผ ๋ถ์ธ function์์ ๊ฐ์ ๋ฆฌํดํ๋ฉด ์ด๋ป๊ฒ ๋ ๊น?
async function func1() {
return 1;
}
const data = func1();
console.log(data); // ํ๋ก๋ฏธ์ค ๊ฐ์ฒด๊ฐ ๋ฐํ๋๋ค
๋จ์ ์ ์ 1์ ๋ฆฌํดํ์์๋ ์ ๊ฒฐ๊ณผ์์ ๋ณด๋ฏ์ด, ์ดํ(fulfilled) ์ํ์ ํ๋ก๋ฏธ์ค ๊ฐ์ฒด ํํ๋ก ๋ฐํ๋จ์ ๋ณผ ์ ์๋ค. ์ด๋ฅผ ํตํด async function์์ ์ด๋ค ๊ฐ์ ๋ฆฌํดํ๋ ๋ฌด์กฐ๊ฑด ํ๋ก๋ฏธ์ค ๊ฐ์ฒด๋ก ๊ฐ์ธ์ ธ ๋ฐํ ๋๋ค๋ ํน์ง์ ์ ์ ๊ฐ ์๋ค.
๋ค๋ฅธ Promise ์ํ๋ฅผ ๋ฐํํ๊ธฐ
๋ฌผ๋ก ์ง์ ํ๋ก๋ฏธ์ค ์ ์ ๋ฉ์๋๋ฅผ ํตํด ๋ค์๊ณผ ๊ฐ์ด ํ๋ก๋ฏธ์ค ์ํ(state)๋ฅผ ๋ค๋ฅด๊ฒ ์ง์ ํ์ฌ ๋ฐํ์ด ๊ฐ๋ฅํ๋ค.
async function resolveP() {
return Promise.resolve(2);
}
async function rejectP() {
return Promise.reject(2);
}
reject ๊ฐ์ ๊ฒฝ์ฐ ์์ ๊ฐ์ด Promise.reject() ์ ์ ๋ฉ์๋๋ฅผ ํตํด ๋ฐํ๋๋ ํ๋ก๋ฏธ์ค ์ํ๋ฅผ ์คํจ(rejected) ์ํ๋ก ์ง์ ํด์ค ์ ์์ง๋ง, async ํจ์ ๋ด๋ถ์์ ์์ธ throw ๋ฅผ ํด๋ ์คํจ ์ํ์ ํ๋ก๋ฏธ์ค ๊ฐ์ฒด๊ฐ ๋ฐํ๋๊ฒ ๋๋ค.
async function errorFunc() {
throw new Error("ํ๋ก๋ฏธ์ค reject ๋ฐ์์ํด");
}
๋ง์ผ async function์์ ์ผ๋ถ๋ฌ return์ ํ์ง ์์๋ ์๋์ผ๋ก return undefiend ์ผ๋ก ์ฒ๋ฆฌ ๋๊ธฐ ๋๋ฌธ์ ์ด์ฐ๋ซ๋ ๋ฌด์กฐ๊ฑด ํ๋ก๋ฏธ์ค ๊ฐ์ฒด๋ฅผ ๋ฐํํ๊ฒ ๋๋ค
async ํจ์์ then ํธ๋ค๋ฌ
๋ง์ ์๋ด๊ธฐ๋ค์ด ์ค๋กํ ํ๋ก๋ฏธ์ค ๊ฐ์ฒด์๋ง then ํธ๋ค๋ฌ๋ฅผ ๋ถ์ผ ์ ์๋ค๊ณ ์๊ฐํ๋ค. ์์์ ๋ฐฐ์ ๋ฏ์ด async ํจ์์ ๋ฆฌํด๊ฐ์ ํ๋ก๋ฏธ์ค ๊ฐ์ฒด์ด๊ธฐ ๋๋ฌธ์ async ํจ์ ์์ฒด์ then ํธ๋ค๋ฌ๋ฅผ ๋ถ์ผ์๋ ์๋ค.
async function func1() {
return 1;
}
func1()
.then(data => console.log(data));
๋ค๋ง then ํธ๋ค๋ฌ ์ฝ๋ ๋ฐฉ์์ ๋จ์ฉํ ๊ฒฝ์ฐ Promise Hell์ ๊ฑธ๋ฆด ์ ์๊ธฐ ๋๋ฌธ์ ์ด๋ฌํ ๋ฐฉ์์ ์ด์ฉํ์ง ์๊ณ ๋์ ์ await ํค์๋๋ฅผ ํตํด ์ฒ๋ฆฌํ๋ค.
await ํค์๋
await ํค์๋๋ promise.then() ๋ณด๋ค ์ข ๋ ์ธ๋ จ๋๊ฒ ๋น๋๊ธฐ ์ฒ๋ฆฌ์ ๊ฒฐ๊ณผ๊ฐ์ ์ป์ ์ ์๋๋ก ํด์ฃผ๋ ๋ฌธ๋ฒ์ด๋ผ๊ณ ๋ณด๋ฉด ๋๋ค. ์๋ฅผ๋ค์ด ์๋ฒ์ ๋ฆฌ์์ค๋ฅผ ์์ฒญํ๋ fetch() ๋น๋๊ธฐ ํจ์๋ฅผ ๋ค์๊ณผ ๊ฐ์ด then ํธ๋ค๋ฌ ๋ฐฉ์์ผ๋ก ๊ฒฐ๊ณผ๋ฅผ ์ป์ด ์ฌ์ฉํด์์ ๊ฒ์ด๋ค.
// then ํธ๋ค๋ฌ ๋ฐฉ์
fetch(url)
.then(res => res.json()) // ์๋ต์ JSON์ผ๋ก ํ์ฑ
.then(data => {
// data ์ฒ๋ฆฌ
console.log(data);
})
await ํค์๋๋ฅผ ์ฌ์ฉํ๋ฉด then ํธ๋ค๋ฌ๋ฅผ ๋ณต์กํ๊ฒ ์ฒ๋ฆฌํ ํ์ ์์ด, ์ฌํํ๊ฒ ๋น๋๊ธฐ ํจ์ ์ผ์ชฝ์ await ๋ง ๋ช ์ํด์ฃผ๊ณ ๊ฒฐ๊ณผ๊ฐ์ ๋ณ์์ ๋ฐ๋๋ก ์ฝ๋๋ฅผ ์ ์ํ๋ฉด ๋์ด๋ค. then๊ณผ ์ฝ๋ฐฑ ํจ์๋ฅผ ๋จ๋ฐํ์ฌ ์ฝ๋๊ฐ ๋ค์ฌ์ฐ๊ธฐ๋ก ๊น์ด์ง๋ ๊ฒ์ ๋ฐฉ์งํ๊ณ , ํ ์ค ๋ ๋ฒจ์์ ์ฝ๋๋ฅผ ๋์ดํ์ฌ ๊ฐ๋ ์ฑ์ ๋์ผ ์ ์๋ค.
// await ๋ฐฉ์
async function func() {
const res = await fetch(url); // ์์ฒญ์ ๊ธฐ๋ค๋ฆผ
const data = await res.json(); // ์๋ต์ JSON์ผ๋ก ํ์ฑ
// data ์ฒ๋ฆฌ
console.log(data);
}
func();
await๋ Promise ์ฒ๋ฆฌ๊ฐ ๋๋ ๋๊น์ง ๊ธฐ๋ค๋ฆผ
await๋ ํค์๋ ์ด๋ฆ์์ ๋ณด๋ฏ์ด Promise ๋น๋๊ธฐ ์ฒ๋ฆฌ๊ฐ ์๋ฃ๋ ๋ ๊น์ง ์ฝ๋ ์คํ์ ์ผ์ ์ค์งํ๊ณ wait ํ๋ค๋ผ๋ ๋ป์ผ๋ก ๋ณด๋ฉด ๋๋ค. ์๋ฅผ ๋ค์ด fetch() ํจ์๋ฅผ ์ฌ์ฉํ์ฌ ์๋ฒ์์ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ค๋ ๊ฒฝ์ฐ๋ฅผ ์๊ฐํด๋ณด์. ์ด ํจ์๋ Promise๋ฅผ ๋ฐํํ๋ค. ๋ฐ๋ผ์ await ํค์๋๋ฅผ ์ฌ์ฉํ์ฌ ์ด Promise๊ฐ ์ฒ๋ฆฌ๋ ๋๊น์ง ์ฝ๋ ์คํ์ ์ผ์ ์ค์งํ๊ณ , Promise๊ฐ ์ฒ๋ฆฌ๋๋ฉด ๊ฒฐ๊ณผ ๊ฐ์ ๋ฐํํ์ฌ ๋ณ์์ ํ ๋นํ๋ ์์ด๋ค.
async function getData() {
const response = await fetch('https://jsonplaceholder.typicode.com/users/1');
const data = await response.json();
console.log(data):
}
์ ์์ ๋ฅผ ๋ณด๋ฉด getData() async ํจ์ ๋ด์์ fetch() ๋น๋๊ธฐ ํจ์๋ฅผ ํธ์ถํ๊ณ , ๋ฐํ๋ Promise๋ฅผ await ํค์๋๋ก ์ฒ๋ฆฌํ๋ค. ์ด๋ก ์ธํด ํจ์ ๋ด ์ฝ๋ ์คํ์ด ์ผ์ ์ค์ง๋๊ณ , fetch() ํจ์๊ฐ ์๋ฃ๋ ๋๊น์ง ๊ธฐ๋ค๋ฆฌ๊ฒ ๋๋ค. ์๋ฒ๋ก๋ถํฐ ๋ฆฌ์์ค๋ฅผ ์ฑ๊ณต์ ์ผ๋ก ๊ฐ์ ธ์ fetch() ํจ์๊ฐ ์๋ฃ๋๋ฉด, ๋ฐ๋ก ๋ค์ response.json() ํจ์๋ฅผ ํธ์ถํ์ฌ ๋ฐํ๋ Promise๋ฅผ ๋ค์ await๋ก ์ฒ๋ฆฌํ๋ค. ๋ค์ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ค๋ ๋์ ์ฝ๋ ์คํ์ด ์ผ์ ์ค์ง๋๊ณ , ๋ฐ์ดํฐ๊ฐ ์ฑ๊ณต์ ์ผ๋ก ๊ฐ์ ธ์์ง๋ฉด ์ต์ข
๊ฒฐ๊ณผ ๊ฐ์ ๋ฐํํ๋ค. ๋ฐ๋ผ์ await๋ Promise๋ฅผ ์ฒ๋ฆฌํ๊ณ ๊ฒฐ๊ณผ๋ฅผ ๋ฐํํ๋ ๋ฐ, ๋น๋๊ธฐ์ ์ธ ์์
์ ๋๊ธฐ์ ์ผ๋ก ์ฒ๋ฆฌํ ์ ์๊ฒ ๋๋ ๊ฒ์ด๋ค.
async/await ์๋ฌ ์ฒ๋ฆฌ
๊ธฐ์กด์ Promise.then() ๋ฐฉ์์ ์๋ฌ ์ฒ๋ฆฌ๋ catch() ํธ๋ค๋ฌ๋ฅผ ์ค๊ฐ ์ค๊ฐ์ ๋ช
์ํจ์ผ๋ก์จ ์๋ฌ๋ฅผ ๋ฐ์์ผ๋ง ํ๋ค.
// then ํธ๋ค๋ฌ ๋ฐฉ์
function fetchResource(url) {
fetch(url)
.then(res => res.json()) // ์๋ต์ JSON์ผ๋ก ํ์ฑ
.then(data => {
// data ์ฒ๋ฆฌ
console.log(data);
})
.catch(err => {
// ์๋ฌ ์ฒ๋ฆฌ
console.error(err);
});
}
์ฐ๋ฆฌ๊ฐ ์ผ๋ฐ์ ์ผ๋ก ์๋ฌ๋ฅผ ์ฒ๋ฆฌํ๊ธฐ ์ํด์ try/catch ๋ฌธ์ ์ฌ์ฉํ์ฌ ์๋ฌ๋ฅผ ์ฒ๋ฆฌํด์๋ค. async/await๋ ์ด์ ๊ฐ์ด ๋น๋๊ธฐ ์ฒ๋ฆฌ์ ๋ํ ์๋ฌ๋ฅผ ์ฒ๋ฆฌํ ํ์๊ฐ ์๊ธฐ๋ฉด ๊ณ ๋๋ก try/catch๋ฌธ์ ์์ฐ๋ฉด ๋๊ฒ ๋๋ค.
// async/await ๋ฐฉ์
async function func() {
try {
const res = await fetch(url); // ์์ฒญ์ ๊ธฐ๋ค๋ฆผ
const data = await res.json(); // ์๋ต์ JSON์ผ๋ก ํ์ฑ
// data ์ฒ๋ฆฌ
console.log(data);
} catch (err) {
// ์๋ฌ ์ฒ๋ฆฌ
console.error(err);
}
}
func();
์ด์ฒ๋ผ async/await์ ์ฅ์ ์ ๋น๋๊ธฐ ์ฝ๋๋ฅผ ๋ง์น ๋๊ธฐ ์ฝ๋์ฒ๋ผ ์ฝํ๊ฒ ํด์ค๋ค๋ ๊ฒ์ด๋ค. ์ฐ๋ฆฌ๊ฐ ์ผ๋ฐ์ ์ผ๋ก ์ฝ๋๋ฅผ ์ฐ๊ณ ์ฝ์ด ๋ด๋ฆฌ๋ฏ์ด ๋ง์ด๋ค.
async / await ํจ์ ๊ณผ ๋ณ๋ ฌ์ฒ๋ฆฌ
๋น๋๊ธฐ ํ๋ก๊ทธ๋๋ฐ์ ์น์์ ๋ฉ์ธ ์ค๋ ๋๋ฅผ ์ฐจ๋จํ์ง ์๊ณ ์๊ฐ ์๋ชจ์ ์ธ ์์ ์ ๋ณ๋ ฌ์ ์ผ๋ก ์ํํ ์ ์๋๋ก ํ๋ ์น ๊ฐ๋ฐ์ ํ์์ ์ธ ๋ถ๋ถ์ด๋ค. ์๋ฐ์คํฌ๋ฆฝํธ์์ ๋น๋๊ธฐ ์ฝ๋๋ฅผ ์ฒ๋ฆฌํ๋ ๋ฌธ๋ฒ์ผ๋ก Promise์ await ํค์๋๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด๋ค. ๊ทธ๋ฌ๋ await๋ฅผ ๊น์ ์ดํด ์์ด ๋ง๋ฌด๊ฐ๋ด๋ก ์ฌ์ฉํ๊ฒ ๋๋ค๋ฉด ์ฑ๋ฅ ๋ฌธ์ ๋ฐ ๊ธฐํ ๋ฌธ์ ๊ฐ ๋ฐ์ํ ์๋ ์๋ค. await ์์ฒด๊ฐ Promise๊ฐ ํด๊ฒฐ๋ ๋๊น์ง ํจ์ ์คํ์ ์ผ์ ์ค์งํ๋ ๊ฒ์ธ๋ฐ, ๋ณ๋ ฌ์ ์ผ๋ก ๋ฉํฐ๋ก ์ฒ๋ฆฌํ ์ ์๋ ์์ ์ ์ต์ง๋ก ๋๊ธฐ์ ์ผ๋ก ์ฒ๋ฆฌํ๊ฒ ํจ์ผ๋ก์จ ์คํ๋ ค 2์ด๋ง์ ํด๊ฒฐํ ๋ก์ง์ 6์ด์ฉ์ด๋ ๊ฑธ๋ฆฌ๊ฒ ํ ์ ์๊ธฐ ๋๋ฌธ์ด๋ค.
๋ฐ๋ผ์ await๋ฅผ ์ฌ๋ฐ๋ฅด๊ฒ ์ฌ์ฉํ์ง ์์ผ๋ฉด ์คํ๋ ค ์ฑ๋ฅ ๋ฌธ์ ๊ฐ ๋ฐ์ํ๊ธฐ ๋๋ฌธ์, ์๋ฐ์คํฌ๋ฆฝํธ await ๋จ์ฉ์ ๋ํ ๋ช ๊ฐ์ง ์ฃผ์ ์ฌํญ๊ณผ Promise.all์ ํตํด ๋ณ๋ ฌ ์ฒ๋ฆฌ๋ฅผ ์ต์ ํํ๋ ๋ฐฉ๋ฒ์ ์ดํด๋ณผ ์์ ์ด๋ค.
์ ์ ํ์ง ์์ async/await ์ฌ์ฉ
์๋ ์ฝ๋๋ Promise๋ฅผ ์ฌ์ฉํ์ฌ ๋น๋๊ธฐ์์ผ๋ก ๊ณผ์ผ ์ ๋ณด๋ฅผ ๊ฐ์ ธ์ค๋ ํจ์๋ค์ ์ ์ํ๊ณ , ์ด๋ฅผ ์กฐํฉํ์ฌ ๊ณผ์ผ ์ ๋ณด๋ฅผ ์ถ๋ ฅํ๋ ํจ์๋ฅผ ๋ง๋๋ ๊ฐ๋จํ ์์ ๋ค.
์ฐ์ , getApple() ํจ์๋ "apple"์ด๋ผ๋ ๋ฌธ์์ด์ ๋ฐํํ๋ Promise ๊ฐ์ฒด๋ฅผ ์์ฑํ๋ค. ์ด๋ ์๋ฒ๋ก๋ถํฐ ๊ฒฐ๊ณผ๋ฅผ ์ป๊ธฐ์ํด 1์ด๊ฐ ๊ฑธ๋ฆฐ๋ค๊ณ ๊ฐ์ ํด๋ณด์. ๋ง์ฐฌ๊ฐ์ง๋ก, getBanana() ํจ์๋ 1์ด ํ์ "banana"๋ผ๋ ๋ฌธ์์ด์ ๋ฐํํ๋ Promise ๊ฐ์ฒด๋ฅผ ์์ฑํ๋ค.
function getApple(){
return new Promise( (resolve, reject) => {
setTimeout(() => resolve("apple"), 1000);
})
}
function getBanana(){
return new Promise( (resolve, reject) => {
setTimeout(() => resolve("banana"), 1000);
})
}
์ด๋ฅผ ์ฐ๋ฆฌ๊ฐ ์ง๊ธ๊น์ง ๋ฐฐ์ด async/await ํ์์ ๋น๋๊ธฐ ์ฒ๋ฆฌ ์ฝ๋๋ฅผ ์์ฑํ์๋ฉด ์๋์ ๊ฐ์ ๊ฒ์ด๋ค.
async function getFruites(){
let a = await getApple();
let b = await getBanana();
console.log(`${a} and ${b}`);
}
getFruites();
ํ์ง๋ง ์ด๋ฌํ ๊ตฌ์ฑ์ ์ ์ฌ์ ์ธ ๋ฌธ์ ์ ์ด ์กด์ฌํ๋ค. ์ฐ์ ์ฌ๊ณผ์ ๋ฐ๋๋๋ฅผ ๊ฐ์ ธ์ค๋ getApple() ์ getBanana() ๋น๋๊ธฐ ํจ์๋ ์๋ก ์ฐ๊ด์ด ์๋ค. ์ฆ, ์ฌ๊ณผ๋ฅผ ๋จผ์ ๊ฐ์ ธ์๋ ๋๊ณ ๋ฐ๋๋๋ฅผ ๋จผ์ ๊ฐ์ ธ์๋ ๋๋ค. ์ด๋ฅผ ๋น๋๊ธฐ๋ก ๋ฐฑ๊ทธ๋ผ์ด๋์์ ํ๊บผ๋ฒ์ ์ฒ๋ฆฌํด ๊ฐ์ ธ์ค๊ฒ ๋๋ค๋ผ๋ฉด 1์ด๋ฅผ ์์ฃผ์์ฃผ ์ฝ๊ฐ ๋๊ธฐ๋ ์์ค์ผ๋ก ์ฝ 1์ด ์์ผ๋ก ๊ฐ์ ธ์ค๋ ๊ฒ์ด ๋ง์ ๊ฒ์ด๋ค.
ํ์ง๋ง ์๊ฐ์์ด await ํค์๋๋ฅผ ๋๋ฒ ๋ถ์์ผ๋ก์จ ๋ ๊ณผ์ผ์ ๊ฐ์ ธ์ค๋๋ฐ ๋๊ธฐ์ ์ผ๋ก ์คํ๋จ์ผ๋ก์จ ์ด 2์ด๊ฐ ๊ฑธ๋ฆฌ๊ฒ ๋์๋ค. ์๊ฐ ๋ญ๋น์ธ ์
์ด๋ค. ์ด๋ฅผ console.time() ์ ํตํด ์ด ๋น๋๊ธฐ ์ฝ๋์ ์คํํ๊ฐ์ ๊ตฌํด๋ณด๋ฉด ์๋์ ๊ฐ์ด 2์ด๊ฐ ์กฐ๊ธ ๋๋ ์๊ฐ์ด ๊ฑธ๋ฆผ์ ์ ์ ์๋ค.
async function getFruites(){
console.time();
let a = await getApple(); // 1์ด ์์
let b = await getBanana(); // 1์ด ์์
console.log(`${a} and ${b}`);
console.timeEnd();
}
getFruites();
์ ์ ํ async/await ์ฌ์ฉ
await ํค์๋๋ฅผ ์ฐ๋ฉด ๋น๋๊ธฐ๊ฐ ๊ฐ์ ์ ์ผ๋ก ๋๊ธฐ ์ฒ๋ฆฌ๊ฐ ๋์ด ์ฝ๋๊ฐ ์์ฐจ์ ์ผ๋ก ์ํ๋๋ค. ๊ทธ๋ฌ๋ฉด ์ด๋ฅผ ์ด๋ป๊ฒ '๋ณ๋ ฌ ์ฒ๋ฆฌ 'ํ๋ค๋ ๊ฒ์ผ๊น? ํต์ฌ์ ํ๋ก๋ฏธ์ค ๊ฐ์ฒด ํจ์๋ฅผ await๊ณผ ๊ฐ์ด ์จ์ ์คํ์ํค๋๊ฒ ์๋๋ผ, ๋ฏธ๋ฆฌ ํจ์๋ฅผ ๋๊ธฐ/๋ ผ๋ธ๋กํน์ผ๋ก ์คํํ๊ณ ๊ทธ ๊ฒฐ๊ณผ ํ๋ก๋ฏธ์ค๊ฐ์ await๋ฅผ ํตํด ๋ฐ๋ ์์ด๋ค.
๊ธฐ์กด์๋ ๋น๋๊ธฐ ์ฒ๋ฆฌ ์์ฒญ์ ํ๊ณ ๋์์ ์์ฒญ์ด ์๋ฃ๋ ๋ ๊น์ง await ํ์๊ธฐ ๋๋ฌธ์ 1์ด์์ ์ฒ๋ฆฌ๋ ๊ฒ์ด 2์ด๊ฐ ๊ฑธ๋ ธ์๋ค.
async function getFruites() {
let a = await getApple(); // getApple() ๋น๋๊ธฐ ์ฒ๋ฆฌ๋ฅผ ์์ฒญํ๊ณ , ์์ฒญ์ด ์ฒ๋ฆฌ๋ ๋ ๊น์ง ๊ธฐ๋ค๋ฆผ (1์ด ์์)
let b = await getBanana(); // getBanana() ๋น๋๊ธฐ ์ฒ๋ฆฌ๋ฅผ ์์ฒญํ๊ณ , ์์ฒญ์ด ์ฒ๋ฆฌ๋ ๋ ๊น์ง ๊ธฐ๋ค๋ฆผ (1์ด ์์)
console.log(`${a} and ${b}`); // ์ด 2์ด ์์
}
getApple() ์ getBanana() ๋น๋๊ธฐ ๋ก์ง์ด ๋ง์ผ ์์๋ฅผ ์ง์ผ์ผํ๋ ๋ก์ง์ด๋ผ๋ฉด ์์ ๊ฐ์ด ๊ตฌ์ฑํ์ฌ์ผ ํ๋ ๊ฒ์ด ์ณ์ง๋ง, ํ์ฌ๋ก์๋ ์๋ก ์ฐ๊ด ์์ด ๋๋ฌธ์ ๋ฐ๋์ ์์ฐจ์ ์ผ๋ก ์คํ ์ํฌ ํ์๊ฐ ์๋ค. ๋ฐ๋ผ์ ๋น๋๊ธฐ ์ฒ๋ฆฌ ์์ฒญ๊ณผ ๊ฐ์ await ํ๋ ๋ก์ง์ ๋ถ๋ฆฌ์ํค๋ฉด ๋๋ค.
async function getFruites(){
let getApplePromise = getApple(); // asyncํจ์๋ฅผ ๋ฏธ๋ฆฌ ๋
ผ๋ธ๋กํน์ผ๋ก ์คํํ๋ค.
let getBananaPromise = getBanana(); // asyncํจ์๋ฅผ ๋ฏธ๋ฆฌ ๋
ผ๋ธ๋กํน์ผ๋ก ์คํํ๋ค.
// ์ด๋ ๊ฒ ํ๋ฉด ๊ฐ๊ฐ ๋ฐฑ๋จ์์ ๋
๋ฆฝ์ ์ผ๋ก ๊ฑฐ์ ๋์์ ์คํ๋๊ฒ ๋๋ค.
console.log(getApplePromise)
console.log(getBananaPromise)
let a = await getApplePromise; // ์์์ ๋ฐ์ ํ๋ก๋ฏธ์ค๊ฐ์ฒด ๊ฒฐ๊ณผ ๋ณ์๋ฅผ await์ ํตํด ๊บผ๋ธ๋ค.
let b = await getBananaPromise; // ์์์ ๋ฐ์ ํ๋ก๋ฏธ์ค๊ฐ์ฒด ๊ฒฐ๊ณผ ๋ณ์๋ฅผ await์ ํตํด ๊บผ๋ธ๋ค.
console.log(`${a} and ${b}`); // ๋ณธ๋๋ผ๋ฉด 1์ด+1์ด ๋ฅผ ๊ธฐ๋ค๋ ค์ผ ํ๋๋ฐ, ์์์ 1์ด๊ธฐ๋ค๋ฆฌ๋ ํจ์๋ฅผ ๋ฐ๋ก ์ฐ์์ผ๋ก ๋น๋๊ธฐ๋ก ๋ถ๋ ค์๊ธฐ ๋๋ฌธ์, ๋์ถฉ 1.01์ด๋ง ๊ธฐ๋ค๋ฆฌ๋ฉด ์ฒ๋ฆฌ๋๋ค.
})
Promise.all ๋ฉ์๋
๋๋ค๋ฅธ ๋ฐฉ๋ฒ์ผ๋ก Promise.all() ์ ์ ๋ฉ์๋๋ฅผ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ด ์๋ค. ์์ ๊ฐ์ด ๊ตฌ์ฑํ ๊ฒฝ์ฐ ๋น๋๊ธฐ ์ฒ๋ฆฌ ์๋ฃ ์์ ์ ๊ฐ๋ ํ๊ธฐ ํ๋ค๊ธฐ ๋๋ฌธ์ ๋๋ถ๋ถ์ ์ค๋ฌด์์ Promise.all()๋ก ์ฒ๋ฆฌํ๋ค.
Promise.all() ์ ๋ฐฐ์ด ์ธ์์ ๊ฐ ํ๋ก๋ฏธ์ค ๋น๋๊ธฐ ํจ์๋ค์ด resolve๊ฐ ๋ชจ๋ ๋์ผ ๊ฒฐ๊ณผ๋ฅผ ๋ฆฌํด ๋ฐ๋๋ค. ๋ฐฐ์ด์ธ์์ ๊ฐ ํ๋ก๋ฏธ์ค ํจ์๋ค์ ์ ๊ฐ๊ฐ ๋น๋๊ธฐ ๋
ผ๋ธ๋กํน์ผ๋ก ์คํ๋์ด ์๊ฐ์ ๋จ์ถ ํ ์ ์๋ค. ๋ฆฌํด๊ฐ์ ๊ฐ ํ๋ก๋ฏธ์ค ํจ์์ ๋ฐํ๊ฐ๋ค์ด ๋ฐฐ์ด๋ก ๋ด๊ฒจ์ ธ ์๋ค.
async function getFruites(){
console.time();
// ๊ตฌ์กฐ ๋ถํด๋ก ๊ฐ ํ๋ก๋ฏธ์ค ๋ฆฌํด๊ฐ๋ค์ ๋ณ์์ ๋ด๋๋ค.
let [ a, b ] = await Promise.all([getApple(), getBanana()]);
console.log(`${a} and ${b}`);
console.timeEnd();
}
getFruites();
top-level await
๊ธฐ์กด์๋ await ํค์๋๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํด์ ๋ฌด์กฐ๊ฑด async function๋ฅผ ์ ์ํ๊ณ async ํจ์๋ฅผ ํธ์ถํ๋ ์์ผ๋ก ์ฌ์ฉํด์์ผ ํ๋ค. ๊ทธ๋์ ๊ตณ์ด ํจ์๋ก ๊ฐ์ธ์ง ์์๋ ๋ ์ฝ๋๋ฅผ ์ด๊ฑฐ์ง๋ก ํจ์๋ก ๊ฐ์ธ IIFE๋ก ํธ์ถํ๋ ์์ผ๋ก ์ฌ์ฉํด์๋ค.
(async function func1() {
const res = await fetch(url); // ์์ฒญ์ ๊ธฐ๋ค๋ฆผ
const data = await res.json(); // ์๋ต์ JSON์ผ๋ก ํ์ฑ
console.log(data);
})();
์ด๋ฌํ ํ๊ณ์ ๋๋ฌธ์ ์ถ๊ฐ๋ Top-level await ๋ async ํจ์๋ ๋ชจ๋ ์ธ๋ถ์์๋ await ํค์๋๋ฅผ ์ฌ์ฉํ ์ ์๊ฒ ํด์ฃผ๋ ํธ์ ๊ธฐ๋ฅ์ด๋ค. ์ด ๊ธฐ๋ฅ์ ES2022์ ์ถ๊ฐ๋์์ผ๋ฉฐ, ํ์ฌ ๋๋ถ๋ถ์ ์ต์ ๋ธ๋ผ์ฐ์ ์ Node.js์์ ์ง์๋๋ค.
// Top Level์์ async funciton ์ ์์์ด ๊ณง๋ฐ๋ก await ํค์๋ ์ฌ์ฉ์ด ๊ฐ๋ฅํ๋ค
const res = await fetch(url); // ์์ฒญ์ ๊ธฐ๋ค๋ฆผ
const data = await res.json(); // ์๋ต์ JSON์ผ๋ก ํ์ฑ
console.log(data);
# ์ฐธ๊ณ ์๋ฃ
https://www.youtube.com/watch?v=aoQSOZfz3vQ