** ๐๋น๋๊ธฐ๋ ๋ฌด์์ธ๊ฐ?**
๋น๋๊ธฐ โ โ์๊ฐ์ด ์ค๋ ๊ฑธ๋ฆฌ๋ ์์ ์ ๊ธฐ๋ค๋ฆฌ์ง ์๊ณ ๋ฐ๋ก ๋ค์ ์์ ์ผ๋ก ๋์ด๊ฐ๋ ๋ฐฉ์โ
๐ฏ ๋๊ธฐ vs ๋น๋๊ธฐ ๋น๊ต
์ ํ | ๋๊ธฐ | ๋น๋๊ธฐ |
---|---|---|
ํน์ง | ์์ ์๋ฃ ํ ๋ค์ ์งํ | ์์ ์๋ฃ ์ฌ๋ถ ๊ด๊ณ์์ด ์งํ |
์์ | alert() , prompt() |
setTimeout() , fetch() |
์ฅ์ | ์์ฐจ์ , ์์ธก ๊ฐ๋ฅ | UI ๋ฉ์ถค ๋ฐฉ์ง, ํจ์จ์ |
๋จ์ | ๋๋ฆผ, ๋ธ๋กํน ๋ฐ์ | ๋ณต์กํ ์ ์ด, ์ฝ๋ฐฑ ํฌ ๊ฐ๋ฅ |
๐งฉ ๊ธฐ๋ณธ ์์
// ๋๊ธฐ
console.log('A');
console.log('B');
// ๋น๋๊ธฐ
console.log('A');
setTimeout(() => console.log('B'), 1000);
console.log('C');
2๏ธโฃ ๐งต ์ฑ๊ธ ์ค๋ ๋ & ์ด๋ฒคํธ ๋ฃจํ
๐ ์๋ฐ์คํฌ๋ฆฝํธ ํน์ง
- ์ฑ๊ธ ์ค๋ ๋(Single Thread)
- ํ ๋ฒ์ ํ๋์ ์์ ๋ง ์คํ
- ๋น๋๊ธฐ ์์ ์ ๋ธ๋ผ์ฐ์ (Web API)๊ฐ ๊ด๋ฆฌ โ ์๋ฃ๋๋ฉด ์ด๋ฒคํธ ๋ฃจํ(Event Loop) ํตํด ์ฝ๋ฐฑ ํ๋ก ์ ๋ฌ
๐ Event Loop ๋์ํ
[ Call Stack ] <---> [ Event Loop ] <---> [ Callback Queue ]
โ โ
์คํ ์ค์ธ ํจ์ ์๋ฃ๋ ๋น๋๊ธฐ ํจ์
๐ง ๋ฉด์ ํฌ์ธํธ
โJS๊ฐ ์ฑ๊ธ ์ค๋ ๋์ธ๋ฐ, ์ด๋ป๊ฒ ๋น๋๊ธฐ ์ฒ๋ฆฌ ๊ฐ๋ฅ?โ
โ Web API + Event Loop + Callback Queue ๊ตฌ์กฐ ๋๋ถ!
3๏ธโฃ ๐ Callback (์ฝ๋ฐฑ)
๐ ์ ์:
๋ค๋ฅธ ํจ์์ ์ธ์๋ก ์ ๋ฌ๋๋ ํจ์ โ ํน์ ์์ ์๋ฃ ํ ์คํ
โ ๊ธฐ์ด ์์
function greet(name, callback) {
console.log(`Hello, ${name}`);
callback();
}
greet('Tom', () => console.log('Welcome!'));
4๏ธโฃ ๐จ Callback Hell ์ฌํ
๐ ๋ฌธ์ ์
- ์ฝ๋ฐฑ ์ค์ฒฉ โ ๊ฐ๋ ์ฑ โ
- ์๋ฌ ์ฒ๋ฆฌ ๋ณต์ก
- ๋๋ฒ๊น ์ด๋ ค์
โ ์ฝ๋ฐฑ ํฌ ์์
setTimeout(() => {
console.log('1');
setTimeout(() => {
console.log('2');
setTimeout(() => {
console.log('3');
}, 1000);
}, 1000);
}, 1000);
5๏ธโฃ โจ Promise ๊ตฌ์กฐ & ๋์ ์๋ฆฌ
๐ ์ ์
๋น๋๊ธฐ ์์ ์ ๊ฒฐ๊ณผ๊ฐ(์ฑ๊ณต/์คํจ)์ ํํํ๋ ๊ฐ์ฒด
๐ ์ํ ๋ณํ
์ํ | ์ค๋ช |
---|---|
Pending | ๋๊ธฐ ์ํ |
Fulfilled | ์ฑ๊ณต(resolve) |
Rejected | ์คํจ(reject) |
โ ๊ธฐ๋ณธ ์์
const myPromise = new Promise((resolve, reject) => {
let success = true;
if(success) resolve('Success!');
else reject('Error!');
});
myPromise
.then(result => console.log(result)) // ์ฑ๊ณต
.catch(error => console.log(error)) // ์คํจ
.finally(() => console.log('Done!')); // ํญ์ ์คํ
๐งฉ Promise Chaining (์ฐ์ ์ฒ๋ฆฌ)
fetch('url1')
.then(res => res.json())
.then(data => fetch('url2'))
.then(res => res.json())
.then(data2 => console.log('Complete'))
.catch(err => console.error(err));
6๏ธโฃ ๐ฅ Promise ์ฌํ ํจํด
๐ Promise.all
Promise.all([
fetch('url1'),
fetch('url2')
]).then(([res1, res2]) => console.log('All done!'));
- ๋ชจ๋ ์ฑ๊ณตํด์ผ ๋ค์์ผ๋ก ์งํ
- ํ๋๋ผ๋ ์คํจ โ
.catch()
๋ก ์ด๋
โก Promise.race
Promise.race([
fetch('url1'),
fetch('url2')
]).then(res => console.log('First done!'));
- ๊ฐ์ฅ ๋นจ๋ฆฌ ๋๋ Promise ๋ฐํ
โ Promise.allSettled
Promise.allSettled([
Promise.resolve('A'),
Promise.reject('B')
]).then(results => console.log(results));
- ๋ชจ๋ Promise ์๋ฃ โ ์คํจ/์ฑ๊ณต ๋ชจ๋ ํ์ธ ๊ฐ๋ฅ
๐ Promise.any
Promise.any([
Promise.reject('X'),
Promise.resolve('Y')
]).then(result => console.log(result)); // Y
- ๊ฐ์ฅ ๋จผ์ ์ฑ๊ณตํ๋ ๊ฒ ๋ฐํ
7๏ธโฃ ๐ข async/await ๋ด๋ถ ์๋ ์๋ฆฌ & ์ฌํ
๐ ์ ์
Promise๋ฅผ ๋ ์ฝ๊ธฐ ์ฝ๊ฒ ์ฐ๊ธฐ ์ํ ๋ฌธ๋ฒ โ ๋๊ธฐ์ฒ๋ผ ๋ณด์ด์ง๋ง ๋ด๋ถ๋ ๋น๋๊ธฐ
โ ๊ธฐ๋ณธ ์์
async function fetchData() {
try {
const res = await fetch('url');
const data = await res.json();
console.log(data);
} catch (err) {
console.error(err);
} finally {
console.log('Done');
}
}
fetchData();
๐ ๋ณ๋ ฌ ์ฒ๋ฆฌ ์ต์ ํ: Promise.all ํ์ฉ
async function parallelFetch() {
const [res1, res2] = await Promise.all([
fetch('url1'),
fetch('url2')
]);
const data1 = await res1.json();
const data2 = await res2.json();
}
๐จ ์ฃผ์: forEach + async/await ๊ธ์ง
[1,2,3].forEach(async (num) => {
await fetchData(num); // ์ ๋๋ก ๊ธฐ๋ค๋ฆฌ์ง ์์
});
โ ์ ํํ ๋ฐฉ๋ฒ: forโฆof
for (const num of [1,2,3]) {
await fetchData(num);
}
8๏ธโฃ ๐ผ ๋น๋๊ธฐ + ์๋ฌ ํธ๋ค๋ง ์ฌํ
โ try-catch-finally ํจํด
async function robustFetch() {
try {
const res = await fetch('url');
if(!res.ok) throw new Error('Server error!');
const data = await res.json();
return data;
} catch (err) {
console.error('Handled:', err);
} finally {
console.log('Cleanup');
}
}
9๏ธโฃ ๐ง ๊ธฐ์ ๋ฉด์ ๋๋น ํต์ฌ ์์ฝ
์ง๋ฌธ | ํต์ฌ ๋ต๋ณ |
---|---|
JS์์ ๋น๋๊ธฐ ์ฒ๋ฆฌ ๋ฐฉ๋ฒ? | Callback, Promise, async/await |
Callback Hell ๋ฌธ์ ? | ์ค์ฒฉ โ ๊ฐ๋ ์ฑโ, ์๋ฌ ์ฒ๋ฆฌ ์ด๋ ค์ |
Promise ์ํ? | Pending โ Fulfilled/Rejected |
Promise.all, race ์ฐจ์ด? | all: ๋ชจ๋ ์ฑ๊ณต ์ ์งํ, race: ๊ฐ์ฅ ๋น ๋ฅธ ๊ฒ |
allSettled์ any๋ ์ธ์ ? | ์คํจ ํฌํจ ๋ชจ๋ ๊ฒฐ๊ณผ ํ์ธ, ๊ฐ์ฅ ๋จผ์ ์ฑ๊ณต ๋ฐํ |
async/await ๋ด๋ถ ์๋ฆฌ? | Promise ๊ธฐ๋ฐ, ์คํ ์ปจํ ์คํธ์ Promise ๋ฑ๋ก |
forEach + await ์ฌ์ฉํด๋ ๋๋? | ๋น์ถ์ฒ (ํ๋ฆ ์ ์ด ๋ถ๊ฐ), forโฆof ์ฌ์ฉ |
์๋ฌ ํธ๋ค๋ง ํจํด? | try-catch-finally, HTTP ์๋ฌ๋ ๋ฐ๋ก ํ์ธ ํ์ |
๐ ์ข ํฉ ์ ๋ฆฌ ์ฝ๋ ์
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>JavaScript ๋น๋๊ธฐ ํ๋ก๊ทธ๋๋ฐ ์ฌํ ์ค์ต</title>
<style>
.area {
background: lightgray;
border: 1px solid black;
width: 600px;
margin-bottom: 10px;
padding: 10px;
white-space: pre-wrap;
font-family: monospace;
}
.big { height: 600px; overflow-y: scroll; }
</style>
</head>
<body>
<h2>๐ข JavaScript ๋น๋๊ธฐ ํ๋ก๊ทธ๋๋ฐ ์ฌํ ์ค์ต</h2>
<div class="area big" id="outputArea"></div>
<script>
function runExamples() {
const output = document.getElementById("outputArea");
function log(text) { output.innerHTML += text + "\n"; }
log("โ
๋๊ธฐ vs ๋น๋๊ธฐ ์์ ");
log("๋๊ธฐ ์ฝ๋ ์คํ:");
log("A");
log("B");
log("\n๋น๋๊ธฐ ์ฝ๋ ์คํ:");
log("A");
setTimeout(() => log("B (1์ด ํ ์คํ)"), 1000); // 1์ด ํ ์คํ๋๋ ๋น๋๊ธฐ ์ฝ๋
log("C");
log("\nโ
Event Loop ์ดํด");
setTimeout(() => log("๐ ์ด๋ฒคํธ ๋ฃจํ ์คํ ์๋ฃ!"), 0); // ์ด๋ฒคํธ ๋ฃจํ์ ๋์ ๋ฐฉ์ ํ์ธ
log("๐ ๋๊ธฐ ์ฝ๋ ๋จผ์ ์คํ๋จ");
log("\nโ
Promise ๊ธฐ๋ณธ ์ฌ์ฉ");
const myPromise = new Promise((resolve) => {
setTimeout(() => resolve("๐ Promise ์ฑ๊ณต!"), 1500);
});
myPromise.then(result => log(result)); // Promise๊ฐ ์ฑ๊ณตํ๋ฉด ์คํ
log("\nโ
async/await ์ฌ์ฉ");
async function fetchData() {
log("โณ ๋ฐ์ดํฐ ๊ฐ์ ธ์ค๋ ์ค...");
await new Promise(resolve => setTimeout(resolve, 2000)); // 2์ด ๋๊ธฐ
log("โ
๋ฐ์ดํฐ ๊ฐ์ ธ์ค๊ธฐ ์๋ฃ!");
}
fetchData();
log("\nโ
Promise.all ์ฌ์ฉ");
async function parallelTasks() {
const [res1, res2] = await Promise.all([
new Promise(resolve => setTimeout(() => resolve("๐ฆ ์์
1 ์๋ฃ"), 1000)),
new Promise(resolve => setTimeout(() => resolve("๐ฆ ์์
2 ์๋ฃ"), 1200))
]);
log(res1);
log(res2);
}
parallelTasks();
log("\nโ
์๋ฌ ํธ๋ค๋ง");
async function errorHandlingExample() {
try {
throw new Error("๐ฅ ์ค๋ฅ ๋ฐ์!");
} catch (err) {
log("โ " + err.message); // ์ค๋ฅ ๋ฉ์์ง ์ถ๋ ฅ
} finally {
log("๐ ๏ธ ์ ๋ฆฌ ์๋ฃ"); // finally ๋ธ๋ก ์คํ
}
}
errorHandlingExample();
log("\nโ
๋ง์ดํฌ๋กํ์คํฌ vs ๋งคํฌ๋กํ์คํฌ");
setTimeout(() => log("๐ setTimeout (๋งคํฌ๋กํ์คํฌ)"), 0);
Promise.resolve().then(() => log("โก Promise (๋ง์ดํฌ๋กํ์คํฌ)"));
log("๐ ๋๊ธฐ ์ฝ๋ ์คํ ์ค");
}
runExamples();
</script>
</body>
</html>