์๋ฐ์คํฌ๋ฆฝํธ๋ ์ฑ๊ธ ์ค๋ ๋๋ก ๋์ํ๋ ์ธ์ด์ด๋ค. ๋ฐ๋ผ์ ํ ๋ฒ์ ํ๋์ ์์
๋ง ์ฒ๋ฆฌํ ์ ์๋ค. ํ์ง๋ง ์ฐ๋ฆฌ๊ฐ ์น์ํ์ ํ ๋ ์ด๋ฏธ์ง๋ฅผ ๋ถ๋ฌ์ค๋ฉด์ ๋์์ ํด๋ฆญ๋ ํ ์ ์๋ ์ด์ ๋ ๋ฐ๋ก ๋น๋๊ธฐ ์ฒ๋ฆฌ ๋๋ถ์ด๋ค.
์๋ฐ์คํฌ๋ฆฝํธ์์ ์ด ๋น๋๊ธฐ ์ฒ๋ฆฌ๊ฐ ์ด๋ป๊ฒ ๋ฐ์ ํด ์๋์ง ํ๋ฆ์ ์์๋ณด์.
์ฝ๋ฐฑ ํจ์๋ ํน์ ์์ ์ด ๋๋ ๋ค์ ์คํํ๊ธฐ ์ํด ๋์ค์ ํธ์ถ๋ ํจ์๋ฅผ ์ธ์๋ก ๋๊ฒจ์ฃผ๋ ๊ฒ์ ์๋ฏธํ๋ค. ์๋ฐ์คํฌ๋ฆฝํธ๋ ์ฑ๊ธ ์ค๋ ๋ ์ธ์ด์ด๊ธฐ ๋๋ฌธ์ ์ค๋ ๊ฑธ๋ฆฌ๋ ์์ (๋คํธ์ํฌ ์์ฒญ, ํ์ด๋จธ ๋ฑ)์ ๋น๋๊ธฐ์ ์ผ๋ก ์ฒ๋ฆฌํ๊ธฐ ์ํด ์ฝ๋ฐฑ์ ์ฌ์ฉํ๋ค.
function fetchUser(id, callback) {
console.log('1. ์ ์ ์ฐพ๊ธฐ');
setTimeout(() => {
const user = { id: id, name: 'BlueCool' };
callback(user);
}, 2000);
console.log('2. ๋ค์ ์์ ์ํ');
}
fetchUser(1, (user) => {
console.log('3. ์ ์ ์ ๋ณด: ', user);
});โ
์ ์ฝ๋๊ฐ ์คํ๋๋ฉด ๋จผ์ fetchUser๊ฐ ์คํ๋๊ณ setTimeout์ ๋ง๋๋ ์๊ฐ ์๋ฐ์คํฌ๋ฆฝํธ ์์ง์ ํ์ด๋จธ๋ฅผ ๋ธ๋ผ์ฐ์ (Web API)์ ๋งก๊ธด๋ค.
์ดํ ์๋ฐ์คํฌ๋ฆฝํธ๋ ๋ฐ๋ก ๋ค์ ์ค์ธ '2. ๋ค์ ์์
์ํ'์ ๋จผ์ ์ถ๋ ฅ ํ 2์ด๊ฐ ์ง๋๋ฉด ๋ธ๋ผ์ฐ์ ๊ฐ ์ฝ๋ฐฑ ํจ์๋ฅผ ์คํ ํ์ ๋ฃ์ด ์ ์ ์ ๋ณด๊ฐ ์ถ๋ ฅ๋๋ค.
์ฝ๋ฐฑ์ ์ ์ฉํ์ง๋ง ๋น๋๊ธฐ ์์
์ด ์ฐ์์ ์ผ๋ก ํ์ํ ๋ ์น๋ช
์ ์ธ ๋จ์ ์ด ์กด์ฌํ๋ค. ์ด๋ฅผ ํํ '์ฝ๋ฐฑ ์ง์ฅ'์ด๋ผ๊ณ ๋ถ๋ฅธ๋ค.
1) ๊ฐ๋
์ฑ ํ๊ดด
๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ค๊ณ ๊ทธ ๋ฐ์ดํฐ๋ก ๋ค๋ฅธ ์์ฒญ์ ํ๊ณ ๋ ๊ทธ ๊ฒฐ๊ณผ๋ก ๋ฌด์ธ๊ฐ๋ฅผ ํด์ผ ํ ๋ ์ฝ๋๋ ์ค๋ฅธ์ชฝ์ผ๋ก ๋์์ด ๋ฐ๋ ค๋๋ ์ํฉ์ด ๋ฐ์ํ๋ค.
// ์ฝ๋ฐฑ ์ง์ฅ
fetchUser(1, (user) => {
fetchPosts(user.id, (posts) => {
fetchComments(posts[0].id, (comments) => {
renderUI(comments, () => {
console.log('ํ๋ฉด ์ ๋ฐ์ดํธ...');
});
});
});
});
2) ์๋ฌ ์ฒ๋ฆฌ์ ์ด๋ ค์
์ฝ๋ฐฑ ๋ฐฉ์์ ์๋ฌ ์ฒ๋ฆฌ๊ฐ ๋งค์ฐ ๋ฒ๊ฑฐ๋กญ๋ค. ๊ฐ ๋จ๊ณ์ ์ฝ๋ฐฑ ํจ์๋ง๋ค ์๋ฌ ๋ฐ์ ์ ์ฒ๋ฆฌํ ๋ก์ง์ ์ค๋ณตํด์ ์์ฑํด์ผ ํ๋ฉฐ ์๋ฌ๊ฐ ์ด๋์ ์์๋์๋์ง๋ ์ถ์ ํ๊ธฐ๊ฐ ๋งค์ฐ ํ๋ค๋ค.
3) ์ ์ด๊ถ์ ์ญ์ (Inversion of Control)
๊ตฌ์กฐ์ ์ผ๋ก ์ฝ๋ฐฑ์ ๋ค๋ฅธ ํจ์(ex: ์ธ๋ถ ๋ผ์ด๋ธ๋ฌ๋ฆฌ)์ ๋๊ฒจ์ฃผ๋ ์๊ฐ, ๊ทธ ํจ์๊ฐ ๋ด ์ฝ๋ฐฑ์ ์ธ์ , ์ด๋ป๊ฒ, ๋ช ๋ฒ ์คํํ ์ง์ ๋ํ ์ ์ด๊ถ์ด ์๋๋ฐฉ์๊ฒ ๋์ด๊ฐ ๋ฒ๋ฆฐ๋ค.
์ด๋ ๋ง์ฝ ์ธ๋ถ ์์คํ
์ ์ค๋ฅ๋ก ๋ด ์ฝ๋ฐฑ์ด ๋ ๋ฒ ์คํ๋๊ฑฐ๋ ํน์ ์์ ์คํ๋์ง ์๋๋ค๋ฉด ํ๋ก๊ทธ๋จ์ ์น๋ช
์ ์ธ ์ค๋ฅ๊ฐ ์๊ธธ ์ ์๋ค.
์ด๋ฌํ ๋จ์ ๋ค์ ๊ทน๋ณตํ๊ธฐ ์ํด ๋ฑ์ฅํ ๊ฒ์ด ๋ฐ๋ก Promise์ด๋ค.
ํ๋ก๋ฏธ์ค๋ ์ฝ๋ฐฑ ์ง์ฅ์ ํด๊ฒฐํ๊ธฐ ์ํด ES6์์ ๋์
๋ ๋น๋๊ธฐ ์์
์ ๊ฒฐ๊ณผ๋ฅผ ๋ด๋ ๊ฐ์ฒด์ด๋ค. ์์
์ด ๋๋ ํ ์ฑ๊ณต ํน์ ์คํจ์ ๊ฒฐ๊ณผ๋ฅผ ๋๋ ค์ค๋ค๋ ์ฝ์์ ์๋ฏธํ๋ค.
*ํ๋ก๋ฏธ์ค์ 3๊ฐ์ง ์ํ (Lifecycle)
ํ๋ก๋ฏธ์ค๋ ์์
์ ์งํ ์ํฉ์ ๋ฐ๋ผ ์ธ ๊ฐ์ง ์ํ๋ฅผ ๊ฐ์ง๋ค.
const getData = new Promise((resolve, reject) => {
const success = true;
if (success) resolve("์ฑ๊ณต ๋ฐ์ดํฐ");
else reject("์๋ฌ ๋ฐ์");
})โ;
getData
.then(data => console.log(data)) // ์ฑ๊ณต ์ ์คํ
.catch(error => console.log(error)) // ์คํจ ์ ์คํ
.finally(() => console.log("์ข ๋ฃ")); // ๊ฒฐ๊ณผ์ ์๊ด์์ด ๋ฌด์กฐ๊ฑด ์คํ
์๋ฐ์คํฌ๋ฆฝํธ ์์ง์ ํ๋ก๋ฏธ์ค ๊ฐ์ฒด ๋ด๋ถ์ ์ฐ๋ฆฌ๊ฐ ์ง์ ์ ๊ทผํ ์ ์๋ Internal Slots๋ฅผ ๋์ด ์ํ๋ฅผ ๊ด๋ฆฌํ๋ค.
new Promise์ ์ธ์๋ก ๋ฐ๋ resolve์ reject๋ ์์ง์ด ์ ๊ณตํ๋ ์ค์์น์ด๋ค.
ํ๋ก๋ฏธ์ค์ ๋ด๊ธด ๋ฐ์ดํฐ๋ฅผ promise.data์ฒ๋ผ ๋ฐ๋ก ๊บผ๋ผ ์ ์๋ ์ด์ ๋ ๋น๋๊ธฐ์ฑ ๋๋ฌธ์ด๋ค. ์ฝ๋๊ฐ ์คํ๋๋ ์ํ์์๋ ๋ฐ์ดํฐ๊ฐ ์์ง ๋์ฐฉํ์ง ์์์ ๊ฐ๋ฅ์ฑ์ด ํฌ๊ธฐ ๋๋ฌธ์ .then()์ ์ฌ์ฉํ๋ค.
.then()์ ๊ฐ์ฒด์ ์ํ๊ฐ fulfilled๊ฐ ๋๋ ์๊ฐ ๋ฐ์ดํฐ๋ฅผ ๊บผ๋ด ์ด ํจ์๋ฅผ ์คํํด๋ฌ๋ผ๊ณ ๋ฏธ๋ฆฌ ์์ฝํ๋ ์ญํ ์ ์ํํ๋ค.
ํต์ฌ์ ํ๋ฒ Fulfilled ๋ Rejected ์ํ๊ฐ ๋๋ฉด ์ ๋ ๋ค๋ฅธ ์ํ๋ก ๋ณํ์ง ์๋๋ค๋ ์ ์ด๋ค. ์ด๋ ์ฝ๋ฐฑ ๋ฐฉ์์์ ๋ฐ์ํ ์ ์๋ ์ค๋ณต ์คํ๊ณผ ๊ฐ์ ๋ฌธ์ ๋ฅผ ์์ฒ ์ฐจ๋จํ๋ค.
ํ๋ก๋ฏธ์ค์ ๊ฐ์ฅ ํฐ ์ฅ์ ์ .then()์ ํตํด ๋น๋๊ธฐ ์์ ์ ์ฐ๊ฒฐํ ์ ์๋ค๋ ์ ์ด๋ค. ์ด๋ฅผ ํตํด ์ฝ๋ฐฑ ์ง์ฅ์ ๊น์ ๋ค์ฌ ์ฐ๊ธฐ๋ฅผ ์์์ ์๋๋ก ํ๋ฅด๋ ์ ํ์ ์ธ ์ฝ๋๋ก ๋ฐ๊ฟ ์ ์๋ค.
fetchUser(1)
.then(user => fetchPosts(user.id)) // ์ ์ ๋ฅผ ๊ฐ์ ธ์จ ํ ํฌ์คํธ ํธ์ถ
.then(posts => fetchComments(posts[0].id)) // ํฌ์คํธ๋ฅผ ๊ฐ์ ธ์จ ํ ๋๊ธ ํธ์ถ
.then(comments => renderUI(comments)) // ๋ชจ๋ ๋ฐ์ดํฐ๊ฐ ์ค๋น๋๋ฉด ํ๋ฉด ๋ ๋๋ง
.catch(error => console.error(error)) // ์ค๊ฐ ์ด๋์๋ ์๋ฌ๊ฐ ๋๋ฉด ์ฌ๊ธฐ์ ์ฒ๋ฆฌ
.finally(() => console.log('์์ ์๋ฃ'));
์ฝ๋ฐฑ ํจ์์ ๋จ์ ์ด์๋ ๊ฐ๋ ์ฑ๊ณผ ์๋ฌ ์ฒ๋ฆฌ๋ฅผ ๋ชจ๋ ํด๊ฒฐํ ์ ์๋ค. ๋ํ ์๋ฐ์คํฌ๋ฆฝํธ์ ํ์ค ๋ด์ฅ ๊ฐ์ฒด์ด๋ฏ๋ก fetch, axios ๋ฑ ํ๋์ ์ธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ค์ ๋ชจ๋ ์ด ํ๋ก๋ฏธ์ค๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ๋์ํ๋ค.
ํ๋ก๋ฏธ์ค๋ฅผ ํตํด ์ฝ๋ฐฑ ์ง์ฅ์ ํด๊ฒฐํ์์ง๋ง .then() ์ฒด์ด๋์ด ๊ธธ์ด์ง๋ฉด ์ฌ์ ํ ์ฝ๋์ ํ๋ฆ์ ํ๋์ ํ์
ํ๊ธฐ ์ด๋ ค์ธ ๋๊ฐ ์๋ค. ์ด๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด ES8์ ๋ฑ์ฅํ ๊ฒ์ด ๋ฐ๋ก async/await์ด๋ค.
๋น๋๊ธฐ ์ฝ๋๋ฅผ ๋ง์น ๋๊ธฐ ์ฝ๋์ฒ๋ผ ์์ฑํ ์ ์๊ฒ ํด์ฃผ๋ ํธ๋ฆฌํ ๋ฌธ๋ฒ์ ์คํ(Syntactic Sugar)์ด๋ค.
*ํต์ฌ ๊ฐ๋
async function processData() {
try {
// await๋ฅผ ์ฌ์ฉํ์ฌ ๋น๋๊ธฐ ๊ฒฐ๊ณผ๋ฅผ ๋ณ์์ ์ง์ ํ ๋น
const user = await fetchUser(1); // 1. ์ ์ ์ ๋ณด ๋์ฐฉ๊น์ง ๋๊ธฐ
const posts = await fetchPosts(user.id); // 2. ํฌ์คํธ ๋ก๋๊น์ง ๋๊ธฐ
console.log(posts);
} catch (error) {
// .catch() ๋์ try-catch ๋ฌธ์ผ๋ก ์๋ฌ ์ฒ๋ฆฌ
console.error('์๋ฌ ๋ฐ์: ', error);
} finally {
console.log('๋ชจ๋ ์์ ์ข ๋ฃ');
}
}
์์์ ๋ค๋ค๋ .then()์ด ๋ฐ์ดํฐ๊ฐ ์ค๋ฉด ์คํํ๋ผ๋ ์์ฝ ์์คํ
์ด์๋ค๋ฉด await๋ ํ๋ก๋ฏธ์ค๊ฐ fulfilled ์ํ๊ฐ ๋ ๋๊น์ง ๊ธฐ๋ค๋ ธ๋ค๊ฐ [[PromiseResult]]์ ๋ด๊ธด ๊ฐ์ ๊ทธ ์๋ฆฌ์์ ๋ฐ๋ก ๊บผ๋ด์ฃผ๋ ์ญํ ์ ํ๋ค.
๋๋ถ์ ๋ฒ๊ฑฐ๋ก์ด ์ฝ๋ฐฑ ํจ์๋ฅผ ์ฐ์ง ์๊ณ ๋ ๋น๋๊ธฐ ๋ฐ์ดํฐ๋ฅผ ์ผ๋ฐ ๋ณ์์ ๋ด๋ฏ์ด ์ฌ์ฉํ ์ ์๋ค.
