๐ ์๋ฐ์คํฌ๋ฆฝํธ์ ๋น๋๊ธฐ ์ฒ๋ฆฌ
์น ํ์ด์ง๋ฅผ ๋์ฐ๊ณ ์๊ฐํด๋ณด์. ์ฌ์ฉ์๊ฐ ๋ฒํผ์ ํด๋ฆญํ๋ ์๊ฐ ์ ๋๋ฉ์ด์ ์ด ๋ถ๋๋ฝ๊ฒ ์คํ๋๊ณ , ๋์์ ์๋ฒ์์ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ค๋ API ์์ฒญ๋ ๋น์ทํ ์์ ์ ์ผ์ด๋๋ค. ์ฌ์ง์ด ์คํฌ๋กค ์ด๋ฒคํธ๋ ๋ฌธ์ ์์ด ์ ๋์ํ๋ค.
"์? ์๋ฐ์คํฌ๋ฆฝํธ๋ ์ฑ๊ธ ์ค๋ ๋๋ผ๋ฉด์? ๊ทธ๋ผ ์ด ๋ชจ๋ ์ผ๋ค์ ๋์์ ์ด๋ป๊ฒ ์ฒ๋ฆฌํ๋ ๊ฑฐ์ง?"
์ด๋ฐ ๊ถ๊ธ์ฆ์ด ๋ ๋ค๋ฉด ์์ฃผ ์์ฐ์ค๋ฝ๋ค. ์๋ฐ์คํฌ๋ฆฝํธ๋ ๋ถ๋ช ํ ๋ฒ์ ํ๋์ ์์ ๋ง ์ฒ๋ฆฌํ ์ ์๋ ์ธ์ด๋ค. ๊ทธ๋ผ์๋ ๋ถ๊ตฌํ๊ณ ๋ค์ํ ์์ ๋ค์ด "๊ฑฐ์ ๋์์" ์ผ์ด๋๋ ๊ฒ์ฒ๋ผ ๋ณด์ด๋ ์ด์ ๋ ๋ฌด์์ผ๊น? ์ด๋ฅผ ์ดํดํ๋ ค๋ฉด ๋จผ์ ์๋ฐ์คํฌ๋ฆฝํธ ์์ง์ ๋์ ์๋ฆฌ, ๊ทธ๋ฆฌ๊ณ ๋น๋๊ธฐ ์ฒ๋ฆฌ ๊ตฌ์กฐ์ ๋ํด ์ง๊ณ ๋์ด๊ฐ์ผ ํ๋ค.
โฌ๏ธ ์ค๋ ๋์ ๋ํ ๊ฐ๋ ์ ์๋ ๊ธ์ ์ฐธ๊ณ
[CS #6] Process์ Thread์ ๋ํ์ฌ
๐ Program์ด๋?ํ๋ก๊ทธ๋จ์ ์ปดํจํฐ์์ ์คํํ ์ ์๋ ํ์ผ๋ก, ์ฝ๊ฒ ๋งํด์ ์ฝ๋ ๋ฉ์ด๋ฆฌ๋ค. ์ด๋ ๋์คํฌ์ ์ ์ฅ๋ ์ ์ ์ธ ์กด์ฌ๋ก, ์คํ๋๊ธฐ ์ ๊น์ง๋ CPU์ ๋ฉ๋ชจ๋ฆฌ ๋ฑ ์์คํ ์์์ ์ฌ์ฉํ์ง ์
isliife2.tistory.com
console.log("Start");
setTimeout(() => console.log("Timeout"), 1000);
console.log("End");
// ๊ฒฐ๊ณผ:
// Start
// End
// Timeout
์๋ฐ์คํฌ๋ฆฝํธ๋ ์คํ ์ค์ธ ํจ์๊ฐ ๋๋๊ธฐ ์ ๊น์ง๋ ๋ค๋ฅธ ํจ์๊ฐ ๋ผ์ด๋ค ์ ์๋ค. ์ด๊ฑธ Run-to-Completion์ด๋ผ๊ณ ๋ถ๋ฅธ๋ค. ํจ์๊ฐ ํธ์ถ๋๋ฉด Call Stack์ ์์ด๊ณ , ์คํ์ด ๋๋์ผ๋ง Stack์์ ๋น ์ ธ๋๊ฐ๋ค. ๊ทธ ์ฌ์ด์ ์๋ฌด๋ฆฌ ๋ค๋ฅธ ์ด๋ฒคํธ๊ฐ ๋ฐ์ํ๋๋ผ๋, ๊ทธ ์ด๋ฒคํธ์ Callback์ "์ง๊ธ ์คํ ์ค์ธ ์ฝ๋๊ฐ ๋๋ ๋๊น์ง" ๋๊ธฐํ๊ฒ ๋๋ค.
"๊ทธ๋ฐ๋ฐ๋ ์ ๋์์ ์๋ํ๋ ๊ฒ์ฒ๋ผ ๋ณด์ผ๊น?"
๊ทธ ์ด์ ๋ ์๋ฐ์คํฌ๋ฆฝํธ๋ ์๋ฐ์คํฌ๋ฆฝํธ ์์ง๋ง์ผ๋ก ๋์ํ์ง ์๊ธฐ ๋๋ฌธ์ด๋ค. ์ฆ, ๋ธ๋ผ์ฐ์ (๋๋ Node.js) ํ๊ฒฝ์๋ ์๋ฐ์คํฌ๋ฆฝํธ ๋ฐํ์์ด ์กด์ฌํ๋ค.
+ ์ถ๊ฐ ๊ณต๋ถ
์๋ฐ์คํฌ๋ฆฝํธ ์์ง
~> ์๋ฐ์คํฌ๋ฆฝํธ ์ฝ๋๋ฅผ ํด์ํ๊ณ ์คํํ๋ ํ๋ก๊ทธ๋จ(์คํ๊ธฐ)
~> JS ๋ฌธ๋ฒ์ผ๋ก ์์ฑ๋ ์ฝ๋๋ฅผ ์ฝ๊ณ , ์ด๋ฅผ ๊ธฐ๊ณ๊ฐ ์ดํดํ ์ ์๋ ์ ์์ค ๋ช ๋ น์ด๋ก ๋ณํํด์ ์คํํด์ฃผ๋ ์ญํ
~> ์ฃผ์ ์ญํ
โข ํ์ฑ: JS ์ฝ๋๋ฅผ ๋ถ์ํด์ ๋ฌธ๋ฒ ํธ๋ฆฌ๋ก ๋ฐ๊ฟ
โข ์ปดํ์ผ: ๋ฌธ๋ฒ ํธ๋ฆฌ๋ฅผ ๋ฐํ์ผ๋ก ๋ฐ์ดํธ์ฝ๋ ํน์ ๋จธ์ ์ฝ๋ ์์ฑ
โข ์คํ: ์์ฑ๋ ์ฝ๋๋ก ์ค์ ๊ณ์ฐ ์ํ
์๋ฐ์คํฌ๋ฆฝํธ ๋ฐํ์
~> ์๋ฐ์คํฌ๋ฆฝํธ ์์ง์ด ์ค์ ๋ก ๋์ํ๋ ์คํ ํ๊ฒฝ ์ ์ฒด
~> ์ฆ, ์๋ฐ์คํฌ๋ฆฝํธ ์์ง + ๋น๋๊ธฐ ์ฒ๋ฆฌ + ์ธ๋ถ ๊ธฐ๋ฅ ์ง์ ๋๊ตฌ๋ค์ ๋ชจ๋ ํฌํจํ ํ๊ฒฝ
~> ํน์ง
โข JS ์ฝ๋ ์คํ ๋ฟ ์๋๋ผ ๋น๋๊ธฐ ์ฒ๋ฆฌ ์ ์ฒด๋ฅผ ๋ด๋น
โข ์ค์ ๋ก๋ ์์ง๋ณด๋ค ํจ์ฌ ๋ณต์กํ๊ณ ํ๋ถํ ๊ธฐ๋ฅ์ ์ ๊ณต
โข ๋ฐํ์์ด ์์ด์ผ JS๊ฐ ์ค์ํ์์ ์ธ ์ ์๋ ์ธ์ด๊ฐ ๋จ
๐ ์๋ฐ์คํฌ๋ฆฝํธ ๋ฐํ์ ๊ตฌ์ฑ ์์

โ ๊ตฌ์ฑ ์์
- Call Stack: ํ์ฌ ์คํ ์ค์ธ ์ฝ๋
- Web APIs: ๋ธ๋ผ์ฐ์ ์์ ์ ๊ณตํ๋ ๋น๋๊ธฐ ๊ธฐ๋ฅ (setTimeout, fetch ๋ฑ)
- Callback Queue: ๋์ค์ ์คํํ ์์ ๋ค์ ๋๊ธฐ
- Event Loop: Call Stack์ด ๋น์๋์ง ํ์ธํ๊ณ , Callbac Queue์์ Callback์ ๊บผ๋ด ์คํ
์ด๋ค์ด ํจ๊ป ๋์ํ๋ฉด์ ๋น๋๊ธฐ ์ฒ๋ฆฌ๋ฅผ ๊ฐ๋ฅํ๊ฒ ๋ง๋ ๋ค. ์ฆ, ์๋ฐ์คํฌ๋ฆฝํธ ์์ฒด๋ ์ฑ๊ธ ์ค๋ ๋์ง๋ง, ๋น๋๊ธฐ ์์ ์ ํจ์จ์ ์ผ๋ก ๋ถ๋ฆฌํด ์ฒ๋ฆฌํ ์ ์๋ ๊ตฌ์กฐ ๋๋ถ์ ์ค์ ๋ก๋ "๋์์ฑ์ฒ๋ผ" ๋ณด์ด๊ฒ ๋๋ ๊ฒ์ด๋ค.
โ ๋น๋๊ธฐ ์ฒ๋ฆฌ ํ๋ฆ
- ๋ธ๋ผ์ฐ์ ๋ Node.js ํ๊ฒฝ์์ ์ฌ์ฉ์๊ฐ setTimeout, fetch, ์ด๋ฒคํธ ๋ฆฌ์ค๋ ๋ฑ ๋น๋๊ธฐ ์์ ์ ์์ฒญ
- ํด๋น ์์ ์ ์๋ฐ์คํฌ๋ฆฝํธ ์์ง์ด ์ง์ ์ฒ๋ฆฌํ์ง ์๊ณ , Web API ์์ญ์ผ๋ก ์ ๋ฌ
- Web API๋ ์ด ์์ฒญ์ ๋ฐ์ ์ฒ๋ฆฌ (์ด ๊ณผ์ ์ ์๋ฐ์คํฌ๋ฆฝํธ์ ์คํ ํ๋ฆ๊ณผ๋ ๋ณ๋๋ก ์งํ)
- ๋น๋๊ธฐ ์์ ์ด ์๋ฃ๋๋ฉด, Web API๋ ํด๋น ์์ ์ ์ฐ๊ฒฐ๋ Callback์ Callback Queue ๊ณต๊ฐ์ ๋ฑ๋ก
- Event Loop๋ ๋ง์ฝ Call Stack์ด ๋น์ด ์๋ค๋ฉด, Callback Queue์ ๋๊ธฐ ์ค์ธ ์์ ์ Call Stack์ผ๋ก ์ด๋์์ผ ์คํ
- ์ด์ Callback์ด Call Stack์ ์ฌ๋ผ๊ฐ ์คํ (์์ ์ ๊ฒฐ๊ณผ๊ฐ ๋ฐ์๋๋ฉฐ, ์ฌ์ฉ์์๊ฒ ํ๋ฉด์ด ์ ๋ฐ์ดํธ๋๊ฑฐ๋ ์ฝ์์ ์ถ๋ ฅ๋๋ ๋ฑ์ ๋์)
๊ฒฐ๊ตญ ์ฌ๊ธฐ์ ์ค์ํ ์ ์, ์๋ฐ์คํฌ๋ฆฝํธ ์์ง์ ๊ทธ์ ์ฃผ์ด์ง ์ฝ๋๋ฅผ ์คํํ๋ ์ญํ ๋ง์ ์ํํ๋ค๋ ๊ฒ์ด๋ค. ์ด ์์ง์ ์ค์ค๋ก ์ด๋ค ์์ ์ ์ค์ผ์คํ๊ฑฐ๋, ๋๊ธฐ ์ค์ธ ์์ ์ ์์์ ์คํํ๋ ๊ธฐ๋ฅ์ ์๋ค. ์ฆ, ์๋ฐ์คํฌ๋ฆฝํธ ์์ง์ ๋จ์ํ "์์ฒญ์ด ๋ค์ด์์ ๋ ์คํํ๋(on demand) ๊ณ์ฐ๊ธฐ ๊ฐ์ ์กด์ฌ"์ผ ๋ฟ์ด๋ค.
๊ทธ๋ ๋ค๋ฉด ์ธ์ ์ด๋ค ์ฝ๋๋ฅผ ์คํํ ์ง ๊ฒฐ์ ํ๋ ๊ฑด ๋๊ฐ ๋งก์๊น? ๋ฐ๋ก ์๋ฐ์คํฌ๋ฆฝํธ๊ฐ ๋์ํ๋ ๋ฐํ์ ํ๊ฒฝ(์: ๋ธ๋ผ์ฐ์ , Node.js)์ด ๊ทธ ์ญํ ์ ํ๋ค. ์ด ๋ฐํ์์ setTimeout, fetch, event listener ๊ฐ์ ๋น๋๊ธฐ ์์
์ ๋ฐฑ๊ทธ๋ผ์ด๋์์ ์ฒ๋ฆฌํ๊ณ , ์ด๋ฒคํธ ๋ฃจํ(Event Loop) ๋ฅผ ํตํด ์ ์ ํ ํ์ด๋ฐ์ ์๋ฐ์คํฌ๋ฆฝํธ ์์ง์ ์์
์ ์ ๋ฌํ๋ค.
๊ฒฐ๊ณผ์ ์ผ๋ก, ์ฐ๋ฆฌ๊ฐ ๋ณด๋ ์๋ฐ์คํฌ๋ฆฝํธ์ "๋์์ฑ"์ ์๋ฐ์คํฌ๋ฆฝํธ ์์ง ํ๋๋ง์ผ๋ก๋ ์ค๋ช ํ ์ ์๊ณ , ๊ทธ ์์ง์ ๊ฐ์ธ๊ณ ์๋ ๋ฐํ์ ํ๊ฒฝ ์ ์ฒด ๊ตฌ์กฐ๋ฅผ ์ดํดํด์ผ๋ง ์ ํํ ์ค๋ช ํ ์ ์๋ค.
๐ Callback
Callback์ ์ด๋ค ์์ ์ด ๋๋ ๋ค์ ์คํ๋์ด์ผ ํ๋ ํจ์๋ค. ์๋ฐ์คํฌ๋ฆฝํธ์์๋ ํจ์๊ฐ ์ผ๊ธ ๊ฐ์ฒด์ด๊ธฐ ๋๋ฌธ์, ๋ค๋ฅธ ํจ์์ ์ธ์๋ก ์ ๋ฌ๋ ์ ์๊ณ , ์ด๋ฌํ ํน์ฑ์ ํ์ฉํด ํน์ ์ด๋ฒคํธ๋ ์กฐ๊ฑด์ด ๋ฐ์ํ์ ๋ ํธ์ถ๋๋๋ก ํธ๋ค๋ฌ๋ก ์ฌ์ฉ๋๋ค. ์๋ฐ์คํฌ๋ฆฝํธ๋ ์ฑ๊ธ ์ค๋ ๋๋ก ๋์ํ๋ฏ๋ก, ์ค๋ ๊ฑธ๋ฆฌ๋ ์์ (์: ์๋ฒ ์์ฒญ, ํ์ด๋จธ ๋ฑ)์ ๊ทธ๋๋ก ์คํํ๋ฉด ์ ์ฒด ํ๋ก๊ทธ๋จ์ด ๋ฉ์ถ๊ฒ ๋๋ค. ๊ทธ๋์ ์๋ฐ์คํฌ๋ฆฝํธ๋ ๋น๋๊ธฐ์ ์ผ๋ก ์ด๋ฐ ์์ ์ ๋ฐฑ๊ทธ๋ผ์ด๋์ ๋งก๊ธฐ๊ณ , ์๋ฃ๋ ๋ค ํธ์ถํ Callback ํจ์๋ฅผ ๋ฑ๋กํ๋ ๋ฐฉ์์ผ๋ก ํ๋ฆ์ ์ ์ดํ๋ค. ๋ํ์ ์ธ ์์๋ก๋ setTimeout, addEventListener, ๊ทธ๋ฆฌ๊ณ AJAX ์์ฒญ ์ ์ฌ์ฉ๋๋ ์ฝ๋ฐฑ์ด ์๋ค.
function getData(callback) {
setTimeout(() => {
callback("๋ฐ์ดํฐ ๋์ฐฉ!");
}, 1000);
}
getData((data) => {
console.log(data);
});
์ ์์ ์์ setTimeout์ ๋ฐฑ๊ทธ๋ผ์ด๋์์ 1์ด๋ฅผ ๊ธฐ๋ค๋ฆฌ๊ณ , ๊ทธ ์ดํ์ ์ฐ๋ฆฌ๊ฐ ๋๊ธด callback("๋ฐ์ดํฐ ๋์ฐฉ!")์ ์คํํ๋ค. ์ด๋ ๊ฒ ํ๋ฉด ํ๋ก๊ทธ๋จ์ ๋ฉ์ถ์ง ์๊ณ ๋ค์ ์ฝ๋๋ก ๋์ด๊ฐ๋ฉด์๋, ๋์ค์ ๋ฐ์ดํฐ๋ฅผ ๋ฐ์์์ ์ฒ๋ฆฌํ ์ ์๋ค.
๐ Callback ์ง์ฅ
Callback์ ๊ฐ๋จํ ์ํฉ์์๋ ์ ์ฉํ์ง๋ง, ๋ณต์กํ ๋น์ฆ๋์ค ๋ก์ง์๋ ํฐ ๋ฌธ์ ๋ฅผ ์ผ์ผํจ๋ค. ํนํ ๋น๋๊ธฐ ์์ ์ด ์ฐ์์ ์ผ๋ก ์ด์ด์ง ๋, Callback์ ์ค์ฒฉํด์ ์ฌ์ฉํด์ผ ํ๋ฏ๋ก ์ฝ๋๊ฐ ์ ์ ์ค๋ฅธ์ชฝ์ผ๋ก ๋ฐ๋ฆฌ๋ฉฐ ๊ตฌ์กฐ๊ฐ ๋ฌด๋์ง๊ฒ ๋๋ค.
// ์น ๋ก๊ทธ์ธ ํ
์คํธ์ ์ฝ๋ฐฑ ์ง์ฅ ์์
function testLoginProcess(callback) {
loadPage('/login', function(error) {
if (error) return callback(error);
enterUsername('tester', function(error) {
if (error) return callback(error);
enterPassword('pass123', function(error) {
if (error) return callback(error);
clickLoginButton(function(error, result) {
if (error) return callback(error);
verifyRedirect('/dashboard', function(error, isSuccess) {
if (error) return callback(error);
checkWelcomeMessage(function(error, message) {
if (error) return callback(error);
callback(null, {
success: isSuccess,
message: message
});
});
});
});
});
});
});
}
์ด๋ ๊ฒ Callback์ด Callback ์์ ๋ค์ด๊ฐ๋ ํํ๋ฅผ ํํ "Callback ์ง์ฅ"์ด๋ผ๊ณ ๋ถ๋ฅธ๋ค.
โ
๊ทธ ์ด์ ๋ ๋ค์๊ณผ ๊ฐ๋ค:
- ์ฝ๋ ๊ฐ๋ ์ฑ ์ ํ๋ก ์ธํ ์ ์ง๋ณด์ ์ด๋ ค์
- ์๋ฌ ์ฒ๋ฆฌ ๋ก์ง ์ค๋ณต ๋ฐ ๋๋ฝ ์ํ
- ๋๋ฒ๊น ๋ณต์ก์ฑ ์ฆ๊ฐ
- ์คํ ํ๋ฆ ํ์ ์ด๋ ค์
- ์ฝ๋ ์ฌ์ฌ์ฉ์ฑ ์ ํ
Callback ์ง์ฅ์ ์ด๊ธฐ์ ๋น๋๊ธฐ ์ฒ๋ฆฌ๋ฅผ ํ ์๋ฐ์ ์์๋ ์๋ฐ์คํฌ๋ฆฝํธ์ ํ๊ณ์๊ณ , ์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด ๋ฑ์ฅํ ๊ฒ์ด Promise์ด๋ค.
๐ Promise
Promise๋ ๋น๋๊ธฐ ์์ ์ ์ฒด๊ณ์ ์ด๊ณ ์ ์ธ์ ์ผ๋ก ๋ค๋ฃจ๊ธฐ ์ํ ๊ฐ์ฒด๋ค. ๋ฏธ๋์ ์ด๋ค ๊ฐ์ด ๋์ฐฉํ ๊ฒ์ด๋ผ๋ ์ฝ์์ ๋ํ๋ด๋ฉฐ, ๊ทธ ๊ฐ์ด ์ค๋ฉด .then()์ผ๋ก ์ฒ๋ฆฌํ๊ณ , ์ค์ง ์๊ฑฐ๋ ์คํจํ๋ฉด .catch()๋ก ์ฒ๋ฆฌํ ์ ์๋ค.
// Promise ์์ฑ
const loginPromise = new Promise((resolve, reject) => {
// ๋น๋๊ธฐ ์์
์ํ
authenticateUser('testuser', 'password')
.then(user => {
if (user) {
resolve(user); // ์ฑ๊ณต
} else {
reject(new Error('์ธ์ฆ ์คํจ')); // ์คํจ
}
})
.catch(error => reject(error));
});
// Promise ์ฌ์ฉ
loginPromise
.then(user => console.log('๋ก๊ทธ์ธ ์ฑ๊ณต:', user))
.catch(error => console.error('๋ก๊ทธ์ธ ์คํจ:', error));
// ํ
์คํธ์์์ Promise ์ฒด์ด๋
function testCheckout() {
return addToCart('product1')
.then(cart => {
expect(cart.items.length).toBe(1);
return proceedToCheckout(cart);
})
.then(checkout => {
expect(checkout.total).toBeGreaterThan(0);
return completePayment(checkout, 'credit-card');
})
.then(order => {
expect(order.status).toBe('confirmed');
return order;
})
.catch(error => {
console.error('ํ
์คํธ ์คํจ:', error);
throw error;
});
}
โ Promise๋ 3๊ฐ์ง ์ํ๋ฅผ ๊ฐ์ง๋ค:
- pending: ์ด๊ธฐ ์ํ, ์์ ์งํ ์ค
- fulfilled: ์์ ์ฑ๊ณต (resolve)
- rejected: ์์ ์คํจ (reject)
โ Promise ์ฃผ์ ๋ฉ์๋
- Promise.all(): ๋ชจ๋ Promise ์๋ฃ ๋๊ธฐ
- Promise.race(): ๊ฐ์ฅ ๋จผ์ ์๋ฃ๋๋ Promise ๋ฐํ
- Promise.allSettled(): ๋ชจ๋ Promise์ ๊ฒฐ๊ณผ(์ฑ๊ณต/์คํจ) ๋ฐํ
- Promise.any(): ์ฒซ ๋ฒ์งธ ์ฑ๊ณตํ Promise ๋ฐํ
โ ์ Promise๊ฐ ์ค์ํ๊ฐ?
- Callback Chain์ ๊น๋ํ๊ฒ ์ฐ๊ฒฐํ ์ ์๋ค
โ .then().then().then() ์ผ๋ก ๋จ๊ณ๋ณ ์ฒ๋ฆฌ ๊ฐ๋ฅ - ์๋ฌ๋ฅผ ํตํฉ์ ์ผ๋ก ์ฒ๋ฆฌํ ์ ์๋ค
โ .catch() ํ๋๋ก ์ ์ฒด ํ๋ฆ์ ์ค๋ฅ ์ก๊ธฐ ๊ฐ๋ฅ - ๋น์ฆ๋์ค ๋ก์ง์ ๋ ๋ช ํํ๊ฒ ํํํ ์ ์๋ค
ํ์ง๋ง .then().then() ๊ตฌ์กฐ๋ ๊ธธ์ด์ง๋ฉด ๊ฐ๋ ์ฑ์ด ๋ค์ ๋๋น ์ง ์ ์๊ณ , ๋๊ธฐ ์ฝ๋์ฒ๋ผ ์ฝํ์ง๋ ์๊ธฐ ๋๋ฌธ์, ์ด๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด ๋ฑ์ฅํ ๊ฒ์ด async/await์ด๋ค.
๐ async, await
async/await๋ Promise๋ฅผ ๋ ๋๊ธฐ์์ฒ๋ผ ๋ณด์ด๊ฒ ๋ง๋ค์ด์ฃผ๋ ๋ฌธ๋ฒ์ด๋ค. ๋์ ๋ณด์ด๋ ๊ตฌ์กฐ๋ ๋ง์น ์์์ ์๋๋ก ํ๋ฅด๋ ์ผ๋ฐ ์ฝ๋ ๊ฐ์ง๋ง, ๋ด๋ถ์ ์ผ๋ก๋ ์ฌ์ ํ ๋น๋๊ธฐ๋ก ์๋ํ๋ค.
async๋ ํจ์ ์์ ๋ถ์ฌ์ ๊ทธ ํจ์๊ฐ ํญ์ Promise๋ฅผ ๋ฐํํ๋๋ก ๋ง๋๋ ํค์๋๊ณ , await๋ Promise๊ฐ ์ฒ๋ฆฌ๋ ๋๊น์ง ๊ธฐ๋ค๋ฆฐ ๋ค, ๊ทธ ๊ฒฐ๊ณผ๊ฐ์ ๋ฐํํ๋ ํค์๋๋ค. await๋ ๋ฐ๋์ async ํจ์ ์์์๋ง ์ฌ์ฉํ ์ ์์ผ๋ฉฐ, ์ด๋ฅผ ํ์ฉํ๋ฉด ๋ณต์กํ .then() ์ฒด์ธ์ ํผํ๊ณ ์ฝ๋๋ฅผ ๋ ๊ฐ๊ฒฐํ๊ฒ ์์ฑํ ์ ์๋ค.
// async ํจ์ ์ ์ธ
async function fetchUserData(userId) {
// await ํค์๋๋ async ํจ์ ๋ด๋ถ์์๋ง ์ฌ์ฉ ๊ฐ๋ฅ
const response = await fetch(`/api/users/${userId}`);
if (!response.ok) {
throw new Error('์ฌ์ฉ์ ์ ๋ณด๋ฅผ ๊ฐ์ ธ์ค๋๋ฐ ์คํจํ์ต๋๋ค');
}
return await response.json();
}
// ํ์ดํ ํจ์์ ํจ๊ป ์ฌ์ฉ
const verifyUser = async (username) => {
const user = await getUserByName(username);
return user.isVerified;
};
โ async/await์ ์ฅ์ :
- ์ฝ๋๊ฐ ํจ์ฌ ๊ฐ๊ฒฐํ๊ณ ์ง๊ด์ ์ด๋ค
- ๋๊ธฐ ์ฝ๋์ฒ๋ผ ๋ณด์ด๊ธฐ ๋๋ฌธ์ ๋๋ฒ๊น ์ด ์ฌ์
- try-catch๋ก ์๋ฌ ํธ๋ค๋ง์ด ์ผ๊ด๋๊ณ ๋ช ํํจ
โ Promise์์ ๊ด๊ณ
- async ํจ์๋ ํญ์ Promise๋ฅผ ๋ฐํ
- await๋ Promise๊ฐ ์ฒ๋ฆฌ๋ ๋๊น์ง ํจ์ ์คํ์ ์ผ์ ์ค์ง
- ๋ด๋ถ์ ์ผ๋ก Promise ๊ธฐ๋ฐ์ผ๋ก ๋์ํ๋ ๋ฌธ๋ฒ์ ๊ฐ์ํ
- Promise ๋ฉ์๋(then/catch) ๋์ฒด ์ญํ
๐ฅ ์ฝ๋ ๊ฐ๋ ์ฑ ํฅ์ ์์
// Promise ์ฒด์ธ
function testUserFlow() {
return loginUser('testuser', 'password')
.then(token => {
return fetchUserProfile(token);
})
.then(profile => {
return updateUserPreferences(profile.id, { theme: 'dark' });
})
.then(result => {
expect(result.success).toBe(true);
});
}
// async/await ๋ฒ์
async function testUserFlow() {
const token = await loginUser('testuser', 'password');
const profile = await fetchUserProfile(token);
const result = await updateUserPreferences(profile.id, { theme: 'dark' });
expect(result.success).toBe(true);
}
๐ฅ try/catch๋ฅผ ์ด์ฉํ ์ค๋ฅ ์ฒ๋ฆฌ
// async/await + try-catch-finally ์์
async function secureLogin() {
try {
const user = await authenticateUser('test', 'pass');
const permissions = await fetchPermissions(user.id);
const isAdmin = await checkAdminRole(permissions);
return isAdmin; // ์ฑ๊ณต ์ ๊ฒฐ๊ณผ ๋ฐํ
} catch (error) {
console.error('๋ก๊ทธ์ธ ์ ์ฐจ ์คํจ:', error);
throw new Error('์ธ์ฆ ์ฒ๋ฆฌ ์ค ์ค๋ฅ๊ฐ ๋ฐ์ํ์ต๋๋ค'); // ์๋ฌ ๋ค์ ๋์ง๊ธฐ
} finally {
// ์ฑ๊ณต/์คํจ ๊ด๊ณ์์ด ๋ฐ๋์ ์คํ๋จ
await logAttempt('test', new Date());
}
}