๐ ์๋ฐ์คํฌ๋ฆฝํธ ๋น๋๊ธฐ ํ๋ก๊ทธ๋๋ฐ: Promise์ async/await ์๋ฒฝ ๊ฐ์ด๋ (2025๋ ์ต์ ํธ๋ ๋) ๐

์๋ , ์ฝ๋ฉ ์น๊ตฌ๋ค! ์ค๋์ ์๋ฐ์คํฌ๋ฆฝํธ์ ๊ฝ์ด๋ผ๊ณ ํ ์ ์๋ ๋น๋๊ธฐ ํ๋ก๊ทธ๋๋ฐ์ ๋ํด ํจ๊ป ์์๋ณผ ๊ฑฐ์ผ. 2025๋ ํ์ฌ, ์น ๊ฐ๋ฐ์์ ๋น๋๊ธฐ ์ฒ๋ฆฌ๋ ์ ํ์ด ์๋ ํ์๊ฐ ๋์์ด. ํนํ Promise์ async/await๋ ๋ชจ๋ ์๋ฐ์คํฌ๋ฆฝํธ์ ํต์ฌ ๊ธฐ๋ฅ์ด์ง! ๐
์ด ๊ธ์ ํตํด ์ฝ๋ฐฑ ์ง์ฅ์์ ๋ฒ์ด๋ ๊น๋ํ๊ณ ํจ์จ์ ์ธ ๋น๋๊ธฐ ์ฝ๋๋ฅผ ์์ฑํ๋ ๋ฐฉ๋ฒ์ ๋ง์คํฐํ ์ ์์ ๊ฑฐ์ผ. ์ฌ๋ฅ๋ท์์ ์๋ฐ์คํฌ๋ฆฝํธ ๊ฐ๋ฐ ์ฌ๋ฅ์ ๊ณต์ ํ๊ฑฐ๋ ๊ตฌ๋งคํ ๋๋ ์ด๋ฐ ์ง์์ ์ ๋ง ์ค์ํ๊ฑฐ๋ ! ์, ์ด์ ์์ํด๋ณผ๊น? ๐ฎ
๐ ๋ชฉ์ฐจ
- ๋น๋๊ธฐ ํ๋ก๊ทธ๋๋ฐ์ด๋?
- ์ฝ๋ฐฑ ํจ์์ ์ฝ๋ฐฑ ์ง์ฅ
- Promise ์๋ฒฝ ์ดํดํ๊ธฐ
- async/await ๋ง์คํฐํ๊ธฐ
- ์ค์ ์์ ๋ก ๋ฐฐ์ฐ๋ ๋น๋๊ธฐ ์ฒ๋ฆฌ
- 2025๋ ์ต์ ๋น๋๊ธฐ ํจํด๊ณผ ํธ๋ ๋
- ์ฑ๋ฅ ์ต์ ํ ํ
- ๋ง๋ฌด๋ฆฌ ๋ฐ ์ถ๊ฐ ์๋ฃ
1. ๋น๋๊ธฐ ํ๋ก๊ทธ๋๋ฐ์ด๋? ๐ค
๋น๋๊ธฐ ํ๋ก๊ทธ๋๋ฐ์ด ๋ญ์ง ์น๊ตฌ์๊ฒ ์ค๋ช ํ๋ค๊ณ ์๊ฐํด๋ณผ๊น? ์์ฃผ ๊ฐ๋จํด! ๋น๋๊ธฐ๋ '๊ธฐ๋ค๋ฆฌ์ง ์๊ณ ๋ค๋ฅธ ์ผ์ ํ๋ ๊ฒ'์ด๋ผ๊ณ ์๊ฐํ๋ฉด ๋ผ.
์๋ฅผ ๋ค์ด๋ณผ๊ฒ. ๋ ์นดํ์์ ์ปคํผ๋ฅผ ์ฃผ๋ฌธํ์ด. ๋๊ธฐ์ ์ธ๊ณ์์ ์ปคํผ๊ฐ ๋์ฌ ๋๊น์ง ์นด์ดํฐ ์์์ ๊ผผ์ง ๋ชปํ๊ณ ๊ธฐ๋ค๋ ค์ผ ํด. ๊ทผ๋ฐ ๋น๋๊ธฐ์ ์ธ๊ณ์์ ? ์ฃผ๋ฌธํ๊ณ ์ง๋๋ฒจ์ ๋ฐ์ ๋ค์, ์๋ฆฌ์ ์์์ ๋ค๋ฅธ ์ผ(๋ ธํธ๋ถ ์ผ๊ธฐ, ์น๊ตฌ๋ ๋ํํ๊ธฐ ๋ฑ)์ ํ ์ ์์ง! ์ปคํผ๊ฐ ์ค๋น๋๋ฉด ๋ฒจ์ด ์ธ๋ฆฌ๊ณ , ๊ทธ๋ ๊ฐ์ ์ปคํผ๋ฅผ ๋ฐ์ผ๋ฉด ๋ผ. ์ด๊ฒ ๋ฐ๋ก ๋น๋๊ธฐ์ผ! ๐
1.1 ์๋ฐ์คํฌ๋ฆฝํธ์ ์ฑ๊ธ ์ค๋ ๋
์๋ฐ์คํฌ๋ฆฝํธ๋ ์ฑ๊ธ ์ค๋ ๋ ์ธ์ด์ผ. ์ฆ, ํ ๋ฒ์ ํ๋์ ์์ ๋ง ์ฒ๋ฆฌํ ์ ์์ด. ๊ทธ๋ฐ๋ฐ ์ด๋ป๊ฒ ์ฌ๋ฌ ์์ ์ ๋์์ ์ฒ๋ฆฌํ๋ ๊ฒ์ฒ๋ผ ๋ณด์ผ๊น? ๊ทธ ๋น๋ฐ์ ๋ฐ๋ก '์ด๋ฒคํธ ๋ฃจํ'์ ์์ด!
์ด๋ฒคํธ ๋ฃจํ๋ ์๋ฐ์คํฌ๋ฆฝํธ๊ฐ ๋น๋๊ธฐ ์์ ์ ์ฒ๋ฆฌํ ์ ์๊ฒ ํด์ฃผ๋ ํต์ฌ ๋ฉ์ปค๋์ฆ์ด์ผ. ์ ๊ทธ๋ฆผ์์ ๋ณผ ์ ์๋ฏ์ด, ์๋ฐ์คํฌ๋ฆฝํธ๋ ์ฝ ์คํ์์ ์ฝ๋๋ฅผ ์คํํ๊ณ , ๋น๋๊ธฐ ์์ ์ Web API๋ก ๋๊ฒจ. ์์ ์ด ์๋ฃ๋๋ฉด ์ฝ๋ฐฑ ํ์ ๋ค์ด๊ฐ๊ณ , ์ด๋ฒคํธ ๋ฃจํ๊ฐ ์ฝ ์คํ์ด ๋น์์ ๋ ์ฝ๋ฐฑ์ ์คํํด์ฃผ๋ ๊ฑฐ์ง! ๐
1.2 ๋๊ธฐ vs ๋น๋๊ธฐ ์ฝ๋ ๋น๊ต
๋๊ธฐ ์ฝ๋ ์์:
console.log("์์
1 ์์");
// ์๊ฐ์ด ์ค๋ ๊ฑธ๋ฆฌ๋ ์์
for (let i = 0; i < 1000000000; i++) {
// ๋ฌด๊ฑฐ์ด ๊ณ์ฐ
}
console.log("์์
1 ์๋ฃ");
console.log("์์
2 ์์");
๋น๋๊ธฐ ์ฝ๋ ์์:
console.log("์์
1 ์์");
// ๋น๋๊ธฐ ์์
(์๊ฐ์ด ๊ฑธ๋ฆฌ์ง๋ง ๊ธฐ๋ค๋ฆฌ์ง ์์)
setTimeout(() => {
console.log("์์
1 ์๋ฃ");
}, 2000);
console.log("์์
2 ์์"); // ์์
1์ด ๋๋๊ธฐ ์ ์ ์คํ๋จ!
๋น๋๊ธฐ ์ฝ๋์ ์ฅ์ ์ ๋ญ๊น? ๋ฐ๋ก ํจ์จ์ฑ์ด์ผ! ํนํ ๋ค์๊ณผ ๊ฐ์ ์ํฉ์์ ๋น์ ๋ฐํ์ง:
- ๋คํธ์ํฌ ์์ฒญ (API ํธ์ถ, ํ์ผ ๋ค์ด๋ก๋)
- ํ์ผ ์์คํ ์์ (ํ์ผ ์ฝ๊ธฐ/์ฐ๊ธฐ)
- ํ์ด๋จธ ๋ฐ ์ธํฐ๋ฒ (setTimeout, setInterval)
- ์ฌ์ฉ์ ์ ๋ ฅ ์ฒ๋ฆฌ (์ด๋ฒคํธ ๋ฆฌ์ค๋)
- ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ฟผ๋ฆฌ
2. ์ฝ๋ฐฑ ํจ์์ ์ฝ๋ฐฑ ์ง์ฅ ๐ฑ
์๋ฐ์คํฌ๋ฆฝํธ์์ ๋น๋๊ธฐ ์ฒ๋ฆฌ์ ๊ฐ์ฅ ๊ธฐ๋ณธ์ ์ธ ๋ฐฉ๋ฒ์ ์ฝ๋ฐฑ ํจ์๋ฅผ ์ฌ์ฉํ๋ ๊ฑฐ์ผ. ์ฝ๋ฐฑ์ด๋ ๊ฐ๋จํ ๋งํด์ '๋์ค์ ํธ์ถ๋ ํจ์'๋ฅผ ์๋ฏธํด.
์ฝ๋ฐฑ ํจ์๋ ๋ง์น ํผ์๋ฅผ ์ฃผ๋ฌธํ ํ "ํผ์๊ฐ ์ค๋น๋๋ฉด ์ด ๋ฒํธ๋ก ์ ํํด์ฃผ์ธ์"๋ผ๊ณ ๋งํ๋ ๊ฒ๊ณผ ๊ฐ์. ๋๋ ์ ํ๊ฐ ์ฌ ๋๊น์ง ๋ค๋ฅธ ์ผ์ ํ ์ ์๊ณ , ์ ํ(์ฝ๋ฐฑ)๊ฐ ์ค๋ฉด ๊ทธ๋ ํผ์๋ฅผ ๋ฐ์ผ๋ฌ ๊ฐ๋ ๊ฑฐ์ง! ๐
2.1 ๊ฐ๋จํ ์ฝ๋ฐฑ ์์
function downloadFile(url, callback) {
console.log(`${url}์์ ํ์ผ ๋ค์ด๋ก๋ ์์...`);
// ๋น๋๊ธฐ ์์
์๋ฎฌ๋ ์ด์
(์ค์ ๋ก๋ fetch ๋ฑ์ ์ฌ์ฉ)
setTimeout(() => {
const fileName = url.split('/').pop();
console.log(`${fileName} ๋ค์ด๋ก๋ ์๋ฃ!`);
callback(fileName); // ๋ค์ด๋ก๋ ์๋ฃ ํ ์ฝ๋ฐฑ ์คํ
}, 2000);
}
downloadFile('https://example.com/photo.jpg', (fileName) => {
console.log(`๋ค์ด๋ก๋ํ ${fileName}์ ์ฒ๋ฆฌํฉ๋๋ค.`);
});
console.log("๋ค์ด๋ก๋ ๋ช
๋ น ํ ์ฆ์ ์คํ๋๋ ์ฝ๋");
์ ์ฝ๋์ ์คํ ์์๋ ์ด๋ป๊ฒ ๋ ๊น? ๐ค
- "https://example.com/photo.jpg์์ ํ์ผ ๋ค์ด๋ก๋ ์์..." ์ถ๋ ฅ
- "๋ค์ด๋ก๋ ๋ช ๋ น ํ ์ฆ์ ์คํ๋๋ ์ฝ๋" ์ถ๋ ฅ
- 2์ด ํ "photo.jpg ๋ค์ด๋ก๋ ์๋ฃ!" ์ถ๋ ฅ
- "๋ค์ด๋ก๋ํ photo.jpg์ ์ฒ๋ฆฌํฉ๋๋ค." ์ถ๋ ฅ
์ด์ฒ๋ผ ๋น๋๊ธฐ ์์ ์ ์ฝ๋์ ์คํ ์์๊ฐ ์์ฑ๋ ์์์ ๋ค๋ฅผ ์ ์์ด. ์ด๊ฒ ๋ฐ๋ก ๋น๋๊ธฐ์ ํน์ง์ด์ง!
2.2 ์ฝ๋ฐฑ ์ง์ฅ (Callback Hell)
๊ทธ๋ฐ๋ฐ ๋น๋๊ธฐ ์์ ์ด ์ฌ๋ฌ ๊ฐ ์ค์ฒฉ๋๋ฉด ์ด๋ป๊ฒ ๋ ๊น? ๋ฐ๋ก ์ฝ๋ฐฑ ์ง์ฅ(Callback Hell)์ด ํผ์ณ์ ธ! ๐ฑ
์ค์ ์ฝ๋๋ก ๋ณด๋ฉด ์ด๋ฐ ๋ชจ์ต์ด์ผ:
// ์ฝ๋ฐฑ ์ง์ฅ์ ์์
getUserData(userId, (userData) => {
getPostsByUser(userData.id, (posts) => {
getCommentsForLatestPost(posts[0].id, (comments) => {
getLikesForComments(comments, (likes) => {
getUsersWhoLiked(likes, (users) => {
// ์ฌ๊ธฐ์ ๋ญ๊ฐ๋ฅผ ํ๋ ค๋ฉด...
// ๋ค์ฌ์ฐ๊ธฐ๊ฐ ๊ณ์ ๊น์ด์ง๊ณ ...
// ์ฝ๋๊ฐ ์ ์ ๋ณต์กํด์ง๊ณ ...
console.log("๋๋์ด ์ํ๋ ๋ฐ์ดํฐ์ ์ ๊ทผ!", users);
}, (error) => {
console.error("์ข์์ ๋๋ฅธ ์ฌ์ฉ์ ์ ๋ณด ๊ฐ์ ธ์ค๊ธฐ ์คํจ", error);
});
}, (error) => {
console.error("์ข์์ ์ ๋ณด ๊ฐ์ ธ์ค๊ธฐ ์คํจ", error);
});
}, (error) => {
console.error("๋๊ธ ๊ฐ์ ธ์ค๊ธฐ ์คํจ", error);
});
}, (error) => {
console.error("ํฌ์คํธ ๊ฐ์ ธ์ค๊ธฐ ์คํจ", error);
});
}, (error) => {
console.error("์ฌ์ฉ์ ๋ฐ์ดํฐ ๊ฐ์ ธ์ค๊ธฐ ์คํจ", error);
});
์ด๋ฐ ์ฝ๋๋ ์ฝ๊ธฐ ์ด๋ ต๊ณ , ์ ์ง๋ณด์ํ๊ธฐ ์ด๋ ต๊ณ , ์๋ฌ ์ฒ๋ฆฌ๋ ๋ณต์กํด์ ธ. ์ด๋ฐ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด ๋ฑ์ฅํ ๊ฒ์ด ๋ฐ๋ก Promise์ผ! ๐
3. Promise ์๋ฒฝ ์ดํดํ๊ธฐ ๐ค
Promise๋ ์๋ฐ์คํฌ๋ฆฝํธ์์ ๋น๋๊ธฐ ์์ ์ ์ต์ข ์๋ฃ(๋๋ ์คํจ)์ ๊ทธ ๊ฒฐ๊ณผ๊ฐ์ ๋ํ๋ด๋ ๊ฐ์ฒด์ผ. ์ฝ๊ฒ ๋งํ๋ฉด, ๋ฏธ๋์ ์๋ฃ๋ ์์ ์ ๊ฒฐ๊ณผ๋ฅผ ์ฝ์(promise)ํ๋ ๊ฐ์ฒด๋ผ๊ณ ์๊ฐํ๋ฉด ๋ผ!
Promise๋ฅผ ํ์ค์ ๋น์ ํ์๋ฉด ๋ ์คํ ๋์์ ์์์ ์ฃผ๋ฌธํ ํ ๋ฐ๋ '์ฃผ๋ฌธ ๋ฒํธํ'์ ๊ฐ์. ๊ทธ ๋ฒํธํ๋ "์์์ด ์ค๋น๋๋ฉด ์ด ๋ฒํธ๋ฅผ ํธ์ถํ ๊ฒ์"๋ผ๋ ์ฝ์์ด์ง. ๋๋ ๊ทธ ๋ฒํธํ๋ฅผ ๋ค๊ณ ๋ค๋ฅธ ์ผ์ ํ ์ ์๊ณ , ๋ฒํธ๊ฐ ํธ์ถ๋๋ฉด(Promise๊ฐ ์ดํ๋๋ฉด) ์์์ ๋ฐ์ ์ ์์ด! ๐
3.1 Promise์ 3๊ฐ์ง ์ํ
Promise๋ ํญ์ ๋ค์ ์ธ ๊ฐ์ง ์ํ ์ค ํ๋์ผ:
1. Pending (๋๊ธฐ)
์ด๊ธฐ ์ํ, ์์ง ์์ ์ด ์๋ฃ๋์ง ์์
2. Fulfilled (์ดํ)
์์ ์ด ์ฑ๊ณต์ ์ผ๋ก ์๋ฃ๋จ
3. Rejected (๊ฑฐ๋ถ)
์์ ์ด ์คํจํจ
3.2 Promise ์์ฑํ๊ธฐ
Promise ๊ฐ์ฒด๋ new Promise()
์์ฑ์๋ฅผ ์ฌ์ฉํด์ ๋ง๋ค์ด. ์ด ์์ฑ์๋ executor๋ผ๋ ํจ์๋ฅผ ์ธ์๋ก ๋ฐ์.
const myPromise = new Promise((resolve, reject) => {
// ๋น๋๊ธฐ ์์
์ํ
const success = true; // ์์
์ฑ๊ณต ์ฌ๋ถ (์์)
if (success) {
// ์์
์ด ์ฑ๊ณตํ๋ฉด resolve ํธ์ถ
resolve('์์
์ฑ๊ณต! ์ฌ๊ธฐ ๊ฒฐ๊ณผ๊ฐ์ด์ผ.');
} else {
// ์์
์ด ์คํจํ๋ฉด reject ํธ์ถ
reject(new Error('์์
์คํจ! ์ฌ๊ธฐ ์๋ฌ ์ ๋ณด์ผ.'));
}
});
์ค์ ์์ ๋ฅผ ํตํด Promise๋ฅผ ๋ง๋ค์ด๋ณผ๊น?
// ํ์ผ ๋ค์ด๋ก๋๋ฅผ Promise๋ก ๊ตฌํ
function downloadFilePromise(url) {
return new Promise((resolve, reject) => {
console.log(`${url}์์ ํ์ผ ๋ค์ด๋ก๋ ์์...`);
// ๋น๋๊ธฐ ์์
์๋ฎฌ๋ ์ด์
setTimeout(() => {
const random = Math.random();
if (random > 0.3) { // 70% ํ๋ฅ ๋ก ์ฑ๊ณต
const fileName = url.split('/').pop();
console.log(`${fileName} ๋ค์ด๋ก๋ ์๋ฃ!`);
resolve(fileName); // ์ฑ๊ณต ์ ํ์ผ๋ช
๋ฐํ
} else {
reject(new Error('๋คํธ์ํฌ ์ค๋ฅ๋ก ๋ค์ด๋ก๋ ์คํจ')); // ์คํจ ์ ์๋ฌ ๊ฐ์ฒด ๋ฐํ
}
}, 2000);
});
}
3.3 Promise ์ฌ์ฉํ๊ธฐ: then, catch, finally
Promise ๊ฐ์ฒด๋ then(), catch(), finally() ๋ฉ์๋๋ฅผ ํตํด ๊ฒฐ๊ณผ๋ฅผ ์ฒ๋ฆฌํ ์ ์์ด.
downloadFilePromise('https://example.com/photo.jpg')
.then((fileName) => {
console.log(`๋ค์ด๋ก๋ํ ${fileName}์ ์ฒ๋ฆฌํฉ๋๋ค.`);
return `์ฒ๋ฆฌ๋_${fileName}`; // ๋ค์ then์ผ๋ก ๊ฐ์ ์ ๋ฌ
})
.then((processedFile) => {
console.log(`${processedFile}์ ์ ์ฅํฉ๋๋ค.`);
return `์ ์ฅ๋_${processedFile}`; // ์ฒด์ด๋ ๊ณ์ ๊ฐ๋ฅ
})
.catch((error) => {
console.error(`์ค๋ฅ ๋ฐ์: ${error.message}`);
})
.finally(() => {
console.log('๋ค์ด๋ก๋ ์์
์ข
๋ฃ (์ฑ๊ณต์ด๋ ์คํจ๋ )');
});
console.log('๋ค์ด๋ก๋ ๋ช
๋ น ํ ์ฆ์ ์คํ๋๋ ์ฝ๋');
์ ์ฝ๋์ ์คํ ์์๋:
- "https://example.com/photo.jpg์์ ํ์ผ ๋ค์ด๋ก๋ ์์..." ์ถ๋ ฅ
- "๋ค์ด๋ก๋ ๋ช ๋ น ํ ์ฆ์ ์คํ๋๋ ์ฝ๋" ์ถ๋ ฅ
- 2์ด ํ, ์ฑ๊ณต ์:
- "photo.jpg ๋ค์ด๋ก๋ ์๋ฃ!" ์ถ๋ ฅ
- "๋ค์ด๋ก๋ํ photo.jpg์ ์ฒ๋ฆฌํฉ๋๋ค." ์ถ๋ ฅ
- "์ฒ๋ฆฌ๋_photo.jpg์ ์ ์ฅํฉ๋๋ค." ์ถ๋ ฅ
- "๋ค์ด๋ก๋ ์์ ์ข ๋ฃ (์ฑ๊ณต์ด๋ ์คํจ๋ )" ์ถ๋ ฅ
3.4 Promise ์ฒด์ด๋
Promise ์ฒด์ด๋์ ์ฌ๋ฌ ๋น๋๊ธฐ ์์ ์ ์์ฐจ์ ์ผ๋ก ์คํํ ์ ์๊ฒ ํด์ฃผ๋ ๊ฐ๋ ฅํ ๊ธฐ๋ฅ์ด์ผ. ์ฝ๋ฐฑ ์ง์ฅ์ ํํํ๊ฒ ๋ง๋ค์ด์ฃผ์ง! ๐
// ์ฝ๋ฐฑ ์ง์ฅ์ Promise ์ฒด์ด๋์ผ๋ก ๋ณํ
getUserDataPromise(userId)
.then(userData => {
return getPostsByUserPromise(userData.id);
})
.then(posts => {
return getCommentsForLatestPostPromise(posts[0].id);
})
.then(comments => {
return getLikesForCommentsPromise(comments);
})
.then(likes => {
return getUsersWhoLikedPromise(likes);
})
.then(users => {
console.log("๋๋์ด ์ํ๋ ๋ฐ์ดํฐ์ ์ ๊ทผ!", users);
})
.catch(error => {
console.error("์ด๋์ ๊ฐ ์ค๋ฅ ๋ฐ์:", error);
});
๋ ๊ฐ๊ฒฐํ๊ฒ ํ์ดํ ํจ์์ ์์์ ๋ฐํ์ ์ฌ์ฉํ๋ฉด:
getUserDataPromise(userId)
.then(userData => getPostsByUserPromise(userData.id))
.then(posts => getCommentsForLatestPostPromise(posts[0].id))
.then(comments => getLikesForCommentsPromise(comments))
.then(likes => getUsersWhoLikedPromise(likes))
.then(users => console.log("๋๋์ด ์ํ๋ ๋ฐ์ดํฐ์ ์ ๊ทผ!", users))
.catch(error => console.error("์ด๋์ ๊ฐ ์ค๋ฅ ๋ฐ์:", error));
์ด๋ ๊ฒ ํ๋ฉด ์ฝ๋๊ฐ ํจ์ฌ ๋ ์ฝ๊ธฐ ์ฝ๊ณ ์ ์ง๋ณด์ํ๊ธฐ ์ฌ์์ ธ! ๋ค์ฌ์ฐ๊ธฐ ๋ ๋ฒจ๋ ์ผ์ ํ๊ฒ ์ ์ง๋๊ณ , ์๋ฌ ์ฒ๋ฆฌ๋ ํ ๊ณณ์์ ํ ์ ์์ด.
3.5 Promise.all, Promise.race, Promise.allSettled
์ฌ๋ฌ Promise๋ฅผ ๋์์ ์ฒ๋ฆฌํด์ผ ํ ๋ ์ฌ์ฉํ๋ ๋ฉ์๋๋ค์ด์ผ:
Promise.all()
์ฌ๋ฌ Promise๋ฅผ ๋ณ๋ ฌ๋ก ์คํํ๊ณ ๋ชจ๋ Promise๊ฐ ์ฑ๊ณตํ์ ๋ ๊ฒฐ๊ณผ ๋ฐฐ์ด์ ๋ฐํํด. ํ๋๋ผ๋ ์คํจํ๋ฉด ์ ์ฒด๊ฐ ์คํจ๋ก ๊ฐ์ฃผ๋ผ.
Promise.race()
๊ฐ์ฅ ๋จผ์ ์๋ฃ๋๋ Promise์ ๊ฒฐ๊ณผ(์ฑ๊ณต ๋๋ ์คํจ)๋ฅผ ๋ฐํํด.
Promise.allSettled()
๋ชจ๋ Promise๊ฐ ์๋ฃ๋ ๋๊น์ง ๊ธฐ๋ค๋ฆฌ๊ณ , ๊ฐ Promise์ ์ํ์ ๊ฒฐ๊ณผ๋ฅผ ๊ฐ์ฒด ๋ฐฐ์ด๋ก ๋ฐํํด. (ES2020์์ ์ถ๊ฐ)
// ์ฌ๋ฌ ํ์ผ์ ๋์์ ๋ค์ด๋ก๋ํ๋ ์์
const fileUrls = [
'https://example.com/file1.jpg',
'https://example.com/file2.jpg',
'https://example.com/file3.jpg'
];
// Promise.all ์์
Promise.all(fileUrls.map(url => downloadFilePromise(url)))
.then(fileNames => {
console.log('๋ชจ๋ ํ์ผ ๋ค์ด๋ก๋ ์๋ฃ:', fileNames);
})
.catch(error => {
console.error('ํ๋ ์ด์์ ํ์ผ ๋ค์ด๋ก๋ ์คํจ:', error);
});
// Promise.race ์์
Promise.race(fileUrls.map(url => downloadFilePromise(url)))
.then(fileName => {
console.log('๊ฐ์ฅ ๋จผ์ ๋ค์ด๋ก๋๋ ํ์ผ:', fileName);
})
.catch(error => {
console.error('๊ฐ์ฅ ๋จผ์ ์คํจํ ๋ค์ด๋ก๋:', error);
});
// Promise.allSettled ์์
Promise.allSettled(fileUrls.map(url => downloadFilePromise(url)))
.then(results => {
results.forEach((result, index) => {
if (result.status === 'fulfilled') {
console.log(`${fileUrls[index]} ๋ค์ด๋ก๋ ์ฑ๊ณต:`, result.value);
} else {
console.log(`${fileUrls[index]} ๋ค์ด๋ก๋ ์คํจ:`, result.reason);
}
});
});
์ด๋ฐ ๋ฉ์๋๋ค์ ์ฌ๋ฌ ๋น๋๊ธฐ ์์ ์ ํจ์จ์ ์ผ๋ก ๊ด๋ฆฌํ ์ ์๊ฒ ํด์ค. ํนํ API ํธ์ถ์ด๋ ๋ฐ์ดํฐ ์ฒ๋ฆฌ ๊ฐ์ ์์ ์์ ๋งค์ฐ ์ ์ฉํด! ๐
4. async/await ๋ง์คํฐํ๊ธฐ โณ
Promise๋ ์ฝ๋ฐฑ ์ง์ฅ์ ํด๊ฒฐํด์คฌ์ง๋ง, ์ฌ์ ํ .then()
์ฒด์ธ์ด ๊ธธ์ด์ง๋ฉด ์ฝ๋๊ฐ ๋ณต์กํด์ง ์ ์์ด. ๊ทธ๋์ ES2017์์๋ async/await๋ผ๋ ๋ ์ง๊ด์ ์ธ ๋ฌธ๋ฒ์ด ๋์
๋์ด!
async/await๋ ๋น๋๊ธฐ ์ฝ๋๋ฅผ ๋ง์น ๋๊ธฐ ์ฝ๋์ฒ๋ผ ๋ณด์ด๊ฒ ํด์ค. ๋ง์น ์๋ฆฌ ๋ ์ํผ๋ฅผ ๋ฐ๋ผ๊ฐ๋ฏ์ด "์ด ์์ ์ด ๋๋๋ฉด ๋ค์ ์์ "์ด๋ผ๋ ์์๋ฅผ ๋ช ํํ๊ฒ ํํํ ์ ์์ง! ๐ณ
4.1 async ํจ์ ๊ธฐ๋ณธ
async
ํค์๋๋ ํจ์๋ฅผ ๋น๋๊ธฐ ํจ์๋ก ์ ์ธํด. async ํจ์๋ ํญ์ Promise๋ฅผ ๋ฐํํด!
// ๊ธฐ๋ณธ async ํจ์
async function greet() {
return "์๋
ํ์ธ์!";
}
// ์ ํจ์๋ ๋ค์๊ณผ ๋์ผํด:
// function greet() {
// return Promise.resolve("์๋
ํ์ธ์!");
// }
greet().then(message => console.log(message)); // "์๋
ํ์ธ์!" ์ถ๋ ฅ
4.2 await ํค์๋ ์ฌ์ฉํ๊ธฐ
await
ํค์๋๋ Promise๊ฐ ์ฒ๋ฆฌ๋ ๋๊น์ง ํจ์ ์คํ์ ์ผ์ ์ค์ง์์ผ. ๊ทธ๋ฆฌ๊ณ Promise์ ๊ฒฐ๊ณผ๊ฐ์ ๋ฐํํด. await
๋ async
ํจ์ ๋ด์์๋ง ์ฌ์ฉํ ์ ์์ด!
async function downloadAndProcessFile(url) {
try {
console.log(`${url} ๋ค์ด๋ก๋ ์์...`);
// await๋ Promise๊ฐ ์๋ฃ๋ ๋๊น์ง ๊ธฐ๋ค๋ ค
const fileName = await downloadFilePromise(url);
console.log(`${fileName} ๋ค์ด๋ก๋ ์๋ฃ!`);
// ์ฒซ ๋ฒ์งธ ์์
์ด ์๋ฃ๋ ํ์ ๋ ๋ฒ์งธ ์์
์์
const processedFile = `์ฒ๋ฆฌ๋_${fileName}`;
console.log(`${fileName}์ ์ฒ๋ฆฌํด์ ${processedFile} ์์ฑ`);
// ๋ ๋ฒ์งธ ์์
์ด ์๋ฃ๋ ํ์ ์ธ ๋ฒ์งธ ์์
์์
const savedFile = `์ ์ฅ๋_${processedFile}`;
console.log(`${processedFile}์ ์ ์ฅํด์ ${savedFile} ์์ฑ`);
return savedFile;
} catch (error) {
// try/catch๋ก ์๋ฌ ์ฒ๋ฆฌ
console.error(`์ค๋ฅ ๋ฐ์: ${error.message}`);
throw error; // ํ์ํ๋ค๋ฉด ์๋ฌ๋ฅผ ๋ค์ ๋์ง ์ ์์ด
} finally {
console.log('๋ค์ด๋ก๋ ์์
์ข
๋ฃ (์ฑ๊ณต์ด๋ ์คํจ๋ )');
}
}
// async ํจ์ ํธ์ถ
downloadAndProcessFile('https://example.com/photo.jpg')
.then(result => console.log('์ต์ข
๊ฒฐ๊ณผ:', result))
.catch(error => console.error('์ต์ข
์๋ฌ ์ฒ๋ฆฌ:', error));
console.log('๋ค์ด๋ก๋ ๋ช
๋ น ํ ์ฆ์ ์คํ๋๋ ์ฝ๋');
์ ์ฝ๋์ ์คํ ์์๋:
- "https://example.com/photo.jpg ๋ค์ด๋ก๋ ์์..." ์ถ๋ ฅ
- "๋ค์ด๋ก๋ ๋ช ๋ น ํ ์ฆ์ ์คํ๋๋ ์ฝ๋" ์ถ๋ ฅ
- 2์ด ํ, ์ฑ๊ณต ์:
- "photo.jpg ๋ค์ด๋ก๋ ์๋ฃ!" ์ถ๋ ฅ
- "photo.jpg์ ์ฒ๋ฆฌํด์ ์ฒ๋ฆฌ๋_photo.jpg ์์ฑ" ์ถ๋ ฅ
- "์ฒ๋ฆฌ๋_photo.jpg์ ์ ์ฅํด์ ์ ์ฅ๋_์ฒ๋ฆฌ๋_photo.jpg ์์ฑ" ์ถ๋ ฅ
- "๋ค์ด๋ก๋ ์์ ์ข ๋ฃ (์ฑ๊ณต์ด๋ ์คํจ๋ )" ์ถ๋ ฅ
- "์ต์ข ๊ฒฐ๊ณผ: ์ ์ฅ๋_์ฒ๋ฆฌ๋_photo.jpg" ์ถ๋ ฅ
4.3 Promise ์ฒด์ด๋๊ณผ async/await ๋น๊ต
์ด์ ์ ๋ดค๋ Promise ์ฒด์ด๋ ์์ ๋ฅผ async/await๋ก ๋ณํํด๋ณด์:
Promise ์ฒด์ด๋:
getUserDataPromise(userId)
.then(userData => getPostsByUserPromise(userData.id))
.then(posts => getCommentsForLatestPostPromise(posts[0].id))
.then(comments => getLikesForCommentsPromise(comments))
.then(likes => getUsersWhoLikedPromise(likes))
.then(users => console.log("๋๋์ด ์ํ๋ ๋ฐ์ดํฐ์ ์ ๊ทผ!", users))
.catch(error => console.error("์ด๋์ ๊ฐ ์ค๋ฅ ๋ฐ์:", error));
async/await:
async function getUsersWhoLikedLatestPost(userId) {
try {
const userData = await getUserDataPromise(userId);
const posts = await getPostsByUserPromise(userData.id);
const comments = await getCommentsForLatestPostPromise(posts[0].id);
const likes = await getLikesForCommentsPromise(comments);
const users = await getUsersWhoLikedPromise(likes);
console.log("๋๋์ด ์ํ๋ ๋ฐ์ดํฐ์ ์ ๊ทผ!", users);
return users;
} catch (error) {
console.error("์ด๋์ ๊ฐ ์ค๋ฅ ๋ฐ์:", error);
throw error;
}
}
// ํจ์ ํธ์ถ
getUsersWhoLikedLatestPost(123);
async/await๋ฅผ ์ฌ์ฉํ๋ฉด ์ฝ๋๊ฐ ๋ ์ง๊ด์ ์ด๊ณ ์ฝ๊ธฐ ์ฌ์์ ธ. ๋ง์น ๋๊ธฐ ์ฝ๋๋ฅผ ์์ฑํ๋ ๊ฒ์ฒ๋ผ ์์ฐจ์ ์ผ๋ก ์์ฑํ ์ ์์ด์ ๋ก์ง์ ์ดํดํ๊ธฐ ์ฝ์ง!
4.4 ๋ณ๋ ฌ ์ฒ๋ฆฌ์ async/await
์ฃผ์ํ ์ ์ await
๋ฅผ ์ฌ์ฉํ๋ฉด ๊ธฐ๋ณธ์ ์ผ๋ก ์์
์ด ์์ฐจ์ ์ผ๋ก ์คํ๋๋ค๋ ๊ฑฐ์ผ. ๋ง์ฝ ์ฌ๋ฌ ๋น๋๊ธฐ ์์
์ ๋ณ๋ ฌ๋ก ์ฒ๋ฆฌํ๊ณ ์ถ๋ค๋ฉด Promise.all
๊ณผ ํจ๊ป ์ฌ์ฉํ๋ฉด ๋ผ!
// ์์ฐจ ์ฒ๋ฆฌ (๊ฐ ๋ค์ด๋ก๋๊ฐ ์๋ฃ๋ ํ ๋ค์ ๋ค์ด๋ก๋ ์์)
async function downloadFilesSequentially(urls) {
const fileNames = [];
for (const url of urls) {
const fileName = await downloadFilePromise(url); // ๊ฐ ๋ค์ด๋ก๋๋ฅผ ๊ธฐ๋ค๋ฆผ
fileNames.push(fileName);
}
return fileNames;
}
// ๋ณ๋ ฌ ์ฒ๋ฆฌ (๋ชจ๋ ๋ค์ด๋ก๋๋ฅผ ๋์์ ์์)
async function downloadFilesParallel(urls) {
// Promise.all๊ณผ ํจ๊ป ์ฌ์ฉํ๋ฉด ๋ชจ๋ Promise๋ฅผ ๋์์ ์คํ
const fileNames = await Promise.all(
urls.map(url => downloadFilePromise(url))
);
return fileNames;
}
// ์ฌ์ฉ ์
const urls = [
'https://example.com/file1.jpg',
'https://example.com/file2.jpg',
'https://example.com/file3.jpg'
];
// ์์ฐจ ์ฒ๋ฆฌ (์ฝ 6์ด ์์)
downloadFilesSequentially(urls)
.then(files => console.log('์์ฐจ ๋ค์ด๋ก๋ ์๋ฃ:', files));
// ๋ณ๋ ฌ ์ฒ๋ฆฌ (์ฝ 2์ด ์์)
downloadFilesParallel(urls)
.then(files => console.log('๋ณ๋ ฌ ๋ค์ด๋ก๋ ์๋ฃ:', files));
์ฑ๋ฅ์ด ์ค์ํ ๊ฒฝ์ฐ ๋ณ๋ ฌ ์ฒ๋ฆฌ๋ฅผ ๊ณ ๋ คํด๋ด์ผ ํด. ํ์ง๋ง ์์ ๊ฐ์ ์์กด์ฑ์ด ์๋ค๋ฉด ์์ฐจ ์ฒ๋ฆฌ๊ฐ ํ์ํ ์๋ ์์ด!
4.5 async/await์ ์๋ฌ ์ฒ๋ฆฌ
async/await์ ํฐ ์ฅ์ ์ค ํ๋๋ try/catch ๊ตฌ๋ฌธ์ผ๋ก ์๋ฌ๋ฅผ ์ฒ๋ฆฌํ ์ ์๋ค๋ ๊ฑฐ์ผ. ์ด๋ ๋๊ธฐ ์ฝ๋์ ๋์ผํ ๋ฐฉ์์ผ๋ก ์๋ฌ๋ฅผ ์ฒ๋ฆฌํ ์ ์๊ฒ ํด์ค!
async function fetchUserData(userId) {
try {
const response = await fetch(`https://api.example.com/users/${userId}`);
if (!response.ok) {
throw new Error(`HTTP ์๋ฌ! ์ํ: ${response.status}`);
}
const userData = await response.json();
return userData;
} catch (error) {
console.error(`์ฌ์ฉ์ ๋ฐ์ดํฐ ๊ฐ์ ธ์ค๊ธฐ ์คํจ: ${error.message}`);
// ์๋ฌ ์ข
๋ฅ์ ๋ฐ๋ผ ๋ค๋ฅด๊ฒ ์ฒ๋ฆฌํ ์๋ ์์ด
if (error.message.includes('404')) {
return { error: '์ฌ์ฉ์๋ฅผ ์ฐพ์ ์ ์์ต๋๋ค.' };
}
return { error: '์๋ฒ ์ค๋ฅ๊ฐ ๋ฐ์ํ์ต๋๋ค.' };
}
}
์ด๋ ๊ฒ ํ๋ฉด ์๋ฌ ์ฒ๋ฆฌ ๋ก์ง์ด ๋ ๋ช ํํด์ง๊ณ , ํน์ ์๋ฌ ์ ํ์ ๋ฐ๋ผ ๋ค๋ฅด๊ฒ ๋์ํ ์๋ ์์ด!
5. ์ค์ ์์ ๋ก ๋ฐฐ์ฐ๋ ๋น๋๊ธฐ ์ฒ๋ฆฌ ๐ ๏ธ
์ด์ ์ค์ ์น ๊ฐ๋ฐ์์ ์์ฃผ ์ฌ์ฉ๋๋ ๋น๋๊ธฐ ์ฒ๋ฆฌ ์์ ๋ค์ ์ดํด๋ณผ๊ฒ. ์ด๋ก ๋ณด๋ค ์ค์ ์ด ๋ ์ฌ๋ฐ์์! ๐
5.1 API ๋ฐ์ดํฐ ๊ฐ์ ธ์ค๊ธฐ
์น ๊ฐ๋ฐ์์ ๊ฐ์ฅ ํํ ๋น๋๊ธฐ ์์ ์ API์์ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ค๋ ๊ฒ์ด์ผ. fetch API์ async/await๋ฅผ ์ฌ์ฉํด๋ณด์:
// ์ํ ์ ๋ณด๋ฅผ ๊ฐ์ ธ์ค๋ ํจ์
async function fetchMovies(searchTerm) {
try {
const response = await fetch(`https://api.example.com/movies?q=${searchTerm}`);
if (!response.ok) {
throw new Error(`API ์ค๋ฅ! ์ํ: ${response.status}`);
}
const data = await response.json();
return data.movies;
} catch (error) {
console.error('์ํ ๋ฐ์ดํฐ ๊ฐ์ ธ์ค๊ธฐ ์คํจ:', error);
return [];
}
}
// ์ํ ๋ชฉ๋ก์ ํ๋ฉด์ ํ์ํ๋ ํจ์
async function displayMovies(searchTerm) {
const movies = await fetchMovies(searchTerm);
if (movies.length === 0) {
console.log('๊ฒ์ ๊ฒฐ๊ณผ๊ฐ ์์ต๋๋ค.');
return;
}
console.log(`'${searchTerm}' ๊ฒ์ ๊ฒฐ๊ณผ:`);
movies.forEach(movie => {
console.log(`- ${movie.title} (${movie.year}): ${movie.rating}/10`);
});
}
// ์ฌ์ฉ ์
displayMovies('์ธํฐ์คํ
๋ผ');
5.2 ์ด๋ฏธ์ง ํ๋ฆฌ๋ก๋ฉ
์น์ฌ์ดํธ์ ์ฑ๋ฅ์ ํฅ์์ํค๊ธฐ ์ํด ์ด๋ฏธ์ง๋ฅผ ๋ฏธ๋ฆฌ ๋ก๋ํ๋ ์์ ๋ฅผ ์ดํด๋ณด์:
// ์ด๋ฏธ์ง ํ๋ฆฌ๋ก๋ฉ ํจ์
function preloadImage(url) {
return new Promise((resolve, reject) => {
const img = new Image();
img.onload = () => {
console.log(`์ด๋ฏธ์ง ๋ก๋ ์๋ฃ: ${url}`);
resolve(img);
};
img.onerror = () => {
reject(new Error(`์ด๋ฏธ์ง ๋ก๋ ์คํจ: ${url}`));
};
img.src = url;
});
}
// ์ฌ๋ฌ ์ด๋ฏธ์ง ํ๋ฆฌ๋ก๋ฉ
async function preloadGalleryImages(urls) {
try {
console.log('๊ฐค๋ฌ๋ฆฌ ์ด๋ฏธ์ง ํ๋ฆฌ๋ก๋ฉ ์์...');
const images = await Promise.all(urls.map(url => preloadImage(url)));
console.log(`${images.length}๊ฐ ์ด๋ฏธ์ง ํ๋ฆฌ๋ก๋ฉ ์๋ฃ!`);
return images;
} catch (error) {
console.error('์ด๋ฏธ์ง ํ๋ฆฌ๋ก๋ฉ ์ค ์ค๋ฅ ๋ฐ์:', error);
throw error;
}
}
// ์ฌ์ฉ ์
const imageUrls = [
'https://example.com/gallery/image1.jpg',
'https://example.com/gallery/image2.jpg',
'https://example.com/gallery/image3.jpg'
];
preloadGalleryImages(imageUrls)
.then(images => {
console.log('์ด์ ๊ฐค๋ฌ๋ฆฌ๋ฅผ ํ์ํ ์ ์์ต๋๋ค!');
// ์ฌ๊ธฐ์ ์ด๋ฏธ์ง๋ฅผ DOM์ ์ถ๊ฐํ๋ ๋ฑ์ ์์
์ํ
})
.catch(error => {
console.error('๊ฐค๋ฌ๋ฆฌ ๋ก๋ฉ ์คํจ:', error);
// ์๋ฌ ์ฒ๋ฆฌ (๋์ฒด ์ด๋ฏธ์ง ํ์ ๋ฑ)
});
5.3 ํ์์์ ์ค์ ํ๊ธฐ
๋คํธ์ํฌ ์์ฒญ์ด ๋๋ฌด ์ค๋ ๊ฑธ๋ฆด ๊ฒฝ์ฐ๋ฅผ ๋๋นํด ํ์์์์ ์ค์ ํ๋ ๊ฒ์ด ์ข์:
// Promise์ ํ์์์ ์ถ๊ฐํ๋ ํจ์
function withTimeout(promise, timeoutMs) {
// ํ์์์์ฉ Promise ์์ฑ
const timeoutPromise = new Promise((_, reject) => {
setTimeout(() => {
reject(new Error(`์์
์๊ฐ ์ด๊ณผ! (${timeoutMs}ms)`));
}, timeoutMs);
});
// ๋ ์ค ๋จผ์ ์๋ฃ๋๋ Promise ๋ฐํ (race)
return Promise.race([promise, timeoutPromise]);
}
// ์ฌ์ฉ ์: API ์์ฒญ์ 5์ด ํ์์์ ์ค์
async function fetchUserWithTimeout(userId) {
try {
const userPromise = fetch(`https://api.example.com/users/${userId}`)
.then(response => response.json());
// 5์ด ํ์์์ ์ค์
const userData = await withTimeout(userPromise, 5000);
console.log('์ฌ์ฉ์ ๋ฐ์ดํฐ:', userData);
return userData;
} catch (error) {
if (error.message.includes('์๊ฐ ์ด๊ณผ')) {
console.error('์๋ฒ ์๋ต์ด ๋๋ฌด ๋๋ฆฝ๋๋ค!');
} else {
console.error('๋ฐ์ดํฐ ๊ฐ์ ธ์ค๊ธฐ ์คํจ:', error);
}
throw error;
}
}
// ์ฌ์ฉ
fetchUserWithTimeout(123)
.catch(error => {
// ์๋ฌ ์ฒ๋ฆฌ
console.log('์ฌ์ฉ์์๊ฒ ์๋ฌ ๋ฉ์์ง ํ์:', error.message);
});
5.4 ์ฌ์๋ ๋ฉ์ปค๋์ฆ ๊ตฌํํ๊ธฐ
๋คํธ์ํฌ ์์ฒญ์ด ์คํจํ์ ๋ ์๋์ผ๋ก ์ฌ์๋ํ๋ ๊ธฐ๋ฅ์ ๊ตฌํํด๋ณด์:
// ์ฌ์๋ ๊ธฐ๋ฅ์ด ์๋ ๋น๋๊ธฐ ํจ์
async function fetchWithRetry(url, options = {}, maxRetries = 3, delayMs = 1000) {
let lastError;
for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
console.log(`์๋ ${attempt}/${maxRetries}: ${url} ์์ฒญ ์ค...`);
const response = await fetch(url, options);
if (!response.ok) {
throw new Error(`HTTP ์๋ฌ! ์ํ: ${response.status}`);
}
return await response.json(); // ์ฑ๊ณต ์ ๋ฐ์ดํฐ ๋ฐํ
} catch (error) {
console.warn(`์๋ ${attempt} ์คํจ:`, error.message);
lastError = error;
if (attempt < maxRetries) {
// ์ฌ์๋ ์ ์ง์ฐ ์๊ฐ (์ ํ ๋๋ ์ง์ ๋ฐฑ์คํ ์ ์ฉ ๊ฐ๋ฅ)
const delay = delayMs * attempt; // ์ ํ ๋ฐฑ์คํ
console.log(`${delay}ms ํ ์ฌ์๋...`);
await new Promise(resolve => setTimeout(resolve, delay));
}
}
}
// ๋ชจ๋ ์๋ ์คํจ ์
throw new Error(`${maxRetries}๋ฒ ์๋ ํ ์คํจ: ${lastError.message}`);
}
// ์ฌ์ฉ ์
async function getWeatherData(city) {
try {
const data = await fetchWithRetry(
`https://api.weather.example.com/forecast?city=${city}`,
{}, // ๊ธฐ๋ณธ ์ต์
3, // ์ต๋ 3๋ฒ ์๋
500 // 500ms๋ถํฐ ์์ํ๋ ๋ฐฑ์คํ
);
console.log(`${city}์ ๋ ์จ:`, data.forecast);
return data;
} catch (error) {
console.error('๋ ์จ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ฌ ์ ์์ต๋๋ค:', error);
return { error: '๋ ์จ ์ ๋ณด๋ฅผ ๋ถ๋ฌ์ฌ ์ ์์ต๋๋ค. ๋์ค์ ๋ค์ ์๋ํด์ฃผ์ธ์.' };
}
}
// ์ฌ์ฉ
getWeatherData('์์ธ');
5.5 ๋น๋๊ธฐ ๋ฐ์ดํฐ ์บ์ฑ
์์ฃผ ์ฌ์ฉ๋๋ API ๋ฐ์ดํฐ๋ฅผ ์บ์ฑํ์ฌ ์ฑ๋ฅ์ ํฅ์์ํค๋ ์์ :
// ๊ฐ๋จํ ๋ฉ๋ชจ๋ฆฌ ์บ์ ๊ตฌํ
class AsyncCache {
constructor(ttlMs = 60000) { // ๊ธฐ๋ณธ TTL: 1๋ถ
this.cache = new Map();
this.ttlMs = ttlMs;
}
async getOrFetch(key, fetchFn) {
// ์บ์์ ์ ํจํ ๋ฐ์ดํฐ๊ฐ ์๋์ง ํ์ธ
if (this.cache.has(key)) {
const cacheEntry = this.cache.get(key);
// ์บ์๊ฐ ์์ง ์ ํจํ์ง ํ์ธ
if (Date.now() < cacheEntry.expiresAt) {
console.log(`์บ์ ํํธ: ${key}`);
return cacheEntry.data;
} else {
console.log(`์บ์ ๋ง๋ฃ: ${key}`);
this.cache.delete(key);
}
}
// ์บ์์ ์์ผ๋ฉด ๋ฐ์ดํฐ ๊ฐ์ ธ์ค๊ธฐ
console.log(`์บ์ ๋ฏธ์ค: ${key}, ๋ฐ์ดํฐ ๊ฐ์ ธ์ค๋ ์ค...`);
try {
const data = await fetchFn();
// ๊ฒฐ๊ณผ๋ฅผ ์บ์์ ์ ์ฅ
this.cache.set(key, {
data,
expiresAt: Date.now() + this.ttlMs
});
return data;
} catch (error) {
console.error(`๋ฐ์ดํฐ ๊ฐ์ ธ์ค๊ธฐ ์คํจ: ${key}`, error);
throw error;
}
}
invalidate(key) {
console.log(`์บ์ ๋ฌดํจํ: ${key}`);
return this.cache.delete(key);
}
clear() {
console.log('์บ์ ์ ์ฒด ์ญ์ ');
this.cache.clear();
}
}
// ์ฌ์ฉ ์
const apiCache = new AsyncCache(5 * 60 * 1000); // 5๋ถ TTL
async function getUserProfile(userId) {
return apiCache.getOrFetch(
`user_${userId}`,
async () => {
const response = await fetch(`https://api.example.com/users/${userId}`);
if (!response.ok) throw new Error(`API ์ค๋ฅ: ${response.status}`);
return response.json();
}
);
}
// ์ฒซ ๋ฒ์งธ ํธ์ถ: API์์ ๊ฐ์ ธ์ด
getUserProfile(123).then(profile => console.log('ํ๋กํ:', profile));
// ์ ์ ํ ๋ค์ ํธ์ถ: ์บ์์์ ๊ฐ์ ธ์ด
setTimeout(() => {
getUserProfile(123).then(profile => console.log('ํ๋กํ (์บ์๋จ):', profile));
}, 2000);
// ์ฌ์ฉ์ ์ ๋ณด๊ฐ ์
๋ฐ์ดํธ๋์์ ๋ ์บ์ ๋ฌดํจํ
function updateUserProfile(userId, newData) {
// API ํธ์ถ๋ก ํ๋กํ ์
๋ฐ์ดํธ
fetch(`https://api.example.com/users/${userId}`, {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(newData)
})
.then(response => {
if (response.ok) {
// ์
๋ฐ์ดํธ ์ฑ๊ณต ์ ์บ์ ๋ฌดํจํ
apiCache.invalidate(`user_${userId}`);
}
return response.json();
})
.then(data => console.log('ํ๋กํ ์
๋ฐ์ดํธ๋จ:', data))
.catch(error => console.error('ํ๋กํ ์
๋ฐ์ดํธ ์คํจ:', error));
}
์ด๋ฐ ์ค์ ์์ ๋ค์ ์ฌ๋ฅ๋ท์์ ํ๋ก๊ทธ๋๋ฐ ์ฌ๋ฅ์ ๊ณต์ ํ๊ฑฐ๋ ๊ตฌ๋งคํ ๋ ์ ๋ง ์ ์ฉํ ์ง์์ด ๋ ์ ์์ด! ์ค์ ํ๋ก์ ํธ์์ ์์ฃผ ์ฌ์ฉ๋๋ ํจํด๋ค์ด๊ฑฐ๋ . ๐
6. 2025๋ ์ต์ ๋น๋๊ธฐ ํจํด๊ณผ ํธ๋ ๋ ๐ฎ
2025๋ ํ์ฌ, ์๋ฐ์คํฌ๋ฆฝํธ์ ๋น๋๊ธฐ ํ๋ก๊ทธ๋๋ฐ์ ๊ณ์ ๋ฐ์ ํ๊ณ ์์ด. ์ต์ ํธ๋ ๋์ ํจํด์ ์์๋ณด์!
6.1 Top-level await
ES2022๋ถํฐ ๋ชจ๋ ์ต์์ ๋ ๋ฒจ์์ await ์ฌ์ฉ์ด ๊ฐ๋ฅํด์ก์ด. async ํจ์ ์์ ์์ด๋ await๋ฅผ ์ฌ์ฉํ ์ ์๋ค๋ ๋ป์ด์ง!
// ๊ณผ๊ฑฐ์๋ ์ด๋ ๊ฒ ํด์ผ ํ์ด:
// import { setupDatabase } from './database.js';
//
// async function initialize() {
// const dbConnection = await setupDatabase();
// // ๋๋จธ์ง ์ฝ๋...
// }
//
// initialize();
// 2025๋
์๋ ์ด๋ ๊ฒ ํ ์ ์์ด:
import { setupDatabase } from './database.js';
// ๋ชจ๋ ์ต์์ ๋ ๋ฒจ์์ ๋ฐ๋ก await ์ฌ์ฉ
const dbConnection = await setupDatabase();
// ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ฐ๊ฒฐ์ด ์๋ฃ๋ ํ์ ์คํ๋๋ ์ฝ๋
console.log('๋ฐ์ดํฐ๋ฒ ์ด์ค ์ฐ๊ฒฐ ์๋ฃ:', dbConnection.status);
export function getUsers() {
// dbConnection์ ๋ฐ๋ก ์ฌ์ฉํ ์ ์์ด
return dbConnection.query('SELECT * FROM users');
}
์ด ๊ธฐ๋ฅ์ ๋ชจ๋ ์ด๊ธฐํ ์ ๋น๋๊ธฐ ์์ ์ ๋ ๊น๋ํ๊ฒ ์ฒ๋ฆฌํ ์ ์๊ฒ ํด์ค!
6.2 AbortController๋ก ๋น๋๊ธฐ ์์ ์ทจ์ํ๊ธฐ
2025๋ ์๋ ์งํ ์ค์ธ ๋น๋๊ธฐ ์์ ์ ์ทจ์ํ๋ ๊ฒ์ด ๋ ์ค์ํด์ก์ด. AbortController API๋ฅผ ์ฌ์ฉํ๋ฉด fetch ์์ฒญ ๋ฑ์ ์ทจ์ํ ์ ์์ง:
// ์ทจ์ ๊ฐ๋ฅํ API ์์ฒญ ํจ์
async function fetchWithTimeout(url, timeoutMs = 5000) {
// AbortController ์ธ์คํด์ค ์์ฑ
const controller = new AbortController();
const { signal } = controller;
// ํ์์์ ์ค์
const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
try {
const response = await fetch(url, { signal });
clearTimeout(timeoutId); // ํ์์์ ์ทจ์
return await response.json();
} catch (error) {
clearTimeout(timeoutId); // ํ์์์ ์ทจ์
if (error.name === 'AbortError') {
throw new Error(`์์ฒญ ์๊ฐ ์ด๊ณผ (${timeoutMs}ms)`);
}
throw error;
}
}
// ์ฌ์ฉ์ ์ธํฐ๋์
์ผ๋ก ์์ฒญ ์ทจ์ํ๊ธฐ
function searchProducts(query) {
// ์ด์ ์์ฒญ์ด ์์ผ๋ฉด ์ทจ์
if (window.currentSearchController) {
window.currentSearchController.abort();
console.log('์ด์ ๊ฒ์ ์์ฒญ ์ทจ์๋จ');
}
// ์ ์ปจํธ๋กค๋ฌ ์์ฑ
const controller = new AbortController();
window.currentSearchController = controller;
// ์์ฒญ ์์
fetch(`https://api.example.com/products?q=${query}`, {
signal: controller.signal
})
.then(response => response.json())
.then(data => {
console.log('๊ฒ์ ๊ฒฐ๊ณผ:', data);
displayResults(data);
})
.catch(error => {
if (error.name === 'AbortError') {
console.log('๊ฒ์ ์์ฒญ์ด ์ทจ์๋์์ต๋๋ค.');
} else {
console.error('๊ฒ์ ์ค๋ฅ:', error);
}
});
}
// ์ฌ์ฉ ์: ์ฌ์ฉ์๊ฐ ๊ฒ์์ฐฝ์ ํ์ดํํ ๋๋ง๋ค ์ด์ ์์ฒญ ์ทจ์
document.querySelector('#search-input').addEventListener('input', (e) => {
searchProducts(e.target.value);
});
6.3 ๋น๋๊ธฐ ์ดํฐ๋ ์ดํฐ์ for-await-of
2025๋ ์๋ ์คํธ๋ฆฌ๋ฐ ๋ฐ์ดํฐ ์ฒ๋ฆฌ๊ฐ ๋ ์ค์ํด์ก์ด. ๋น๋๊ธฐ ์ดํฐ๋ ์ดํฐ์ for-await-of ๋ฃจํ๋ฅผ ์ฌ์ฉํ๋ฉด ๋์ฉ๋ ๋ฐ์ดํฐ๋ฅผ ์ฒญํฌ ๋จ์๋ก ์ฒ๋ฆฌํ ์ ์์ง:
// ๋น๋๊ธฐ ์ดํฐ๋ฌ๋ธ ๊ฐ์ฒด ์์ฑ
async function* fetchCommentsStream(postId) {
let page = 1;
let hasMore = true;
while (hasMore) {
console.log(`๋๊ธ ํ์ด์ง ${page} ๊ฐ์ ธ์ค๋ ์ค...`);
const response = await fetch(
`https://api.example.com/posts/${postId}/comments?page=${page}`
);
const data = await response.json();
// ํ์ด์ง์ ๋๊ธ๋ค์ ํ๋์ฉ yield
for (const comment of data.comments) {
yield comment;
}
// ๋ค์ ํ์ด์ง ํ์ธ
hasMore = data.hasNextPage;
page++;
// API ๋ถํ ๋ฐฉ์ง๋ฅผ ์ํ ์ง์ฐ
if (hasMore) {
await new Promise(resolve => setTimeout(resolve, 300));
}
}
}
// for-await-of๋ก ์คํธ๋ฆผ ์ฒ๋ฆฌ
async function displayComments(postId) {
const commentStream = fetchCommentsStream(postId);
let count = 0;
console.log('๋๊ธ ์คํธ๋ฆผ ์ฒ๋ฆฌ ์์...');
// ๋น๋๊ธฐ ์ดํฐ๋ ์ดํฐ๋ฅผ for-await-of๋ก ์ํ
for await (const comment of commentStream) {
console.log(`๋๊ธ #${++count}: ${comment.author} - ${comment.text}`);
// ์ค์ ๋ก๋ DOM์ ๋๊ธ ์ถ๊ฐ ๋ฑ์ ์์
์ํ
// ๊ฐ ๋๊ธ์ด ๋์ฐฉํ ๋๋ง๋ค UI ์
๋ฐ์ดํธ ๊ฐ๋ฅ
// ์ฌ์ฉ์๊ฐ ์ค๋จ ๋ฒํผ์ ๋๋ ๋์ง ํ์ธ (์์)
if (window.commentLoadingCancelled) {
console.log('์ฌ์ฉ์๊ฐ ๋๊ธ ๋ก๋ฉ์ ์ค๋จํ์ต๋๋ค.');
break;
}
}
console.log(`์ด ${count}๊ฐ ๋๊ธ ์ฒ๋ฆฌ ์๋ฃ!`);
}
// ์ฌ์ฉ
displayComments(42);
6.4 Web Workers๋ฅผ ํ์ฉํ ๋ณ๋ ฌ ์ฒ๋ฆฌ
2025๋ ์๋ ๋ฉํฐ์ฝ์ด ํ์ฉ์ด ๋ ์ค์ํด์ก์ด. Web Workers๋ฅผ ์ฌ์ฉํ๋ฉด ๋ฉ์ธ ์ค๋ ๋๋ฅผ ์ฐจ๋จํ์ง ์๊ณ ๋ฌด๊ฑฐ์ด ์์ ์ ์ฒ๋ฆฌํ ์ ์์ง:
// main.js
function processDataInWorker(data) {
return new Promise((resolve, reject) => {
// ์์ปค ์์ฑ
const worker = new Worker('data-worker.js');
// ์์ปค๋ก๋ถํฐ ๋ฉ์์ง ์์
worker.onmessage = (event) => {
console.log('์์ปค๋ก๋ถํฐ ๊ฒฐ๊ณผ ์์ ');
resolve(event.data);
worker.terminate(); // ์์
์๋ฃ ํ ์์ปค ์ข
๋ฃ
};
// ์์ปค ์ค๋ฅ ์ฒ๋ฆฌ
worker.onerror = (error) => {
console.error('์์ปค ์ค๋ฅ:', error);
reject(new Error('๋ฐ์ดํฐ ์ฒ๋ฆฌ ์ค ์ค๋ฅ ๋ฐ์'));
worker.terminate();
};
// ์์ปค์ ๋ฐ์ดํฐ ์ ์ก
console.log('์์ปค์ ๋ฐ์ดํฐ ์ ์ก ์ค...');
worker.postMessage(data);
});
}
// ์ฌ์ฉ ์
async function analyzeUserData() {
try {
// ๋์ฉ๋ ๋ฐ์ดํฐ ๊ฐ์ ธ์ค๊ธฐ
const response = await fetch('https://api.example.com/user-analytics');
const rawData = await response.json();
console.log('๋์ฉ๋ ๋ฐ์ดํฐ ๊ฐ์ ธ์ด, ์์ปค์์ ์ฒ๋ฆฌ ์์...');
// ์์ปค์์ ๋ฐ์ดํฐ ์ฒ๋ฆฌ (๋ฉ์ธ ์ค๋ ๋ ์ฐจ๋จ ์์)
const result = await processDataInWorker(rawData);
console.log('๋ถ์ ์๋ฃ:', result);
updateDashboard(result);
} catch (error) {
console.error('๋ถ์ ์คํจ:', error);
}
}
// data-worker.js (๋ณ๋ ํ์ผ)
/*
self.onmessage = function(event) {
const data = event.data;
console.log('์์ปค์์ ๋ฐ์ดํฐ ์์ , ์ฒ๋ฆฌ ์ค...');
// CPU ์ง์ฝ์ ์ธ ์์
์ํ
const result = performHeavyCalculations(data);
// ๊ฒฐ๊ณผ๋ฅผ ๋ฉ์ธ ์ค๋ ๋๋ก ๋ฐํ
self.postMessage(result);
};
function performHeavyCalculations(data) {
// ๋ณต์กํ ๋ฐ์ดํฐ ์ฒ๋ฆฌ ๋ก์ง...
return processedData;
}
*/
6.5 Reactive Programming๊ณผ Observable ํจํด
2025๋ ์๋ ๋ฐ์ํ ํ๋ก๊ทธ๋๋ฐ์ด ๋ ์ธ๊ธฐ๋ฅผ ์ป๊ณ ์์ด. RxJS ๊ฐ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ๋ฉด ๋ณต์กํ ๋น๋๊ธฐ ์ด๋ฒคํธ ์คํธ๋ฆผ์ ๋ ์ฝ๊ฒ ์ฒ๋ฆฌํ ์ ์์ง:
// RxJS ์์ (2025๋
๋ฒ์ )
import { fromEvent, debounceTime, switchMap, catchError, EMPTY } from 'rxjs';
// ๊ฒ์ ์
๋ ฅ ํ๋์ ์ด๋ฒคํธ๋ฅผ Observable๋ก ๋ณํ
const searchInput = document.getElementById('search-input');
const searchButton = document.getElementById('search-button');
// ์
๋ ฅ ์ด๋ฒคํธ์ ๋ฒํผ ํด๋ฆญ ์ด๋ฒคํธ ๊ฒฐํฉ
const searchEvents = fromEvent(searchInput, 'input').pipe(
debounceTime(300) // ํ์ดํ ๋ฉ์ถ ํ 300ms ๋๊ธฐ
);
const buttonClicks = fromEvent(searchButton, 'click');
// ๋ ์ด๋ฒคํธ ์คํธ๋ฆผ ๋ณํฉ
merge(searchEvents, buttonClicks).pipe(
// ํ์ฌ ์
๋ ฅ๊ฐ ๊ฐ์ ธ์ค๊ธฐ
map(() => searchInput.value.trim()),
// ๋น ๊ฒ์์ด ํํฐ๋ง
filter(query => query.length > 0),
// ์ด์ ์์ฒญ ์ทจ์ํ๊ณ ์ ์์ฒญ ์์
switchMap(query => {
console.log(`๊ฒ์ ์ค: ${query}`);
return fetch(`https://api.example.com/search?q=${query}`)
.then(response => response.json())
.catch(error => {
console.error('๊ฒ์ ์ค๋ฅ:', error);
return []; // ์ค๋ฅ ์ ๋น ๋ฐฐ์ด ๋ฐํ
});
})
).subscribe({
next: results => {
console.log('๊ฒ์ ๊ฒฐ๊ณผ:', results);
displayResults(results);
},
error: error => console.error('๊ตฌ๋
์ค๋ฅ:', error)
});
์ด๋ฐ ์ต์ ํจํด๋ค์ ๋ ๋ณต์กํ ๋น๋๊ธฐ ์๋๋ฆฌ์ค๋ฅผ ๋ ์ฐ์ํ๊ฒ ์ฒ๋ฆฌํ ์ ์๊ฒ ํด์ค. ์ฌ๋ฅ๋ท์์ ์ต์ ์๋ฐ์คํฌ๋ฆฝํธ ๊ธฐ์ ์ ๋ฐฐ์ฐ๊ฑฐ๋ ๊ฐ๋ฅด์น๋ ๋ฐ ์์ฃผ ์ ์ฉํ ์ง์์ด ๋ ๊ฑฐ์ผ! ๐
7. ์ฑ๋ฅ ์ต์ ํ ํ โก
๋น๋๊ธฐ ํ๋ก๊ทธ๋๋ฐ์ ๋ง์คํฐํ๋ค๋ฉด, ์ด์ ์ฑ๋ฅ์ ์ต์ ํํ๋ ๋ฐฉ๋ฒ์ ๋ํด ์์๋ณด์! 2025๋ ํ์ฌ, ์น ์ ํ๋ฆฌ์ผ์ด์ ์ ์ฑ๋ฅ์ ๊ทธ ์ด๋ ๋๋ณด๋ค ์ค์ํด์ก์ด.
7.1 ๋น๋๊ธฐ ์์ ๋ณ๋ ฌํ
๋ ๋ฆฝ์ ์ธ ๋น๋๊ธฐ ์์ ์ ๊ฐ๋ฅํ ํ ๋ณ๋ ฌ๋ก ์คํํ๋ ๊ฒ์ด ์ข์:
// ์์ฐจ ์คํ (๋๋ฆผ)
async function loadDataSequential() {
console.time('์์ฐจ ๋ก๋ฉ');
const userData = await fetchUserData();
const productData = await fetchProducts();
const weatherData = await fetchWeather();
console.timeEnd('์์ฐจ ๋ก๋ฉ');
return { userData, productData, weatherData };
}
// ๋ณ๋ ฌ ์คํ (๋น ๋ฆ)
async function loadDataParallel() {
console.time('๋ณ๋ ฌ ๋ก๋ฉ');
// ๋ชจ๋ ์์ฒญ์ ๋์์ ์์
const userPromise = fetchUserData();
const productPromise = fetchProducts();
const weatherPromise = fetchWeather();
// ๋ชจ๋ ๊ฒฐ๊ณผ ๊ธฐ๋ค๋ฆฌ๊ธฐ
const [userData, productData, weatherData] = await Promise.all([
userPromise, productPromise, weatherPromise
]);
console.timeEnd('๋ณ๋ ฌ ๋ก๋ฉ');
return { userData, productData, weatherData };
}
// ๋ ๊ฐ๊ฒฐํ ๋ฐฉ๋ฒ
async function loadDataParallelConcise() {
console.time('๋ณ๋ ฌ ๋ก๋ฉ (๊ฐ๊ฒฐ)');
const [userData, productData, weatherData] = await Promise.all([
fetchUserData(),
fetchProducts(),
fetchWeather()
]);
console.timeEnd('๋ณ๋ ฌ ๋ก๋ฉ (๊ฐ๊ฒฐ)');
return { userData, productData, weatherData };
}
7.2 ๋ฉ๋ชจ์ด์ ์ด์ ๊ณผ ์บ์ฑ
๋์ผํ ๋น๋๊ธฐ ์์ ์ ๊ฒฐ๊ณผ๋ฅผ ์บ์ฑํ๋ฉด ์ฑ๋ฅ์ ํฌ๊ฒ ํฅ์์ํฌ ์ ์์ด:
// ๋ฉ๋ชจ์ด์ ์ด์
ํจ์
function memoizeAsync(fn) {
const cache = new Map();
return async function(...args) {
const key = JSON.stringify(args);
if (cache.has(key)) {
console.log('์บ์์์ ๊ฒฐ๊ณผ ๋ฐํ');
return cache.get(key);
}
console.log('์๋ก์ด ๊ฒฐ๊ณผ ๊ณ์ฐ ์ค');
const result = await fn(...args);
cache.set(key, result);
return result;
};
}
// ์ฌ์ฉ ์
const fetchUserMemoized = memoizeAsync(async (userId) => {
const response = await fetch(`https://api.example.com/users/${userId}`);
return response.json();
});
// ์ฒซ ๋ฒ์งธ ํธ์ถ: API ์์ฒญ ๋ฐ์
fetchUserMemoized(123).then(user => console.log('์ฌ์ฉ์ 1:', user));
// ๋ ๋ฒ์งธ ํธ์ถ: ์บ์์์ ๋ฐํ (API ์์ฒญ ์์)
setTimeout(() => {
fetchUserMemoized(123).then(user => console.log('์ฌ์ฉ์ 2 (์บ์๋จ):', user));
}, 2000);
7.3 ์ง์ฐ ๋ก๋ฉ๊ณผ ํ๋ฆฌํ์นญ
ํ์ํ ๋ฐ์ดํฐ๋ง ๋จผ์ ๋ก๋ํ๊ณ , ๋๋จธ์ง๋ ํ์ํ ๋ ๋๋ ๋ฏธ๋ฆฌ ์์ธกํ์ฌ ๋ก๋ํ๋ ์ ๋ต:
// ์ง์ฐ ๋ก๋ฉ ๊ตฌํ
class DataLoader {
constructor() {
this.data = {};
this.loading = {};
}
// ๋ฐ์ดํฐ ๊ฐ์ ธ์ค๊ธฐ (์ด๋ฏธ ๋ก๋ฉ ์ค์ด๋ฉด ๊ธฐ์กด Promise ๋ฐํ)
async load(key, fetchFn) {
// ์ด๋ฏธ ๋ฐ์ดํฐ๊ฐ ์์ผ๋ฉด ๋ฐ๋ก ๋ฐํ
if (this.data[key]) {
console.log(`${key} ๋ฐ์ดํฐ ์ด๋ฏธ ๋ก๋๋จ`);
return this.data[key];
}
// ์ด๋ฏธ ๋ก๋ฉ ์ค์ด๋ฉด ๊ธฐ์กด Promise ๋ฐํ
if (this.loading[key]) {
console.log(`${key} ๋ฐ์ดํฐ ๋ก๋ฉ ์ค, ๊ธฐ์กด ์์ฒญ์ ์ฐ๊ฒฐ`);
return this.loading[key];
}
// ์๋ก ๋ก๋ฉ ์์
console.log(`${key} ๋ฐ์ดํฐ ๋ก๋ฉ ์์`);
this.loading[key] = fetchFn().then(result => {
this.data[key] = result;
delete this.loading[key];
return result;
});
return this.loading[key];
}
// ๋ฏธ๋ฆฌ ๋ฐ์ดํฐ ๋ก๋ (ํ๋ฆฌํ์นญ)
prefetch(key, fetchFn) {
if (!this.data[key] && !this.loading[key]) {
console.log(`${key} ๋ฐ์ดํฐ ํ๋ฆฌํ์นญ`);
this.load(key, fetchFn).catch(error => {
console.warn(`ํ๋ฆฌํ์นญ ์คํจ (${key}):`, error);
});
}
}
}
// ์ฌ์ฉ ์
const loader = new DataLoader();
// ํ์ ๋ฐ์ดํฐ ์ฆ์ ๋ก๋
async function loadInitialData() {
const userData = await loader.load('user', () =>
fetch('https://api.example.com/user').then(r => r.json())
);
// ์ฌ์ฉ์ ๋ฐ์ดํฐ ํ์
displayUserInfo(userData);
// ์ฌ์ฉ์ ๋ฐ์ดํฐ ๋ก๋ ํ ๊ด๋ จ ๋ฐ์ดํฐ ๋ฏธ๋ฆฌ ๋ก๋
loader.prefetch('notifications', () =>
fetch('https://api.example.com/notifications').then(r => r.json())
);
loader.prefetch('recommendations', () =>
fetch('https://api.example.com/recommendations').then(r => r.json())
);
}
// ์ฌ์ฉ์๊ฐ ์๋ฆผ ํญ์ ํด๋ฆญํ์ ๋
async function showNotifications() {
const notifications = await loader.load('notifications', () =>
fetch('https://api.example.com/notifications').then(r => r.json())
);
displayNotifications(notifications);
}
7.4 ๋น๋๊ธฐ ์์ ๋ฐฐ์น ์ฒ๋ฆฌ
์ฌ๋ฌ ๊ฐ์ ์์ ๋น๋๊ธฐ ์์ ์ ํ๋์ ํฐ ์์ ์ผ๋ก ๋ฐฐ์น ์ฒ๋ฆฌํ๋ฉด ๋คํธ์ํฌ ์ค๋ฒํค๋๋ฅผ ์ค์ผ ์ ์์ด:
// ๋ฐฐ์น ์ฒ๋ฆฌ ์ ํธ๋ฆฌํฐ
class BatchProcessor {
constructor(processFn, options = {}) {
this.processFn = processFn;
this.maxBatchSize = options.maxBatchSize || 100;
this.maxWaitMs = options.maxWaitMs || 50;
this.items = [];
this.pendingPromises = new Map();
this.timeout = null;
}
// ์์ดํ
์ถ๊ฐ ๋ฐ Promise ๋ฐํ
add(item) {
const itemId = Math.random().toString(36).substr(2, 9);
// ์ Promise ์์ฑ ๋ฐ ์ ์ฅ
const promise = new Promise((resolve, reject) => {
this.pendingPromises.set(itemId, { resolve, reject });
});
// ์์ดํ
์ ๋ฐฐ์น์ ์ถ๊ฐ
this.items.push({ id: itemId, data: item });
// ํ์ด๋จธ ์ค์ (์์ง ์๋ ๊ฒฝ์ฐ)
if (!this.timeout) {
this.timeout = setTimeout(() => this.processItems(), this.maxWaitMs);
}
// ๋ฐฐ์น ํฌ๊ธฐ๊ฐ ์ต๋์ ๋๋ฌํ๋ฉด ์ฆ์ ์ฒ๋ฆฌ
if (this.items.length >= this.maxBatchSize) {
clearTimeout(this.timeout);
this.timeout = null;
this.processItems();
}
return promise;
}
// ๋ฐฐ์น ์ฒ๋ฆฌ ์คํ
async processItems() {
const itemsToProcess = [...this.items];
this.items = [];
this.timeout = null;
if (itemsToProcess.length === 0) return;
try {
console.log(`${itemsToProcess.length}๊ฐ ์์ดํ
๋ฐฐ์น ์ฒ๋ฆฌ ์ค...`);
// ๋ฐฐ์น ์ฒ๋ฆฌ ํจ์ ํธ์ถ
const results = await this.processFn(itemsToProcess.map(item => item.data));
// ๊ฐ Promise ํด๊ฒฐ
itemsToProcess.forEach((item, index) => {
const { resolve } = this.pendingPromises.get(item.id);
resolve(results[index]);
this.pendingPromises.delete(item.id);
});
} catch (error) {
console.error('๋ฐฐ์น ์ฒ๋ฆฌ ์คํจ:', error);
// ๋ชจ๋ Promise ๊ฑฐ๋ถ
itemsToProcess.forEach(item => {
const { reject } = this.pendingPromises.get(item.id);
reject(error);
this.pendingPromises.delete(item.id);
});
}
}
}
// ์ฌ์ฉ ์: ์ฌ๋ฌ ์ฌ์ฉ์ ์ ๋ณด๋ฅผ ํ ๋ฒ์ ๊ฐ์ ธ์ค๊ธฐ
const userBatchLoader = new BatchProcessor(async (userIds) => {
// ์ฌ๋ฌ ID๋ฅผ ํ ๋ฒ์ ์์ฒญ
const response = await fetch('https://api.example.com/users/batch', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ ids: userIds })
});
const users = await response.json();
// ๊ฐ ID์ ๋ํ ๊ฒฐ๊ณผ ๋งคํ
return userIds.map(id => users.find(user => user.id === id) || null);
}, { maxBatchSize: 50, maxWaitMs: 100 });
// ๊ฐ๋ณ ์ฌ์ฉ์ ๋ก๋ ํจ์
async function loadUser(userId) {
return userBatchLoader.add(userId);
}
// ์ฌ๋ฌ ์ฌ์ฉ์ ๋ก๋ (๋ด๋ถ์ ์ผ๋ก ๋ฐฐ์น ์ฒ๋ฆฌ๋จ)
loadUser(1).then(user => console.log('์ฌ์ฉ์ 1:', user));
loadUser(2).then(user => console.log('์ฌ์ฉ์ 2:', user));
loadUser(3).then(user => console.log('์ฌ์ฉ์ 3:', user));
// ... ๋ ๋ง์ ์์ฒญ๋ค ...
7.5 ๋น๋๊ธฐ ์์ ์ฐ์ ์์ ์ง์
2025๋ ์๋ ์ค์ํ ์์ ์ ์ฐ์ ์์๋ฅผ ๋ถ์ฌํ๋ ๊ฒ์ด ๋ ์ค์ํด์ก์ด:
// ์ฐ์ ์์ ํ ๊ตฌํ
class PriorityQueue {
constructor() {
this.highPriority = [];
this.normalPriority = [];
this.lowPriority = [];
this.isProcessing = false;
}
// ์์
์ถ๊ฐ
enqueue(task, priority = 'normal') {
switch (priority) {
case 'high':
this.highPriority.push(task);
break;
case 'low':
this.lowPriority.push(task);
break;
default:
this.normalPriority.push(task);
}
// ํ ์ฒ๋ฆฌ ์์
if (!this.isProcessing) {
this.processQueue();
}
}
// ํ ์ฒ๋ฆฌ
async processQueue() {
if (this.isProcessing) return;
this.isProcessing = true;
while (
this.highPriority.length > 0 ||
this.normalPriority.length > 0 ||
this.lowPriority.length > 0
) {
let task;
// ์ฐ์ ์์์ ๋ฐ๋ผ ์์
์ ํ
if (this.highPriority.length > 0) {
task = this.highPriority.shift();
} else if (this.normalPriority.length > 0) {
task = this.normalPriority.shift();
} else {
task = this.lowPriority.shift();
}
try {
await task();
} catch (error) {
console.error('์์
์คํ ์ค๋ฅ:', error);
}
// ๋ธ๋ผ์ฐ์ ๊ฐ ๋ค๋ฅธ ์์
์ ์ฒ๋ฆฌํ ์ ์๋๋ก ์ ์ ์๋ณด
await new Promise(resolve => setTimeout(resolve, 0));
}
this.isProcessing = false;
}
}
// ์ฌ์ฉ ์
const taskQueue = new PriorityQueue();
// ์ค์ํ ์ฌ์ฉ์ ๋ฐ์ดํฐ ๋ก๋ (๋์ ์ฐ์ ์์)
taskQueue.enqueue(async () => {
console.log('์ฌ์ฉ์ ํ๋กํ ๋ก๋ฉ (๋์ ์ฐ์ ์์)');
const userData = await fetch('/api/user').then(r => r.json());
updateUserProfile(userData);
}, 'high');
// ๋ ์ค์ํ ๋ฐ์ดํฐ ๋ก๋ (๋ฎ์ ์ฐ์ ์์)
taskQueue.enqueue(async () => {
console.log('์ถ์ฒ ์ํ ๋ก๋ฉ (๋ฎ์ ์ฐ์ ์์)');
const recommendations = await fetch('/api/recommendations').then(r => r.json());
updateRecommendations(recommendations);
}, 'low');
// ์ผ๋ฐ ์ฐ์ ์์ ์์
taskQueue.enqueue(async () => {
console.log('์๋ฆผ ๋ก๋ฉ (์ผ๋ฐ ์ฐ์ ์์)');
const notifications = await fetch('/api/notifications').then(r => r.json());
updateNotifications(notifications);
});
์ด๋ฐ ์ฑ๋ฅ ์ต์ ํ ๊ธฐ๋ฒ๋ค์ ์ฌ์ฉ์ ๊ฒฝํ์ ํฌ๊ฒ ํฅ์์ํฌ ์ ์์ด. ํนํ ๋๊ท๋ชจ ์น ์ ํ๋ฆฌ์ผ์ด์ ์์๋ ํ์์ ์ธ ๊ธฐ์ ์ด์ง! ์ฌ๋ฅ๋ท์์ ์น ๊ฐ๋ฐ ํ๋ก์ ํธ๋ฅผ ์๋ขฐํ๊ฑฐ๋ ์ํํ ๋ ์ด๋ฐ ๊ธฐ์ ์ ์ ์ฉํ๋ฉด ์ฐจ๋ณํ๋ ๊ฒฐ๊ณผ๋ฌผ์ ๋ง๋ค ์ ์์ ๊ฑฐ์ผ. ๐
8. ๋ง๋ฌด๋ฆฌ ๋ฐ ์ถ๊ฐ ์๋ฃ ๐
์ฌ๊ธฐ๊น์ง ์๋ฐ์คํฌ๋ฆฝํธ ๋น๋๊ธฐ ํ๋ก๊ทธ๋๋ฐ์ ์ธ๊ณ๋ฅผ ํจ๊ป ํํํด๋ดค์ด! ์ฝ๋ฐฑ๋ถํฐ Promise, async/await๊น์ง, ๊ทธ๋ฆฌ๊ณ 2025๋ ์ ์ต์ ํธ๋ ๋์ ์ฑ๋ฅ ์ต์ ํ ๊ธฐ๋ฒ๊น์ง ๋ค์ํ ๋ด์ฉ์ ๋ค๋ค์ง. ๐
๋ฐฐ์ด ๋ด์ฉ ์์ฝ
- ๋น๋๊ธฐ ํ๋ก๊ทธ๋๋ฐ์ ๊ธฐ๋ณธ ๊ฐ๋ ๊ณผ ์๋ฐ์คํฌ๋ฆฝํธ์ ์ด๋ฒคํธ ๋ฃจํ
- ์ฝ๋ฐฑ ํจ์์ ์ฝ๋ฐฑ ์ง์ฅ์ ๋ฌธ์ ์
- Promise์ ๊ฐ๋ ๊ณผ ์ฌ์ฉ๋ฒ (then, catch, finally)
- ์ฌ๋ฌ Promise๋ฅผ ์ฒ๋ฆฌํ๋ Promise.all, Promise.race, Promise.allSettled
- async/await ๋ฌธ๋ฒ์ผ๋ก ๋ ๊น๋ํ ๋น๋๊ธฐ ์ฝ๋ ์์ฑํ๊ธฐ
- 2025๋ ์ต์ ๋น๋๊ธฐ ํจํด๊ณผ ํธ๋ ๋
- ๋น๋๊ธฐ ์ฝ๋์ ์ฑ๋ฅ ์ต์ ํ ๊ธฐ๋ฒ
๋น๋๊ธฐ ํ๋ก๊ทธ๋๋ฐ์ ํ๋ ์น ๊ฐ๋ฐ์ ํต์ฌ์ด์ผ. ํนํ ์ฌ์ฉ์ ๊ฒฝํ์ด ์ค์ํ 2025๋ ์๋ ๋์ฑ ๊ทธ๋ ์ง! ์ฌ๋ฅ๋ท์์ ํ๋ก๊ทธ๋๋ฐ ๊ด๋ จ ์ฌ๋ฅ์ ๊ณต์ ํ๊ฑฐ๋ ๊ตฌ๋งคํ ๋, ์ด๋ฐ ๋น๋๊ธฐ ํ๋ก๊ทธ๋๋ฐ ์ง์์ ํฐ ๊ฒฝ์๋ ฅ์ด ๋ ์ ์์ด. ๐
๋ ๊ณต๋ถํ๋ฉด ์ข์ ์ฃผ์ ๋ค
1. ๋น๋๊ธฐ ์ํ ๊ด๋ฆฌ
Redux-Saga, MobX, Zustand ๋ฑ์ ์ฌ์ฉํ ๋น๋๊ธฐ ์ํ ๊ด๋ฆฌ
2. ๋ฐ์ํ ํ๋ก๊ทธ๋๋ฐ
RxJS๋ฅผ ํ์ฉํ ๋ณต์กํ ๋น๋๊ธฐ ์ด๋ฒคํธ ์คํธ๋ฆผ ์ฒ๋ฆฌ
3. ์๋ฒ ์ฌ์ด๋ ๋น๋๊ธฐ
Node.js์์์ ๋น๋๊ธฐ ํ๋ก๊ทธ๋๋ฐ๊ณผ ์ด๋ฒคํธ ๋ฃจํ
4. ๋น๋๊ธฐ ํ ์คํธ
Jest, Mocha ๋ฑ์ ์ฌ์ฉํ ๋น๋๊ธฐ ์ฝ๋ ํ ์คํธ ๋ฐฉ๋ฒ
์ถ์ฒ ์๋ฃ
๐ ๋์
- "JavaScript: The Good Parts" - Douglas Crockford
- "You Don't Know JS: Async & Performance" - Kyle Simpson
- "JavaScript Patterns" - Stoyan Stefanov
๐ ์น์ฌ์ดํธ
- MDN Web Docs - JavaScript ๊ฐ์ด๋
- JavaScript.info - ํ๋ JavaScript ํํ ๋ฆฌ์ผ
- ์ฌ๋ฅ๋ท - ์๋ฐ์คํฌ๋ฆฝํธ ๊ด๋ จ ๊ฐ์ ๋ฐ ํ๋ก์ ํธ
๐บ ๋์์ ๊ฐ์
- Udemy - "JavaScript: Understanding the Weird Parts"
- Frontend Masters - "JavaScript: The Hard Parts"
- YouTube - "Async JS Crash Course"
์๋ฐ์คํฌ๋ฆฝํธ ๋น๋๊ธฐ ํ๋ก๊ทธ๋๋ฐ์ ๊ณ์ํด์ ๋ฐ์ ํ๊ณ ์์ด. ๊พธ์คํ ๊ณต๋ถํ๊ณ ์ค์ตํ๋ฉด์ ์ต์ ํธ๋ ๋๋ฅผ ๋ฐ๋ผ๊ฐ๋ ๊ฒ์ด ์ค์ํด. ์ด ๊ธ์ด ๋์ ์๋ฐ์คํฌ๋ฆฝํธ ์ฌ์ ์ ๋์์ด ๋์๊ธธ ๋ฐ๋ผ! ๐
ํจ๊ป ์ฑ์ฅํด์!
๋ ๋ง์ ํ๋ก๊ทธ๋๋ฐ ์ง์๊ณผ ์ฌ๋ฅ์ ๊ณต์ ํ๊ณ ์ถ๋ค๋ฉด ์ฌ๋ฅ๋ท์ ๋ฐฉ๋ฌธํด๋ณด์ธ์. ๋ค์ํ ๊ฐ๋ฐ์๋ค๊ณผ ์ง์์ ๋๋๊ณ , ์๋ก์ด ๊ธฐ์ ์ ๋ฐฐ์ธ ์ ์๋ ๊ธฐํ๊ฐ ๊ธฐ๋ค๋ฆฌ๊ณ ์์ต๋๋ค! ๐ป
1. ๋น๋๊ธฐ ํ๋ก๊ทธ๋๋ฐ์ด๋? ๐ค
๋น๋๊ธฐ ํ๋ก๊ทธ๋๋ฐ์ด ๋ญ์ง ์น๊ตฌ์๊ฒ ์ค๋ช ํ๋ค๊ณ ์๊ฐํด๋ณผ๊น? ์์ฃผ ๊ฐ๋จํด! ๋น๋๊ธฐ๋ '๊ธฐ๋ค๋ฆฌ์ง ์๊ณ ๋ค๋ฅธ ์ผ์ ํ๋ ๊ฒ'์ด๋ผ๊ณ ์๊ฐํ๋ฉด ๋ผ.
์๋ฅผ ๋ค์ด๋ณผ๊ฒ. ๋ ์นดํ์์ ์ปคํผ๋ฅผ ์ฃผ๋ฌธํ์ด. ๋๊ธฐ์ ์ธ๊ณ์์ ์ปคํผ๊ฐ ๋์ฌ ๋๊น์ง ์นด์ดํฐ ์์์ ๊ผผ์ง ๋ชปํ๊ณ ๊ธฐ๋ค๋ ค์ผ ํด. ๊ทผ๋ฐ ๋น๋๊ธฐ์ ์ธ๊ณ์์ ? ์ฃผ๋ฌธํ๊ณ ์ง๋๋ฒจ์ ๋ฐ์ ๋ค์, ์๋ฆฌ์ ์์์ ๋ค๋ฅธ ์ผ(๋ ธํธ๋ถ ์ผ๊ธฐ, ์น๊ตฌ๋ ๋ํํ๊ธฐ ๋ฑ)์ ํ ์ ์์ง! ์ปคํผ๊ฐ ์ค๋น๋๋ฉด ๋ฒจ์ด ์ธ๋ฆฌ๊ณ , ๊ทธ๋ ๊ฐ์ ์ปคํผ๋ฅผ ๋ฐ์ผ๋ฉด ๋ผ. ์ด๊ฒ ๋ฐ๋ก ๋น๋๊ธฐ์ผ! ๐
1.1 ์๋ฐ์คํฌ๋ฆฝํธ์ ์ฑ๊ธ ์ค๋ ๋
์๋ฐ์คํฌ๋ฆฝํธ๋ ์ฑ๊ธ ์ค๋ ๋ ์ธ์ด์ผ. ์ฆ, ํ ๋ฒ์ ํ๋์ ์์ ๋ง ์ฒ๋ฆฌํ ์ ์์ด. ๊ทธ๋ฐ๋ฐ ์ด๋ป๊ฒ ์ฌ๋ฌ ์์ ์ ๋์์ ์ฒ๋ฆฌํ๋ ๊ฒ์ฒ๋ผ ๋ณด์ผ๊น? ๊ทธ ๋น๋ฐ์ ๋ฐ๋ก '์ด๋ฒคํธ ๋ฃจํ'์ ์์ด!
์ด๋ฒคํธ ๋ฃจํ๋ ์๋ฐ์คํฌ๋ฆฝํธ๊ฐ ๋น๋๊ธฐ ์์ ์ ์ฒ๋ฆฌํ ์ ์๊ฒ ํด์ฃผ๋ ํต์ฌ ๋ฉ์ปค๋์ฆ์ด์ผ. ์ ๊ทธ๋ฆผ์์ ๋ณผ ์ ์๋ฏ์ด, ์๋ฐ์คํฌ๋ฆฝํธ๋ ์ฝ ์คํ์์ ์ฝ๋๋ฅผ ์คํํ๊ณ , ๋น๋๊ธฐ ์์ ์ Web API๋ก ๋๊ฒจ. ์์ ์ด ์๋ฃ๋๋ฉด ์ฝ๋ฐฑ ํ์ ๋ค์ด๊ฐ๊ณ , ์ด๋ฒคํธ ๋ฃจํ๊ฐ ์ฝ ์คํ์ด ๋น์์ ๋ ์ฝ๋ฐฑ์ ์คํํด์ฃผ๋ ๊ฑฐ์ง! ๐
1.2 ๋๊ธฐ vs ๋น๋๊ธฐ ์ฝ๋ ๋น๊ต
๋๊ธฐ ์ฝ๋ ์์:
console.log("์์
1 ์์");
// ์๊ฐ์ด ์ค๋ ๊ฑธ๋ฆฌ๋ ์์
for (let i = 0; i < 1000000000; i++) {
// ๋ฌด๊ฑฐ์ด ๊ณ์ฐ
}
console.log("์์
1 ์๋ฃ");
console.log("์์
2 ์์");
๋น๋๊ธฐ ์ฝ๋ ์์:
console.log("์์
1 ์์");
// ๋น๋๊ธฐ ์์
(์๊ฐ์ด ๊ฑธ๋ฆฌ์ง๋ง ๊ธฐ๋ค๋ฆฌ์ง ์์)
setTimeout(() => {
console.log("์์
1 ์๋ฃ");
}, 2000);
console.log("์์
2 ์์"); // ์์
1์ด ๋๋๊ธฐ ์ ์ ์คํ๋จ!
๋น๋๊ธฐ ์ฝ๋์ ์ฅ์ ์ ๋ญ๊น? ๋ฐ๋ก ํจ์จ์ฑ์ด์ผ! ํนํ ๋ค์๊ณผ ๊ฐ์ ์ํฉ์์ ๋น์ ๋ฐํ์ง:
- ๋คํธ์ํฌ ์์ฒญ (API ํธ์ถ, ํ์ผ ๋ค์ด๋ก๋)
- ํ์ผ ์์คํ ์์ (ํ์ผ ์ฝ๊ธฐ/์ฐ๊ธฐ)
- ํ์ด๋จธ ๋ฐ ์ธํฐ๋ฒ (setTimeout, setInterval)
- ์ฌ์ฉ์ ์ ๋ ฅ ์ฒ๋ฆฌ (์ด๋ฒคํธ ๋ฆฌ์ค๋)
- ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ฟผ๋ฆฌ
2. ์ฝ๋ฐฑ ํจ์์ ์ฝ๋ฐฑ ์ง์ฅ ๐ฑ
์๋ฐ์คํฌ๋ฆฝํธ์์ ๋น๋๊ธฐ ์ฒ๋ฆฌ์ ๊ฐ์ฅ ๊ธฐ๋ณธ์ ์ธ ๋ฐฉ๋ฒ์ ์ฝ๋ฐฑ ํจ์๋ฅผ ์ฌ์ฉํ๋ ๊ฑฐ์ผ. ์ฝ๋ฐฑ์ด๋ ๊ฐ๋จํ ๋งํด์ '๋์ค์ ํธ์ถ๋ ํจ์'๋ฅผ ์๋ฏธํด.
์ฝ๋ฐฑ ํจ์๋ ๋ง์น ํผ์๋ฅผ ์ฃผ๋ฌธํ ํ "ํผ์๊ฐ ์ค๋น๋๋ฉด ์ด ๋ฒํธ๋ก ์ ํํด์ฃผ์ธ์"๋ผ๊ณ ๋งํ๋ ๊ฒ๊ณผ ๊ฐ์. ๋๋ ์ ํ๊ฐ ์ฌ ๋๊น์ง ๋ค๋ฅธ ์ผ์ ํ ์ ์๊ณ , ์ ํ(์ฝ๋ฐฑ)๊ฐ ์ค๋ฉด ๊ทธ๋ ํผ์๋ฅผ ๋ฐ์ผ๋ฌ ๊ฐ๋ ๊ฑฐ์ง! ๐
2.1 ๊ฐ๋จํ ์ฝ๋ฐฑ ์์
function downloadFile(url, callback) {
console.log(`${url}์์ ํ์ผ ๋ค์ด๋ก๋ ์์...`);
// ๋น๋๊ธฐ ์์
์๋ฎฌ๋ ์ด์
(์ค์ ๋ก๋ fetch ๋ฑ์ ์ฌ์ฉ)
setTimeout(() => {
const fileName = url.split('/').pop();
console.log(`${fileName} ๋ค์ด๋ก๋ ์๋ฃ!`);
callback(fileName); // ๋ค์ด๋ก๋ ์๋ฃ ํ ์ฝ๋ฐฑ ์คํ
}, 2000);
}
downloadFile('https://example.com/photo.jpg', (fileName) => {
console.log(`๋ค์ด๋ก๋ํ ${fileName}์ ์ฒ๋ฆฌํฉ๋๋ค.`);
});
console.log("๋ค์ด๋ก๋ ๋ช
๋ น ํ ์ฆ์ ์คํ๋๋ ์ฝ๋");
์ ์ฝ๋์ ์คํ ์์๋ ์ด๋ป๊ฒ ๋ ๊น? ๐ค
- "https://example.com/photo.jpg์์ ํ์ผ ๋ค์ด๋ก๋ ์์..." ์ถ๋ ฅ
- "๋ค์ด๋ก๋ ๋ช ๋ น ํ ์ฆ์ ์คํ๋๋ ์ฝ๋" ์ถ๋ ฅ
- 2์ด ํ "photo.jpg ๋ค์ด๋ก๋ ์๋ฃ!" ์ถ๋ ฅ
- "๋ค์ด๋ก๋ํ photo.jpg์ ์ฒ๋ฆฌํฉ๋๋ค." ์ถ๋ ฅ
์ด์ฒ๋ผ ๋น๋๊ธฐ ์์ ์ ์ฝ๋์ ์คํ ์์๊ฐ ์์ฑ๋ ์์์ ๋ค๋ฅผ ์ ์์ด. ์ด๊ฒ ๋ฐ๋ก ๋น๋๊ธฐ์ ํน์ง์ด์ง!
2.2 ์ฝ๋ฐฑ ์ง์ฅ (Callback Hell)
๊ทธ๋ฐ๋ฐ ๋น๋๊ธฐ ์์ ์ด ์ฌ๋ฌ ๊ฐ ์ค์ฒฉ๋๋ฉด ์ด๋ป๊ฒ ๋ ๊น? ๋ฐ๋ก ์ฝ๋ฐฑ ์ง์ฅ(Callback Hell)์ด ํผ์ณ์ ธ! ๐ฑ
์ค์ ์ฝ๋๋ก ๋ณด๋ฉด ์ด๋ฐ ๋ชจ์ต์ด์ผ:
// ์ฝ๋ฐฑ ์ง์ฅ์ ์์
getUserData(userId, (userData) => {
getPostsByUser(userData.id, (posts) => {
getCommentsForLatestPost(posts[0].id, (comments) => {
getLikesForComments(comments, (likes) => {
getUsersWhoLiked(likes, (users) => {
// ์ฌ๊ธฐ์ ๋ญ๊ฐ๋ฅผ ํ๋ ค๋ฉด...
// ๋ค์ฌ์ฐ๊ธฐ๊ฐ ๊ณ์ ๊น์ด์ง๊ณ ...
// ์ฝ๋๊ฐ ์ ์ ๋ณต์กํด์ง๊ณ ...
console.log("๋๋์ด ์ํ๋ ๋ฐ์ดํฐ์ ์ ๊ทผ!", users);
}, (error) => {
console.error("์ข์์ ๋๋ฅธ ์ฌ์ฉ์ ์ ๋ณด ๊ฐ์ ธ์ค๊ธฐ ์คํจ", error);
});
}, (error) => {
console.error("์ข์์ ์ ๋ณด ๊ฐ์ ธ์ค๊ธฐ ์คํจ", error);
});
}, (error) => {
console.error("๋๊ธ ๊ฐ์ ธ์ค๊ธฐ ์คํจ", error);
});
}, (error) => {
console.error("ํฌ์คํธ ๊ฐ์ ธ์ค๊ธฐ ์คํจ", error);
});
}, (error) => {
console.error("์ฌ์ฉ์ ๋ฐ์ดํฐ ๊ฐ์ ธ์ค๊ธฐ ์คํจ", error);
});
์ด๋ฐ ์ฝ๋๋ ์ฝ๊ธฐ ์ด๋ ต๊ณ , ์ ์ง๋ณด์ํ๊ธฐ ์ด๋ ต๊ณ , ์๋ฌ ์ฒ๋ฆฌ๋ ๋ณต์กํด์ ธ. ์ด๋ฐ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด ๋ฑ์ฅํ ๊ฒ์ด ๋ฐ๋ก Promise์ผ! ๐
3. Promise ์๋ฒฝ ์ดํดํ๊ธฐ ๐ค
Promise๋ ์๋ฐ์คํฌ๋ฆฝํธ์์ ๋น๋๊ธฐ ์์ ์ ์ต์ข ์๋ฃ(๋๋ ์คํจ)์ ๊ทธ ๊ฒฐ๊ณผ๊ฐ์ ๋ํ๋ด๋ ๊ฐ์ฒด์ผ. ์ฝ๊ฒ ๋งํ๋ฉด, ๋ฏธ๋์ ์๋ฃ๋ ์์ ์ ๊ฒฐ๊ณผ๋ฅผ ์ฝ์(promise)ํ๋ ๊ฐ์ฒด๋ผ๊ณ ์๊ฐํ๋ฉด ๋ผ!
Promise๋ฅผ ํ์ค์ ๋น์ ํ์๋ฉด ๋ ์คํ ๋์์ ์์์ ์ฃผ๋ฌธํ ํ ๋ฐ๋ '์ฃผ๋ฌธ ๋ฒํธํ'์ ๊ฐ์. ๊ทธ ๋ฒํธํ๋ "์์์ด ์ค๋น๋๋ฉด ์ด ๋ฒํธ๋ฅผ ํธ์ถํ ๊ฒ์"๋ผ๋ ์ฝ์์ด์ง. ๋๋ ๊ทธ ๋ฒํธํ๋ฅผ ๋ค๊ณ ๋ค๋ฅธ ์ผ์ ํ ์ ์๊ณ , ๋ฒํธ๊ฐ ํธ์ถ๋๋ฉด(Promise๊ฐ ์ดํ๋๋ฉด) ์์์ ๋ฐ์ ์ ์์ด! ๐
3.1 Promise์ 3๊ฐ์ง ์ํ
Promise๋ ํญ์ ๋ค์ ์ธ ๊ฐ์ง ์ํ ์ค ํ๋์ผ:
1. Pending (๋๊ธฐ)
์ด๊ธฐ ์ํ, ์์ง ์์ ์ด ์๋ฃ๋์ง ์์
2. Fulfilled (์ดํ)
์์ ์ด ์ฑ๊ณต์ ์ผ๋ก ์๋ฃ๋จ
3. Rejected (๊ฑฐ๋ถ)
์์ ์ด ์คํจํจ
3.2 Promise ์์ฑํ๊ธฐ
Promise ๊ฐ์ฒด๋ new Promise()
์์ฑ์๋ฅผ ์ฌ์ฉํด์ ๋ง๋ค์ด. ์ด ์์ฑ์๋ executor๋ผ๋ ํจ์๋ฅผ ์ธ์๋ก ๋ฐ์.
const myPromise = new Promise((resolve, reject) => {
// ๋น๋๊ธฐ ์์
์ํ
const success = true; // ์์
์ฑ๊ณต ์ฌ๋ถ (์์)
if (success) {
// ์์
์ด ์ฑ๊ณตํ๋ฉด resolve ํธ์ถ
resolve('์์
์ฑ๊ณต! ์ฌ๊ธฐ ๊ฒฐ๊ณผ๊ฐ์ด์ผ.');
} else {
// ์์
์ด ์คํจํ๋ฉด reject ํธ์ถ
reject(new Error('์์
์คํจ! ์ฌ๊ธฐ ์๋ฌ ์ ๋ณด์ผ.'));
}
});
์ค์ ์์ ๋ฅผ ํตํด Promise๋ฅผ ๋ง๋ค์ด๋ณผ๊น?
// ํ์ผ ๋ค์ด๋ก๋๋ฅผ Promise๋ก ๊ตฌํ
function downloadFilePromise(url) {
return new Promise((resolve, reject) => {
console.log(`${url}์์ ํ์ผ ๋ค์ด๋ก๋ ์์...`);
// ๋น๋๊ธฐ ์์
์๋ฎฌ๋ ์ด์
setTimeout(() => {
const random = Math.random();
if (random > 0.3) { // 70% ํ๋ฅ ๋ก ์ฑ๊ณต
const fileName = url.split('/').pop();
console.log(`${fileName} ๋ค์ด๋ก๋ ์๋ฃ!`);
resolve(fileName); // ์ฑ๊ณต ์ ํ์ผ๋ช
๋ฐํ
} else {
reject(new Error('๋คํธ์ํฌ ์ค๋ฅ๋ก ๋ค์ด๋ก๋ ์คํจ')); // ์คํจ ์ ์๋ฌ ๊ฐ์ฒด ๋ฐํ
}
}, 2000);
});
}
3.3 Promise ์ฌ์ฉํ๊ธฐ: then, catch, finally
Promise ๊ฐ์ฒด๋ then(), catch(), finally() ๋ฉ์๋๋ฅผ ํตํด ๊ฒฐ๊ณผ๋ฅผ ์ฒ๋ฆฌํ ์ ์์ด.
downloadFilePromise('https://example.com/photo.jpg')
.then((fileName) => {
console.log(`๋ค์ด๋ก๋ํ ${fileName}์ ์ฒ๋ฆฌํฉ๋๋ค.`);
return `์ฒ๋ฆฌ๋_${fileName}`; // ๋ค์ then์ผ๋ก ๊ฐ์ ์ ๋ฌ
})
.then((processedFile) => {
console.log(`${processedFile}์ ์ ์ฅํฉ๋๋ค.`);
return `์ ์ฅ๋_${processedFile}`; // ์ฒด์ด๋ ๊ณ์ ๊ฐ๋ฅ
})
.catch((error) => {
console.error(`์ค๋ฅ ๋ฐ์: ${error.message}`);
})
.finally(() => {
console.log('๋ค์ด๋ก๋ ์์
์ข
๋ฃ (์ฑ๊ณต์ด๋ ์คํจ๋ )');
});
console.log('๋ค์ด๋ก๋ ๋ช
๋ น ํ ์ฆ์ ์คํ๋๋ ์ฝ๋');
์ ์ฝ๋์ ์คํ ์์๋:
- "https://example.com/photo.jpg์์ ํ์ผ ๋ค์ด๋ก๋ ์์..." ์ถ๋ ฅ
- "๋ค์ด๋ก๋ ๋ช ๋ น ํ ์ฆ์ ์คํ๋๋ ์ฝ๋" ์ถ๋ ฅ
- 2์ด ํ, ์ฑ๊ณต ์:
- "photo.jpg ๋ค์ด๋ก๋ ์๋ฃ!" ์ถ๋ ฅ
- "๋ค์ด๋ก๋ํ photo.jpg์ ์ฒ๋ฆฌํฉ๋๋ค." ์ถ๋ ฅ
- "์ฒ๋ฆฌ๋_photo.jpg์ ์ ์ฅํฉ๋๋ค." ์ถ๋ ฅ
- "๋ค์ด๋ก๋ ์์ ์ข ๋ฃ (์ฑ๊ณต์ด๋ ์คํจ๋ )" ์ถ๋ ฅ
3.4 Promise ์ฒด์ด๋
Promise ์ฒด์ด๋์ ์ฌ๋ฌ ๋น๋๊ธฐ ์์ ์ ์์ฐจ์ ์ผ๋ก ์คํํ ์ ์๊ฒ ํด์ฃผ๋ ๊ฐ๋ ฅํ ๊ธฐ๋ฅ์ด์ผ. ์ฝ๋ฐฑ ์ง์ฅ์ ํํํ๊ฒ ๋ง๋ค์ด์ฃผ์ง! ๐
// ์ฝ๋ฐฑ ์ง์ฅ์ Promise ์ฒด์ด๋์ผ๋ก ๋ณํ
getUserDataPromise(userId)
.then(userData => {
return getPostsByUserPromise(userData.id);
})
.then(posts => {
return getCommentsForLatestPostPromise(posts[0].id);
})
.then(comments => {
return getLikesForCommentsPromise(comments);
})
.then(likes => {
return getUsersWhoLikedPromise(likes);
})
.then(users => {
console.log("๋๋์ด ์ํ๋ ๋ฐ์ดํฐ์ ์ ๊ทผ!", users);
})
.catch(error => {
console.error("์ด๋์ ๊ฐ ์ค๋ฅ ๋ฐ์:", error);
});
๋ ๊ฐ๊ฒฐํ๊ฒ ํ์ดํ ํจ์์ ์์์ ๋ฐํ์ ์ฌ์ฉํ๋ฉด:
getUserDataPromise(userId)
.then(userData => getPostsByUserPromise(userData.id))
.then(posts => getCommentsForLatestPostPromise(posts[0].id))
.then(comments => getLikesForCommentsPromise(comments))
.then(likes => getUsersWhoLikedPromise(likes))
.then(users => console.log("๋๋์ด ์ํ๋ ๋ฐ์ดํฐ์ ์ ๊ทผ!", users))
.catch(error => console.error("์ด๋์ ๊ฐ ์ค๋ฅ ๋ฐ์:", error));
์ด๋ ๊ฒ ํ๋ฉด ์ฝ๋๊ฐ ํจ์ฌ ๋ ์ฝ๊ธฐ ์ฝ๊ณ ์ ์ง๋ณด์ํ๊ธฐ ์ฌ์์ ธ! ๋ค์ฌ์ฐ๊ธฐ ๋ ๋ฒจ๋ ์ผ์ ํ๊ฒ ์ ์ง๋๊ณ , ์๋ฌ ์ฒ๋ฆฌ๋ ํ ๊ณณ์์ ํ ์ ์์ด.
3.5 Promise.all, Promise.race, Promise.allSettled
์ฌ๋ฌ Promise๋ฅผ ๋์์ ์ฒ๋ฆฌํด์ผ ํ ๋ ์ฌ์ฉํ๋ ๋ฉ์๋๋ค์ด์ผ:
Promise.all()
์ฌ๋ฌ Promise๋ฅผ ๋ณ๋ ฌ๋ก ์คํํ๊ณ ๋ชจ๋ Promise๊ฐ ์ฑ๊ณตํ์ ๋ ๊ฒฐ๊ณผ ๋ฐฐ์ด์ ๋ฐํํด. ํ๋๋ผ๋ ์คํจํ๋ฉด ์ ์ฒด๊ฐ ์คํจ๋ก ๊ฐ์ฃผ๋ผ.
Promise.race()
๊ฐ์ฅ ๋จผ์ ์๋ฃ๋๋ Promise์ ๊ฒฐ๊ณผ(์ฑ๊ณต ๋๋ ์คํจ)๋ฅผ ๋ฐํํด.
Promise.allSettled()
๋ชจ๋ Promise๊ฐ ์๋ฃ๋ ๋๊น์ง ๊ธฐ๋ค๋ฆฌ๊ณ , ๊ฐ Promise์ ์ํ์ ๊ฒฐ๊ณผ๋ฅผ ๊ฐ์ฒด ๋ฐฐ์ด๋ก ๋ฐํํด. (ES2020์์ ์ถ๊ฐ)
// ์ฌ๋ฌ ํ์ผ์ ๋์์ ๋ค์ด๋ก๋ํ๋ ์์
const fileUrls = [
'https://example.com/file1.jpg',
'https://example.com/file2.jpg',
'https://example.com/file3.jpg'
];
// Promise.all ์์
Promise.all(fileUrls.map(url => downloadFilePromise(url)))
.then(fileNames => {
console.log('๋ชจ๋ ํ์ผ ๋ค์ด๋ก๋ ์๋ฃ:', fileNames);
})
.catch(error => {
console.error('ํ๋ ์ด์์ ํ์ผ ๋ค์ด๋ก๋ ์คํจ:', error);
});
// Promise.race ์์
Promise.race(fileUrls.map(url => downloadFilePromise(url)))
.then(fileName => {
console.log('๊ฐ์ฅ ๋จผ์ ๋ค์ด๋ก๋๋ ํ์ผ:', fileName);
})
.catch(error => {
console.error('๊ฐ์ฅ ๋จผ์ ์คํจํ ๋ค์ด๋ก๋:', error);
});
// Promise.allSettled ์์
Promise.allSettled(fileUrls.map(url => downloadFilePromise(url)))
.then(results => {
results.forEach((result, index) => {
if (result.status === 'fulfilled') {
console.log(`${fileUrls[index]} ๋ค์ด๋ก๋ ์ฑ๊ณต:`, result.value);
} else {
console.log(`${fileUrls[index]} ๋ค์ด๋ก๋ ์คํจ:`, result.reason);
}
});
});
์ด๋ฐ ๋ฉ์๋๋ค์ ์ฌ๋ฌ ๋น๋๊ธฐ ์์ ์ ํจ์จ์ ์ผ๋ก ๊ด๋ฆฌํ ์ ์๊ฒ ํด์ค. ํนํ API ํธ์ถ์ด๋ ๋ฐ์ดํฐ ์ฒ๋ฆฌ ๊ฐ์ ์์ ์์ ๋งค์ฐ ์ ์ฉํด! ๐
- ์ง์์ธ์ ์ฒ - ์ง์ ์ฌ์ฐ๊ถ ๋ณดํธ ๊ณ ์ง
์ง์ ์ฌ์ฐ๊ถ ๋ณดํธ ๊ณ ์ง
- ์ ์๊ถ ๋ฐ ์์ ๊ถ: ๋ณธ ์ปจํ ์ธ ๋ ์ฌ๋ฅ๋ท์ ๋ ์ AI ๊ธฐ์ ๋ก ์์ฑ๋์์ผ๋ฉฐ, ๋ํ๋ฏผ๊ตญ ์ ์๊ถ๋ฒ ๋ฐ ๊ตญ์ ์ ์๊ถ ํ์ฝ์ ์ํด ๋ณดํธ๋ฉ๋๋ค.
- AI ์์ฑ ์ปจํ ์ธ ์ ๋ฒ์ ์ง์: ๋ณธ AI ์์ฑ ์ปจํ ์ธ ๋ ์ฌ๋ฅ๋ท์ ์ง์ ์ฐฝ์๋ฌผ๋ก ์ธ์ ๋๋ฉฐ, ๊ด๋ จ ๋ฒ๊ท์ ๋ฐ๋ผ ์ ์๊ถ ๋ณดํธ๋ฅผ ๋ฐ์ต๋๋ค.
- ์ฌ์ฉ ์ ํ: ์ฌ๋ฅ๋ท์ ๋ช ์์ ์๋ฉด ๋์ ์์ด ๋ณธ ์ปจํ ์ธ ๋ฅผ ๋ณต์ , ์์ , ๋ฐฐํฌ, ๋๋ ์์ ์ ์ผ๋ก ํ์ฉํ๋ ํ์๋ ์๊ฒฉํ ๊ธ์ง๋ฉ๋๋ค.
- ๋ฐ์ดํฐ ์์ง ๊ธ์ง: ๋ณธ ์ปจํ ์ธ ์ ๋ํ ๋ฌด๋จ ์คํฌ๋ํ, ํฌ๋กค๋ง, ๋ฐ ์๋ํ๋ ๋ฐ์ดํฐ ์์ง์ ๋ฒ์ ์ ์ฌ์ ๋์์ด ๋ฉ๋๋ค.
- AI ํ์ต ์ ํ: ์ฌ๋ฅ๋ท์ AI ์์ฑ ์ปจํ ์ธ ๋ฅผ ํ AI ๋ชจ๋ธ ํ์ต์ ๋ฌด๋จ ์ฌ์ฉํ๋ ํ์๋ ๊ธ์ง๋๋ฉฐ, ์ด๋ ์ง์ ์ฌ์ฐ๊ถ ์นจํด๋ก ๊ฐ์ฃผ๋ฉ๋๋ค.
์ฌ๋ฅ๋ท์ ์ต์ AI ๊ธฐ์ ๊ณผ ๋ฒ๋ฅ ์ ๊ธฐ๋ฐํ์ฌ ์์ฌ์ ์ง์ ์ฌ์ฐ๊ถ์ ์ ๊ทน์ ์ผ๋ก ๋ณดํธํ๋ฉฐ,
๋ฌด๋จ ์ฌ์ฉ ๋ฐ ์นจํด ํ์์ ๋ํด ๋ฒ์ ๋์์ ํ ๊ถ๋ฆฌ๋ฅผ ๋ณด์ ํฉ๋๋ค.
ยฉ 2025 ์ฌ๋ฅ๋ท | All rights reserved.
๋๊ธ 0๊ฐ