์ ๋ฒ ๊ธ โ(5) ์๋ฐ์คํฌ๋ฆฝํธ๋ ๋๊ธฐ์ ์ผ๋ก ์๋ํ ๊น? ๋น๋๊ธฐ์ ์ผ๋ก ์๋ํ ๊น?โ์ ๊ฐ๋จํ ๋ณต์ตํ์๋ฉด ๋ค์๊ณผ ๊ฐ๋ค.
์๋ฐ์คํฌ๋ฆฝํธ๋ ๊ธฐ๋ณธ์ ์ผ๋ก ์คํฌ๋ฆฝํธ ์์์ ์๋๋ก ์ฝ์ด๊ฐ๋ฉฐ ๋๊ธฐ์ ์ผ๋ก ์๋ํ์ง๋ง,
๋ธ๋ผ์ฐ์ ์์ ์ฃผ๋ก ์ฌ์ฉ๋๋ ์ธ์ด์ ํน์ฑ ์ ๋ธ๋ผ์ฐ์ ์ฌ์ฉ์ ์ฌ์ฉ์ฑ์ ์ํด
์ด๋ฏธ์ง, API ๋ฑ ๋ชจ๋ ๊ฒ์ ๋ก๋ฉ ํ๊ธฐ ์ ์ฐ์ ์ ์ผ๋ก ๋ก๋ฉ๋ ๊ฒ๋ค์ ๋ณด์ฌ์ฃผ๊ธฐ ์ํด ๋น๋๊ธฐ์ ์ผ๋ก ์ฌ์ฉํ๋ ๊ฒฝ์ฐ๊ฐ ๋ง๋ค.
์๋ฐ์คํฌ๋ฆฝํธ๋ฅผ ๋น๋๊ธฐ์ ์ผ๋ก ์ ์๋ํ๋๋ก ์ ์ด(?)ํ๋ ๋ฐฉ๋ฒ์ผ๋ก๋ ์ฝ๋ฐฑ(callback), ํ๋ก๋ฏธ์ค(promise), async/await ๋ฑ์ด ์๋ค.
(โ์ ์ดโ๋ผ๊ณ ํํํ ๋ถ๋ถ์ด ์ ํฉํ ์ง๋ ๋ชจ๋ฅด๊ฒ ์ง๋ง, ์ฝ๋๊ฐ ์๋ํ๋๋ก ์๋ํ๋๋ก ํ๊ธฐ ์ํด ์ฌ์ฉํ๊ธฐ ๋๋ฌธ์ โ์ ์ดโ๋ผ๊ณ ํํํด๋ณด์๋ค.)
์ด๋ฒ ์๊ฐ์๋ ์ฝ๋ฐฑ, ํ๋ก๋ฏธ์ค(promise), async/await์ ๋ํด ํ์ตํด๋ณด๊ณ ์ ํ๋ค.
์ฝ๋ฐฑ ํจ์๋ ๋์ค์ ํธ์ถํ ํจ์๋ฅผ ์๋ฏธํ๋ฉฐ, ๋น๋๊ธฐ ๋์์์ ์์ฐจ์ ์ผ๋ก ์คํ์ํค๊ธฐ ์ํด ์ฌ์ฉํ๋ค.
// GET ์์ฒญ์ผ๋ก title ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ค๊ณ ๋ฐํํ๋ ๋ฉ์๋
const getTitle = () => {
$.ajax({
types: "GET",
// fake api๋ฅผ ์ ๊ณตํ๋ ํ๋ซํผ์ธ {JSON} Placeholder
url: "https://jsonplaceholder.typicode.com/posts/1",
}).then((data) => {
return data.title
})
}
// title ๋ฐ์ดํฐ๋ฅผ localStorage์ ์ ์ฅํ๋ ๋ฉ์๋
const setTitle = (title) => {
localStorage.setItem('title', title);
}
const title = getTitle();
setTitle(title);
jQuery์ API ์์ฒญ์ ์ํ ajax ํจ์๋ ๋ํ์ ์ผ๋ก ๋น๋๊ธฐ ๋์ํ๋ ํจ์์ด๋ค.
๋ฐ๋ผ์ getTitle()
ํจ์์์ API๋ฅผ ํตํด ๋ฐ์ดํฐ๊ฐ ๋์ฐฉํ๊ธฐ ์ ์
setTitle()
ํจ์๊ฐ ์คํ๋์ด ๊ฒฐ๊ณผ์ ์ผ๋ก localStorage
์ undefined
๊ฐ ์ ์ฅ๋์๋ค.
// GET ์์ฒญ์ผ๋ก title ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ค๊ณ ๋ฐํํ๋ ๋ฉ์๋
// ํ๋ผ๋ฏธํฐ๋ก callback ํจ์๋ฅผ ๋ฐ์์ ajax ์์ฒญ์ด ๋๋ฌ์ ๋ (then ์ ์ด ์คํ๋์์ ๋)
// callback ํจ์๋ฅผ ์คํ์ํจ๋ค.
const getTitle = (callback) => {
$.ajax({
types: "GET",
// fake api๋ฅผ ์ ๊ณตํ๋ ํ๋ซํผ์ธ {JSON} Placeholder
url: "https://jsonplaceholder.typicode.com/posts/1",
}).then((data) => {
callback(data.title);
})
}
// title ๋ฐ์ดํฐ๋ฅผ localStorage์ ์ ์ฅํ๋ ๋ฉ์๋
const setTitle = (title) => {
localStorage.setItem('title', title);
}
// ์ฝ๋ฐฑํจ์์ธ setTitle์ ํ๋ผ๋ฏธํฐ๋ก ๋๊ธด๋ค.
getTitle(setTitle);
์ฝ๋ฐฑ ํจ์๋ฅผ ํตํด getTitle()
โ setTitle()
์์๋ก ๋์ํ๋๋ก ์ฝ๋๋ฅผ ์์ฑํ์๋ค.
๋ง์ฝ, getTitle()
โ setTitle()
โ changeBrowserTitle()
โ โฆ.. ์ด์ ๊ฐ์ด ์ฌ๋ฌ ํจ์๋ฅผ ์์ฐจ์ ์ผ๋ก ๋์ํ๋๋ก ์ฝ๋๋ฅผ ์์ฑํ๊ณ ์ถ์ผ๋ฉด ์ด๋ป๊ฒ ๋ ๊น?
// GET ์์ฒญ์ผ๋ก title ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ค๊ณ ๋ฐํํ๋ ๋ฉ์๋
// ํ๋ผ๋ฏธํฐ๋ก callback ํจ์๋ฅผ ๋ฐ์์ ajax ์์ฒญ์ด ๋๋ฌ์ ๋ (then ์ ์ด ์คํ๋์์ ๋)
// callback ํจ์๋ฅผ ์คํ์ํจ๋ค.
const getTitle = (callback) => {
$.ajax({
types: "GET",
// fake api๋ฅผ ์ ๊ณตํ๋ ํ๋ซํผ์ธ {JSON} Placeholder
url: "https://jsonplaceholder.typicode.com/posts/1",
}).then((data) => {
callback(data.title);
})
}
// title ๋ฐ์ดํฐ๋ฅผ localStorage์ ์ ์ฅํ๋ ๋ฉ์๋
const setTitle = (title, callback) => {
localStorage.setItem('title', title);
callback();
}
// ์์ฐจ์ ์ผ๋ก ์งํ๋์ด์ผ ํ ๋ฉ์๋
const changeBrowserTitle = (callback) => {
callback();
}
// ๊ฐ๊ฐ์ ์ฝ๋ฐฑํจ์๋ฅผ ํ๋ผ๋ฏธํฐ๋ก ๋๊ธด๋ค.
getTitle(setTitle(changeBrowserTitle(...)));
์ด๋ ๊ฒ ์ฝ๋ฐฑ ํจ์ ์์ ์ฝ๋ฐฑ์ ์ค์ฒฉ๋๋๋ก ์ฝ๋๋ฅผ ์์ฑํ๋ฉด ์ ์ ์ฝ๋๊ฐ ๋ณต์กํด์ง๊ณ ์ฝ๊ธฐ ์ด๋ ค์ ์ง๋๋ฐ, ์ด๋ฅผ โ์ฝ๋ฐฑ ์ง์ฅโ์ด๋ผ๊ณ ํํํ๋ค.
์ด๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํ ๋ฐฉ๋ฒ์ผ๋ก Promise ๊ฐ์ฒด ๋๋ async/await ๋ฅผ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ด ์๋ค.
Promise ๊ฐ์ฒด๋ ๋น๋๊ธฐ ์์ ์ ๊ฒฐ๊ณผ๋ฅผ ๋ํ๋ด๋ฉฐ, ๋ค์๊ณผ ๊ฐ์ ์ธ ๊ฐ์ง ์ํ๋ฅผ ๊ฐ์ง๋ค.
Promise ๊ฐ์ฒด๋ ๋ค์๊ณผ ๊ฐ์ด ์ฌ์ฉํ ์ ์๋ค.
const promise = new Promise((resolve, reject) => {
// ๋น๋๊ธฐ ์์
์ํ
// ์ฑ๊ณต ์ resolve() ํธ์ถ, ์คํจ ์ reject() ํธ์ถ
});
promise.then(() => {
// ์ฑ๊ณต ์ ์คํํ ์ฝ๋
}).catch(() => {
// ์คํจ ์ ์คํํ ์ฝ๋
}).finally(() => {
// ์ฑ๊ณต ๋๋ ์คํจ ๊ฒฐ๊ณผ๊ฐ ๋์ค๊ณ ๊ฒฐ๊ณผ์ ์๊ด์์ด ์คํํ ์ฝ๋
});
์ฝ๋ฐฑ ์ง์ฅ๊ณผ ๊ฐ์ ์ํฉ์ ๊ฐ์ ํ์ ๋ Promise ๊ฐ์ฒด๋ก ํด๊ฒฐํ๋ ๋ฐฉ๋ฒ์ ๋ค์๊ณผ ๊ฐ๋ค.
promise
.then((result) => {
// ์ฑ๊ณต ์ฒซ๋ฒ์งธ๋ก ์คํํ ์ฝ๋
}).then((result) => {
// ์ฑ๊ณต ๋๋ฒ์งธ๋ก ์คํํ ์ฝ๋
}).then((result) => {
// ์ฑ๊ณต ์ธ๋ฒ์งธ๋ก ์คํํ ์ฝ๋
}).catch((error) => {
// ์ then ์ ์ค ํ๋๋ผ๋ ๊ฑฐ๋ถ๋๋ฉด ์๋ฌ๋ฅผ ์ก๋ ์ฝ๋
});
๊ฐ๊ฐ์ then
์ ์์ ์คํํ ๊ฒฐ๊ณผ๋ฅผ result
๋ผ๋ ํ๋ผ๋ฏธํฐ๋ก ๋ฐ์ ์์ฐจ์ ์ผ๋ก ์ฒ๋ฆฌํ ์ ์๋ค.
ํ๋ผ๋ฏธ์ค executor์ ํ๋ผ๋ฏธ์ค ํธ๋ค๋ฌ ์ฝ๋ ์ฃผ์์ '๋ณด์ด์ง ์๋(์์์ )ย try..catch
๊ฐ ์๋๋ฐ ์์ธ๊ฐ ๋ฐ์ํ์ ๋ ์๋ฌ๋ฅผ ์ก์ ์ฝ๋๊ฐ ํ์ํ๋ค.
์ฒด์ธ์ ๋ง์ง๋ง catch
์ ์์ ์ด์ ๋น์ทํ ์ญํ ์ ํ๋ค.
์๋ฌ ์ฒ๋ฆฌ ๊ตฌ๋ฌธ์ด ์๋ค๋ฉด ์คํฌ๋ฆฝํธ๊ฐ ์ฃฝ๊ณ , ์๋ฐ์คํฌ๋ฆฝํธ ์์ง์ ํ๋ผ๋ฏธ์ค ๊ฑฐ๋ถ๋ฅผ ์ถ์ ํ๋ค๊ฐ ์ ์ญ ์๋ฌ๋ฅผ ์์ฑํ๋ค. (์๋ฌ์ฒ๋ฆฌ ๊ตฌ๋ฌธ์ ์์ผ๋ก ๊ผญ ๋ถ์ด๋๊ฑธ๋ก!)
function func() {
let promise = Promise.resolve();
promise.then(() => alert("ํ๋ผ๋ฏธ์ค ์ฑ๊ณต!"));
alert("์ฝ๋ ์ข
๋ฃ");
}
func();
์์ ๊ฐ์ ์ฝ๋๊ฐ ์กด์ฌํ๋ค๊ณ ํ์ ๋ promise ๊ตฌ๋ฌธ์ ๋ฐ๋ก ์ฒ๋ฆฌ๊ฐ ๊ฐ๋ฅํ๊ธฐ ๋๋ฌธ์ ์ฝ๋๊ฐ ์์์ ์๋๋ก ์์๋๋ก ์งํ๋ ๊ฒ์ด๋ผ ์๊ฐํ ์ ์์ง๋ง, ๋จผ์ ๋จ๋ alert ๋ฉ์์ง๋ โ์ฝ๋ ์ข
๋ฃโ
์ด๋ค.
๊ทธ ์ด์ ๋ ์ ํฌ์คํธ์ ๋ง์ง๋ง ์ด๋ฏธ์ง์ ํจ๊ป ์ค๋ช ํ๋ ค๊ณ ํ๋ค.
๋ง์ฝ setTimeout ํจ์์ ์๊ฐ์ ํด๋นํ๋ ์ธ์๊ฐ 0์ด๋ผ๊ณ ํ๋๋ผ๋ โ์์โ
โ โ๋โ
โ โ๋์โ
์์ผ๋ก ์ถ๋ ฅ์ด ๋๋ค.
์๋ฐ์คํฌ๋ฆฝํธ ์์ง ๋์ ์์์ ์ํด setTimeout, Promise ๊ฐ์ฒด ์ฝ๋ ๋ฑ ๋น๋๊ธฐ ๋์์ ํ๋ ํจ์๋ ๋ฌด์กฐ๊ฑด
์ ๊ณผ์ ์ ๊ฑฐ์น๋ค.
๋ฐ๋ผ์ ์๋ ์์๋ก ๋์์ alert(โ์ฝ๋ ์ข
๋ฃโ)
์ ๊ฒฝ์ฐ ๋ฐ๋ก ํธ์ถ์คํ์์ ์คํ๋์ด ๋ฒ๋ฆฌ๊ธฐ ๋๋ฌธ์ ๋ ์ฐ์ ์ ์ผ๋ก ์คํ๋๋ ๊ฒ์ด๋ค.
async/await ๊ตฌ๋ฌธ์ Promise ๊ฐ์ฒด๋ฅผ ๋์ฑ ์ฝ๊ฒ ์ฌ์ฉํ ์ ์๋๋ก ๋์์ค๋ค.
async ํจ์๋ Promise ๊ฐ์ฒด๋ฅผ ๋ฐํํ๋ฉฐ, await ๊ตฌ๋ฌธ์ Promise ๊ฐ์ฒด๊ฐ ์ดํ๋ ๋๊น์ง ์ฝ๋์ ์คํ์ ์ผ์ ์ค์งํ๋ค.
function ์์ async ๋ฅผ ๋ถ์ด๊ณ , ์ฒ๋ฆฌ๊ฐ ์๋ฃ๋๊ธธ ๋ฐ๋ผ๋ ํจ์ ์ await ๋ฅผ ๋ถ์ด๋ฉด async/await ๊ตฌ๋ฌธ์ด ๋๋ค.
async function myFunction() {
try {
const result = await promise; // promise ๊ฐ์ฒด๊ฐ ์ดํ๋ ๋๊น์ง ๋๊ธฐ
// result๋ฅผ ์ด์ฉํ ์์
์ํ
} catch (error) {
// ์๋ฌ ์ฒ๋ฆฌ
}
}
async/await ๊ตฌ๋ฌธ์ ์ฌ์ฉํ๋ฉด Promise ๊ฐ์ฒด๋ฅผ ๋์ฑ ์ฝ๊ฒ ๋ค๋ฃฐ ์ ์์ผ๋ฉฐ, ์ฝ๋์ ๊ฐ๋ ์ฑ์ ๋์ผ ์ ์์ต๋๋ค.
await/async ๊ตฌ๋ฌธ์ ์ ์์์ฝ๋์ฒ๋ผ tryโฆcatch ๋ฌธ์ ์ฌ์ฉํ์ฌ ์๋ฌ๋ฅผ ์ฒ๋ฆฌํ๋ค.
์ถ์ฒ
velog - Javascript๋ ๋๊ธฐ์ผ๊น? ๋น๋๊ธฐ์ผ๊น?
velog - ๋น๋๊ธฐ ์ฒ๋ฆฌ์ callback ํจ์
javascript info - ํ๋ผ๋ฏธ์ค์ async, await
๊ฐ์ธ๋ธ๋ก๊ทธ - ์๋ฐ์คํฌ๋ฆฝํธ Promise ์ฝ๊ฒ ์ดํดํ๊ธฐ