๐Ÿ’ป์šฉ๋‡ฝ ๊ฐœ๋ฐœ ๋…ธํŠธ๐Ÿ’ป
article thumbnail
๋ฐ˜์‘ํ˜•

๐Ÿ“– ๋“ค์–ด๊ฐ€๋ฉฐ

์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์—์„œ ์ด๋ฒคํŠธ ๋ฃจํ”„(Event Loop)๋Š” ๋ฌด์—‡์ด๊ณ , ์™œ ์ค‘์š”ํ•œ ๊ฐœ๋…์ผ๊นŒ์š”?


์‹ฑ๊ธ€ ์Šค๋ ˆ๋“œ(Single Thread)๋ž€?

https://www.digikey.kr/en/maker/blogs/2022/an-introduction-to-multi-threading-c-programs

์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋Š” ์‹ฑ๊ธ€ ์Šค๋ ˆ๋“œ ๊ธฐ๋ฐ˜์˜ ์–ธ์–ด์ž…๋‹ˆ๋‹ค.

๊ทธ๋ ‡๋‹ค๋ฉด ์‹ฑ๊ธ€ ์Šค๋ ˆ๋“œ๋ž€ ๋ฌด์—‡์ผ๊นŒ์š”?

์‹ฑ๊ธ€ ์Šค๋ ˆ๋“œ๋ฅผ ์ดํ•ดํ•˜๊ธฐ ์ „์— ์Šค๋ ˆ๋“œ๋ผ๋Š” ๊ฐœ๋…์„ ๋จผ์ € ์•Œ์•„์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์Šค๋ ˆ๋“œ๋Š” ํ”„๋กœ์„ธ์Šค์˜ ์‹คํ–‰ ๋‹จ์œ„์ž…๋‹ˆ๋‹ค.

์ฆ‰, ์ผ์„ ์ฒ˜๋ฆฌํ•˜๋Š” ์ž‘์€ ์š”์›๊ณผ ๊ฐ™์€ ์—ญํ• ์„ ํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.

์‹ฑ๊ธ€ ์Šค๋ ˆ๋“œ๋ผ๋Š” ๊ฒƒ์€ ๋ง ๊ทธ๋Œ€๋กœ ์Šค๋ ˆ๋“œ๊ฐ€ ํ•˜๋‚˜๋งŒ ์กด์žฌ, ์ผ์„ ์ฒ˜๋ฆฌํ•˜๋Š” ์ž‘์€ ์š”์›์ด ํ•œ ๋ช… ๋ฐ–์— ์—†๋Š” ์–˜๊ธฐ์ž…๋‹ˆ๋‹ค.


๋ธ”๋กœํ‚น(Blocking)๊ณผ ๋…ผ๋ธ”๋กœํ‚น(Non-blocking)

์šฐ๋ฆฌ์˜ ์ž‘์€ ์š”์›์€ ํ•œ ๋ช…์ด๋ผ์„œ ๋ชจ๋“  ์ผ์„ ํ•œ ๋ฒˆ์— ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

๋งŒ์•ฝ ์šฐ๋ฆฌ๊ฐ€ ์ปดํ“จํ„ฐ์—๊ฒŒ ๋งก๊ธด ์ผ ์ค‘ ํ•˜๋‚˜๊ฐ€ ๋„ˆ๋ฌด ์˜ค๋ž˜ ๊ฑธ๋ฆฐ๋‹ค๋ฉด ์–ด๋–ป๊ฒŒ ๋ ๊นŒ์š”?
๊ทธ๋Ÿผ ๊ธด ์ž‘์—…์ด ์™„๋ฃŒ๋  ๋•Œ๊นŒ์ง€ ๋‹ค๋ฅธ ๋ชจ๋“  ์ž‘์—…๋“ค์ด ๋ฉˆ์ถฐ์žˆ๋‹ค๊ฐ€ ํ•ด๋‹น ์ž‘์—…์ด ๋๋‚œ ํ›„์— ๋‹ค์‹œ ์ง„ํ–‰์ด ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค.
์ด๋Ÿฌํ•œ ๊ฒฝ์šฐ๋ฅผ ๋ฐ”๋กœ ๋ธ”๋กœํ‚น์ด๋ผ๊ณ  ํ•ฉ๋‹ˆ๋‹ค.

ํ•˜์ง€๋งŒ ์šฐ๋ฆฌ๋Š” ์›น์—์„œ ํŒŒ์ผ๋„ ๋‹ค์šด๋กœ๋“œํ•˜๋ฉด์„œ ์›น ์„œํ•‘๋„ ํ•˜๊ณ  ๋™์˜์ƒ๋„ ๋ณด๊ณ  ์—ฌ๋Ÿฌ ๊ฐ€์ง€ ์ผ์„ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด๊ฑด ๋ฐ”๋กœ ๋…ผ๋ธ”๋กœํ‚น ๋ฐฉ์‹ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

๋…ผ๋ธ”๋กœํ‚น ๋ฐฉ์‹์—์„œ๋Š” ๊ธด ์ž‘์—…์ด ์ง„ํ–‰๋˜๋Š” ๋™์•ˆ์—๋„ ๋‹ค๋ฅธ ์ž‘์—…๋“ค์ด ๊ณ„์† ์ง„ํ–‰๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.


์ด๋ฒคํŠธ ๋ฃจํ”„(Event Loop)์˜ ์กด์žฌ

์—ฌ๊ธฐ์„œ ์ด๋ฒคํŠธ ๋ฃจํ”„์˜ ์—ญํ• ์ด ์ค‘์š”ํ•ด์ง‘๋‹ˆ๋‹ค.

๋…ผ๋ธ”๋กœํ‚น ๋ฐฉ์‹์—์„œ ํ•„์š”ํ•œ ๊ฒƒ์ฒ˜๋Ÿผ, ์ด๋ฒคํŠธ ๋ฃจํ”„๋Š” ๊ธด ์ž‘์—…์„ ํ•˜๊ณ  ์žˆ๋Š” ๋™์•ˆ ์งง์€ ์ž‘์—…๋“ค๋„ ๊ฐ™์ด ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ฆ‰, ์ด๋ฒคํŠธ ๋ฃจํ”„๋Š” ์šฐ๋ฆฌ์˜ ์ž‘์€ ์š”์›์—๊ฒŒ ์–ด๋–ค ์ž‘์—…๋ถ€ํ„ฐ ์‹œ์ž‘ํ•˜๊ณ  ์–ธ์ œ ๋‹ค์Œ ์ž‘์—…์œผ๋กœ ๋„˜์–ด๊ฐˆ์ง€ ์•Œ๋ ค์ฃผ๋Š” ์—ญํ• ์„ ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

๊ทธ๋ž˜์„œ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋Š” ์‹ฑ๊ธ€ ์Šค๋ ˆ๋“œ ์–ธ์–ด์ž„์—๋„ ๋ถˆ๊ตฌํ•˜๊ณ  ์ด๋ฒคํŠธ ๋ฃจํ”„๋ฅผ ํ†ตํ•ด ๋…ผ๋ธ”๋กœํ‚น ๋ฐฉ์‹์˜ ๋น„๋™๊ธฐ์ ์ธ ๋™์‹œ์„ฑ ์–ธ์–ด๋กœ ๋™์ž‘ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด๋ฒคํŠธ ๋ฃจํ”„(Event Loop)์˜ ๊ตฌ์กฐ

์ด๋ฒคํŠธ๋ฃจํ”„ ๊ตฌ์กฐ

์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ์—”์ง„์ด ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ๋ถ€๋ถ„์€ ๋ฉ”๋ชจ๋ฆฌ ํž™(Memory Heap)๊ณผ ์ฝœ ์Šคํƒ(Call Stack)์ด ์žˆ์Šต๋‹ˆ๋‹ค.

  • ๋ฉ”๋ชจ๋ฆฌ ํž™(Memory Heap): ๋ฉ”๋ชจ๋ฆฌ ํž™์€ ์ปดํ“จํ„ฐ๊ฐ€ ์ •๋ณด๋ฅผ ์ €์žฅํ•˜๋Š” ๊ณณ์ž…๋‹ˆ๋‹ค. ์ฆ‰, ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ๊ด€์ ์—์„œ ๋ณด๋ฉด ์šฐ๋ฆฌ๊ฐ€ ๋งŒ๋“œ๋Š” ๊ฐ์ฒด, ๋ฐฐ์—ด, ํ•จ์ˆ˜ ๋“ฑ์˜ ๋ฐ์ดํ„ฐ๊ฐ€ ์ €์žฅ๋˜๋Š” ๊ณต๊ฐ„์ž…๋‹ˆ๋‹ค.
  • ์ฝœ ์Šคํƒ(Call Stack): ์ฝœ ์Šคํƒ์€ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ๊ด€์ ์—์„œ ๋ดค์„ ๋•Œ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์˜ ํ•  ์ผ ๋ชฉ๋ก์ด๋ผ๊ณ  ์ƒ๊ฐํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค. ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜๊ฒŒ ๋˜๋ฉด ํ•ด๋‹น ํ•จ์ˆ˜์˜ ์ •๋ณด๊ฐ€ ์ฝœ ์Šคํƒ์— ์Œ“์ด๊ฒŒ ๋˜๊ณ , ๋จผ์ € ๋“ค์–ด๊ฐ„ ๊ฒƒ์ด ๋งˆ์ง€๋ง‰์— ๋‚˜์˜ค๋Š” FILO(First In Last Out) ๊ตฌ์กฐ์ž…๋‹ˆ๋‹ค.

์›น API(Web APIs)์™€ ์ฝœ๋ฐฑ ํ(Callback Queue)๋Š” ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ์—”์ง„ ์™ธ๋ถ€์—์„œ ๊ด€๋ฆฌ๋˜๋ฉฐ, ์ฃผ๋กœ ๋ธŒ๋ผ์šฐ์ €๋‚˜ Node.js์™€ ๊ฐ™์€ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ๋Ÿฐํƒ€์ž„ ํ™˜๊ฒฝ์—์„œ ์ œ๊ณต๋ฉ๋‹ˆ๋‹ค.

  • ์›น API(Web APIs) : ์›น API๋Š” ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ์ œ๊ณตํ•˜๋Š” ๋‹ค์–‘ํ•œ ๊ธฐ๋Šฅ๋“ค์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, HTTP ์š”์ฒญ, setTimeout ๋“ฑ์˜ ๊ธฐ๋Šฅ๋“ค์ด ํฌํ•จ๋ฉ๋‹ˆ๋‹ค. ์ด๋Ÿฐ ์ž‘์—…๋“ค์€ ์ฃผ๋กœ ๋น„๋™๊ธฐ์ ์œผ๋กœ ์ฒ˜๋ฆฌ๊ฐ€ ๋˜๋ฏ€๋กœ ์™„๋ฃŒ ์‹œ์ ์„ ์ •ํ™•ํžˆ ์•Œ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.
  • ์ฝœ๋ฐฑ ํ(Callback Queue): ์ฝœ๋ฐฑ ํ๋Š” ๋น„๋™๊ธฐ ์ž‘์—…(์˜ˆ: setTimeout, HTTP ์š”์ฒญ)์˜ ๊ฒฐ๊ณผ๋‚˜ ๋‚˜์ค‘์— ์‹คํ–‰๋˜์–ด์•ผ ํ•˜๋Š” ์ž‘์—…๋“ค์ด ๋Œ€๊ธฐํ•˜๋Š” ๊ณต๊ฐ„์ž…๋‹ˆ๋‹ค. ๋จผ์ € ๋“ค์–ด๊ฐ„ ์ž‘์—…์ด ๋จผ์ € ๋‚˜๊ฐ€๋Š” FIFO(First In First Out) ๊ตฌ์กฐ์ž…๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์— ์žˆ๋Š” ์ฝœ๋ฐฑ ํ•จ์ˆ˜๋“ค์€ ์ฝœ์Šคํƒ์ด ๋น„์–ด์กŒ์„ ๋•Œ ๋จผ์ € ๋Œ€๊ธฐ์—ด์— ๋“ค์–ด์˜จ ์ˆœ์„œ๋Œ€๋กœ ์ˆ˜ํ–‰๋ฉ๋‹ˆ๋‹ค.

ํ•˜์ง€๋งŒ ๋‹จ์ˆœํžˆ ๋น„๋™๊ธฐ ํ•จ์ˆ˜๊ฐ€ ์ฝœ๋ฐฑ ํ์— ์Œ“์ด๋Š” ๊ฒƒ์€ ์•„๋‹™๋‹ˆ๋‹ค.

์ฝœ๋ฐฑ ํ์—๋Š” ์„ธ ๊ฐ€์ง€ ์ข…๋ฅ˜๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

  1. ํƒœ์Šคํฌ ํ(Task Queue): ์ผ๋ฐ˜์ ์œผ๋กœ ๋งคํฌ๋กœ ํƒœ์Šคํฌ(Macrotask Queue)๋ผ๊ณ ๋„ ๋ถ€๋ฆ…๋‹ˆ๋‹ค. setTimeout, setInterval ๋“ฑ์˜ ๋น„๋™๊ธฐ ์ž‘์—…์ด ์ด๊ณณ์— ๋“ค์–ด๊ฐ€๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.
  2. ๋งˆ์ดํฌ๋กœํƒœ์Šคํฌ ํ(Microtask Queue): ํ”„๋กœ๋ฏธ์Šค(Promise)์˜ ์ฝœ๋ฐฑ ํ•จ์ˆ˜๋‚˜ async / await๊ณผ ๊ฐ™์€ ์ฝ”๋“œ๊ฐ€ ์ด๊ณณ์— ๋“ค์–ด๊ฐ‘๋‹ˆ๋‹ค.
  3. ์• ๋‹ˆ๋ฉ”์ด์…˜ ํ”„๋ ˆ์ž„(Animation Frames): ๋ธŒ๋ผ์šฐ์ € ํ™˜๊ฒฝ์—์„œ ํ™”๋ฉด์„ ์—…๋ฐ์ดํŠธํ•˜๋Š” ์ž‘์—…๋„ ๋น„๋™๊ธฐ์ ์œผ๋กœ ์ฒ˜๋ฆฌ๋ฉ๋‹ˆ๋‹ค. requestAnimationFrames๊ณผ ๊ฐ™์€ ์ฝ”๋“œ๊ฐ€ ์—ฌ๊ธฐ์— ํ•ด๋‹น๋ฉ๋‹ˆ๋‹ค.
๋งˆ์ดํฌ๋กœํƒœ์Šคํฌ ํ(Microtask Queue) > ์• ๋‹ˆ๋ฉ”์ด์…˜ ํ”„๋ ˆ์ž„(Animation Frames) > ํƒœ์Šคํฌ ํ(Task Queue) ์ˆœ์œผ๋กœ  Microtask Queue๊ฐ€ ๊ฐ€์žฅ ๋จผ์ € ์‹คํ–‰๋˜๊ณ  Task Queue๊ฐ€ ๊ฐ€์žฅ ๋Šฆ๊ฒŒ ์‹คํ–‰๋˜๋Š” ์šฐ์„ ์ˆœ์œ„๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

๊ทธ๋ ‡๋‹ค๋ฉด ๋‚˜์ค‘์— ์‹คํ–‰๋˜์–ด์•ผ ํ•˜๋Š” ์ž‘์—…๋“ค์ด ์–ด๋–ป๊ฒŒ ์‹ค์ œ๋กœ ์‹คํ–‰๋ ๊นŒ์š”?

๋ฐ”๋กœ ์ด๋ฒคํŠธ ๋ฃจํ”„(Event Loop)๊ฐ€ ๊ทธ ์—ญํ• ์„ ๋‹ด๋‹นํ•ฉ๋‹ˆ๋‹ค.

์ด๋ฒคํŠธ ๋ฃจํ”„๋Š” ์ฝœ ์Šคํƒ๊ณผ ์ฝœ๋ฐฑ ํ๋ฅผ ์ง€์†์ ์œผ๋กœ ํ™•์ธํ•˜๋ฉฐ, ์ฝœ ์Šคํƒ์ด ๋น„์–ด์žˆ์œผ๋ฉด ์ฝœ๋ฐฑ ํ์—์„œ ๊ฐ€์žฅ ์˜ค๋ž˜๋œ ์ž‘์—…(FIFO)์„ ๊บผ๋‚ด์„œ ์ฝœ ์Šคํƒ์œผ๋กœ ์˜ฎ๊น๋‹ˆ๋‹ค.

https://dev.to/lydiahallie/javascript-visualized-promises-async-await-5gke#syntax

// ์ด๋ฒคํŠธ ๋ฃจํ”„์˜ ๋™์ž‘์„ ๋‚˜ํƒ€๋‚ด๋Š” ๊ฐ€์ƒ์˜ ์ฝ”๋“œ
while(queue.waitForMessage()){ // ํ์— ๋ฉ”์‹œ์ง€๊ฐ€ ์žˆ์„ ๋•Œ๊นŒ์ง€ ๋Œ€๊ธฐ
  queue.processNextMessage(); // ๊ฐ€์žฅ ์˜ค๋ž˜๋œ ๋ฉ”์‹œ์ง€๋ฅผ ํ์—์„œ ๊บผ๋‚ด์„œ ํ˜ธ์ถœ ์Šคํƒ์œผ๋กœ ์˜ฎ๊น€
}

์œ„ ์ฝ”๋“œ๋Š” ์ด๋ฒคํŠธ ๋ฃจํ”„์˜ ๋™์ž‘์„ ๊ฐ„๋žตํ•˜๊ฒŒ ํ‘œํ˜„ํ•œ ์ฝ”๋“œ์ž…๋‹ˆ๋‹ค.


์ด๋ฒคํŠธ ๋ฃจํ”„(Event Loop)์˜ ๋™์ž‘ ๊ณผ์ •

๋จผ์ € ์ด๋ฒคํŠธ ๋ฃจํ”„์˜ ๋™์ž‘ ๋ฐฉ์‹์— ๋Œ€ํ•ด์„œ ์„ค๋ช…ํ•˜๊ณ  ์˜ˆ์ œ๋“ค๊ณผ ํ•จ๊ป˜ ์„ค๋ช…ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

์ด๋ฒคํŠธ ๋ฃจํ”„์˜ ๋™์ž‘ ๋ฐฉ์‹์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

  1. ์ฝœ ์Šคํƒ(Call Stack) ํ™•์ธ: ์ด๋ฒคํŠธ ๋ฃจํ”„๋Š” ๋จผ์ € ํ˜„์žฌ ์ฝœ ์Šคํƒ์ด ๋น„์–ด ์žˆ๋Š”์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค. ๋งŒ์•ฝ ์ฝœ ์Šคํƒ์— ์•„์ง ์ฒ˜๋ฆฌ๋˜์ง€ ์•Š์€ ํ•จ์ˆ˜๊ฐ€ ์žˆ๋‹ค๋ฉด, ํ•ด๋‹น ํ•จ์ˆ˜๊ฐ€ ์™„์ „ํžˆ ์‹คํ–‰๋  ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆฝ๋‹ˆ๋‹ค.
  2. ์ฝœ๋ฐฑ ํ(Callback Queue) ํ™•์ธ: ๋งŒ์•ฝ ์ฝœ ์Šคํƒ์ด ๋น„์–ด ์žˆ๋‹ค๋ฉด, ์ด์ œ ์ฝœ๋ฐฑ ํ๋ฅผ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค. ์ฝœ๋ฐฑ ํ์—๋Š” ์›น API ๋“ฑ์—์„œ ์ƒ์„ฑ๋œ ์ฝœ๋ฐฑ ํ•จ์ˆ˜๋“ค์ด ๋Œ€๊ธฐํ•ฉ๋‹ˆ๋‹ค.
  3. ํ•จ์ˆ˜ ์ด๋™: ์ฝœ๋ฐฑ ํ์—์„œ ๊ฐ€์žฅ ์˜ค๋ž˜๋œ ํ•จ์ˆ˜๋ฅผ ๊บผ๋‚ด์„œ ์ฝœ ์Šคํƒ์œผ๋กœ ์˜ฎ๊น๋‹ˆ๋‹ค.
  4. ํ•จ์ˆ˜ ์‹คํ–‰: ์ด์ œ ํ•ด๋‹น ํ•จ์ˆ˜๊ฐ€ ์ฝœ ์Šคํƒ์—์„œ ์‹คํ–‰๋˜๊ณ  ์‹คํ–‰์ด ๋๋‚˜๋ฉด ์ฝœ ์Šคํƒ์—์„œ ๋น ์ ธ๋‚˜๊ฐ€๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.
  5. ์œ„ ๊ณผ์ •๋“ค์„ ํ”„๋กœ๊ทธ๋žจ์ด ์ข…๋ฃŒ๋  ๋•Œ๊นŒ์ง€ ๋ฐ˜๋ณตํ•ฉ๋‹ˆ๋‹ค.

์ด๋ฒคํŠธ ๋ฃจํ”„์˜ ๋™์ž‘ ๊ณผ์ •์„ GIF๋กœ ์•„์ฃผ ์‰ฝ๊ฒŒ ์ดํ•ดํ•  ์ˆ˜ ์žˆ๋„๋ก ์ •๋ฆฌํ•ด ๋†“์€ ๋ถ„(Lydia Hallie)์ด ๊ณ„์…”์„œ ํ•ด๋‹น ์ด๋ฏธ์ง€๋ฅผ ์ฐธ๊ณ ํ•˜์—ฌ ์„ค๋ช…ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.


์ฒซ ๋ฒˆ์งธ ์ฝ”๋“œ ๋ถ„์„ (setTimeout๊ณผ ์ฝœ๋ฐฑ ํ)

๊ทธ๋Ÿผ ์ด์ œ ์˜ˆ์ œ ์ด๋ฏธ์ง€ ๋ฐ ๋น„๋™๊ธฐ ์ฝ”๋“œ์™€ ํ•จ๊ป˜ ํ™•์ธํ•ด๋ณผ๊นŒ์š”?

function greet() {
  return 'Hello!';
}

function respond() {
  return setTimeout(() => {
    return 'Hey!';
  }, 1000);
}

greet();
respond();

์œ„ ์ฝ”๋“œ์˜ ๋™์ž‘ ๊ณผ์ •์€ ์–ด๋–ป๊ฒŒ ๋ ๊นŒ์š”?


๋จผ์ € greet ํ•จ์ˆ˜๋ฅผ ๋งŒ๋‚˜์„œ ํ˜ธ์ถœํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

์ฝœ ์Šคํƒ์— ์‹คํ–‰ ์ค‘์ธ ํ•จ์ˆ˜๊ฐ€ ์—†๊ธฐ ๋•Œ๋ฌธ์— ์ฝœ ์Šคํƒ์— greet ํ•จ์ˆ˜๋ฅผ ๋„ฃ์–ด์ค๋‹ˆ๋‹ค.

๊ทธ๋ฆฌ๊ณ  ๋ฐ”๋กœ ์‹คํ–‰๋˜์–ด "Hello!"๋ฅผ ์ถœ๋ ฅํ•˜๊ณ  ์ฝœ ์Šคํƒ์—์„œ ์‚ฌ๋ผ์ง€๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

๋‹ค์Œ์œผ๋กœ respond ํ•จ์ˆ˜๋ฅผ ๋งŒ๋‚˜์„œ ํ˜ธ์ถœํ•ฉ๋‹ˆ๋‹ค.

respond ํ•จ์ˆ˜๋Š”  Web API๊ฐ€ ์ œ๊ณตํ•˜๋Š” setTimeout ํ•จ์ˆ˜๋ฅผ ๋ฐ˜ํ™˜ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋ฉ”์ธ ์Šค๋ ˆ๋“œ๋ฅผ ์ฐจ๋‹จํ•˜์ง€ ์•Š๊ณ  ์ž‘์—…์„ ์ง€์—ฐ์‹œํ‚ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์šฐ๋ฆฌ๊ฐ€ ์•ž์—์„œ ์ด๋ฒคํŠธ ๋ฃจํ”„์˜ ์ค‘์š”์„ฑ์— ๋Œ€ํ•ด์„œ ์•Œ์•„๋ดค๋“ฏ์ด ๋งŒ์•ฝ setTimeout๊ณผ ๊ฐ™์€ ํ•จ์ˆ˜๊ฐ€ ๋ฐ”๋กœ ์ฝœ ์Šคํƒ์— ๋“ค์–ด๊ฐ”๋‹ค๋ฉด, ๊ทธ ํ•จ์ˆ˜๊ฐ€ ์™„์ „ํžˆ ์‹คํ–‰๋  ๋•Œ๊นŒ์ง€ ์ฆ‰, ํƒ€์ด๋จธ๊ฐ€ ๋งŒ๋ฃŒ๋  ๋•Œ๊นŒ์ง€ ๋‹ค๋ฅธ ๋ชจ๋“  ์ž‘์—…๋“ค์€ ๋Œ€๊ธฐ ์ƒํƒœ(Blocking)์— ๋†“์ด๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ setTimeout๊ณผ ๊ฐ™์€ ๋น„๋™๊ธฐ ํ•จ์ˆ˜๋“ค์€ ํ˜ธ์ถœ๋˜๋ฉด ์›น API๋กœ ์ „๋‹ฌ๋ฉ๋‹ˆ๋‹ค.


setTimeout ํ•จ์ˆ˜์™€ respond ํ•จ์ˆ˜๋Š” ์ฝœ ์Šคํƒ์—์„œ ๋น ์ ธ๋‚˜์˜ค๋ฉด์„œ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•˜๊ฒŒ ๋˜๊ณ  setTimeout์— ์ „๋‹ฌํ•œ ์ฝœ๋ฐฑ ํ•จ์ˆ˜๋Š” ๋”ฐ๋กœ ๋น ์ ธ๋‚˜์™€ ์›น API๋กœ ์ด๋™ํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

๊ทธ๋ฆฌ๊ณ  ์›น API์—์„œ setTimeout ํ•จ์ˆ˜์˜ ๋‘ ๋ฒˆ์งธ ์ธ์ˆ˜์˜€๋˜ 1000ms(1์ดˆ)๋งŒํผ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค.


1000ms๋™์•ˆ ์‹คํ–‰์ด ๋๋‚œ ํ›„ ๋ฐ”๋กœ ์ฝœ ์Šคํƒ์œผ๋กœ ๋“ค์–ด๊ฐ€๋Š” ๊ฒƒ์ด ์•„๋‹Œ ์ฝœ๋ฐฑ ํ๋กœ ๋“ค์–ด๊ฐ€๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

์ž์„ธํ•˜๊ฒŒ๋Š” ํƒœ์Šคํฌ ํ(Task Queue)๋กœ ๋“ค์–ด๊ฐ„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.


์ด์ œ ์ด๋ฒคํŠธ ๋ฃจํ”„๊ฐ€ ์ฝœ ์Šคํƒ์ด ๋น„์–ด์žˆ๋Š”์ง€ ํ™•์ธ ํ›„, ์ฝœ๋ฐฑ ํ์— ์žˆ๋Š” ์ฝœ๋ฐฑ ํ•จ์ˆ˜๋ฅผ ์ฝœ ์Šคํƒ์— ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.


์ฝœ๋ฐฑ ํ•จ์ˆ˜๋Š” ์ฝœ ์Šคํƒ์— ์ถ”๊ฐ€๋˜๊ณ , ํ˜ธ์ถœ๋˜๊ณ , ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•œ ๋’ค์— ์ฝœ ์Šคํƒ์—์„œ ๋น ์ ธ๋‚˜๊ฐ€๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.


๋‘ ๋ฒˆ์งธ ์ฝ”๋“œ ๋ถ„์„ (setTimeout, Promise, Macrotask Queue, Microtask Queue)

console.log('Start!');

setTimeout(() => {
  console.log('Timeout!');
}, 0);

Promise.resolve('Promise!').then(res => console.log(res));

console.log('End!');

๊ทธ๋Ÿผ ์œ„์™€ ๊ฐ™์€ ์ฝ”๋“œ๋Š” ์‹คํ–‰์ด ์–ด๋–ป๊ฒŒ ๋ ๊นŒ์š”?

์•ž์—์„œ ์„ค๋ช…ํ–ˆ๋“ฏ์ด ๋น„๋™๊ธฐ ํ•จ์ˆ˜๋ผ๊ณ  ๋ชจ๋‘ ๊ฐ™์€ ์ฝœ๋ฐฑ ํ์— ์ถ”๊ฐ€๋˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๊ณ  ์šฐ์„ ์ˆœ์œ„๊ฐ€ ์žˆ๋‹ค๊ณ  ์„ค๋ช…ํ–ˆ์Šต๋‹ˆ๋‹ค.


๋จผ์ € console.log๋ฅผ ๋งŒ๋‚˜๊ฒŒ ๋˜๊ณ  ์ฝœ ์Šคํƒ์— ์ถ”๊ฐ€๋œ ํ›„ "Start!"๋ผ๋Š” ๊ฐ’์ด ์ถœ๋ ฅ๋œ ๋‹ค์Œ ์ฝœ ์Šคํƒ์—์„œ ๋น ์ ธ๋‚˜๊ฐ‘๋‹ˆ๋‹ค.


๋‹ค์Œ ์ค„์—์„œ ๋ฐ”๋กœ setTimeout ํ•จ์ˆ˜๋ฅผ ๋งŒ๋‚˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

setTimeout ๋‚ด๋ถ€์˜ ์ฝœ๋ฐฑ ํ•จ์ˆ˜๋Š” ์›น API๋กœ ๋„˜์–ด๊ฐ‘๋‹ˆ๋‹ค.

์ธ์ˆ˜๋กœ 0์„ ์ฃผ์—ˆ์ง€๋งŒ ๋น„๋™๊ธฐ ํ•จ์ˆ˜์˜ ์ฝœ๋ฐฑ ํ•จ์ˆ˜๋กœ ๋„˜๊ฒจ๋ฐ›์•˜๊ธฐ ๋•Œ๋ฌธ์— ๋งคํฌ๋กœํƒœ์Šคํฌ ํ(Macro Queue)์— ์ถ”๊ฐ€๋ฉ๋‹ˆ๋‹ค.


๋‹ค์Œ ์ค„์—์„œ ๋ฐ”๋กœ ํ”„๋กœ๋ฏธ์Šค(Promise)๋ฅผ ๋งŒ๋‚˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

Promise.resolve๊ฐ€ ์ฝœ ์Šคํƒ์— ์ถ”๊ฐ€๋œ ํ›„ ์ฝœ๋ฐฑ ํ•จ์ˆ˜๊ฐ€ ๋งˆ์ดํฌ๋กœํƒœ์Šคํฌ ํ(Microtask Queue)์— ์ถ”๊ฐ€๋ฉ๋‹ˆ๋‹ค.

Promise.resolve๋Š” ๋น ์ ธ๋‚˜์˜ค๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.


console.log๋ฅผ ๋งŒ๋‚œ ํ›„ ์ฝœ ์Šคํƒ์— ์ถ”๊ฐ€๋˜๊ณ  "End!"๋ฅผ ์ถœ๋ ฅํ•˜๊ณ  ์ฝœ ์Šคํƒ์—์„œ ๋น ์ ธ๋‚˜์˜ต๋‹ˆ๋‹ค.


์ด์ œ ์ฝœ ์Šคํƒ์ด ๋น„์–ด์žˆ๊ธฐ ๋•Œ๋ฌธ์— ๋งˆ์ดํฌ๋กœํƒœ์Šคํฌ ํ์— ๋Œ€๊ธฐ ์ค‘์ธ ์ž‘์—…์ด ์žˆ๋Š”์ง€ ํ™•์ธ ํ›„ ์ฝœ ์Šคํƒ์— ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.

๊ทธ๋ฆฌ๊ณ  Promise์˜ resolve ๊ฐ’์ธ console.log๋ฅผ ์ถœ๋ ฅํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

์ด์ œ ๋‹ค์‹œ ๋งˆ์ดํฌ๋กœํƒœ์Šคํฌ ํ์— ๋Œ€๊ธฐ ์ค‘์ธ ์ž‘์—…์ด ์žˆ๋Š”์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.

๋Œ€๊ธฐ ์ค‘์ธ ์ž‘์—…์ด ์—†์œผ๋‹ˆ ์ด์ œ ๋งคํฌ๋กœํƒœ์Šคํฌ ํ(Macrotask Queue)๋ฅผ ํ™•์ธํ•  ์ฐจ๋ก€์ž…๋‹ˆ๋‹ค.


๋งคํฌ๋กœํƒœ์Šคํฌ ํ์—์„œ ๋Œ€๊ธฐ ์ค‘์ด์—ˆ๋˜ setTimeout์˜ ์ฝœ๋ฐฑ ํ•จ์ˆ˜์ธ console.log("Timeout")์„ ์ฝœ ์Šคํƒ์— ์ถ”๊ฐ€ํ•œ ๋’ค ์ถœ๋ ฅํ•˜๊ณ  ์ฝœ ์Šคํƒ์—ฃ ๋น ์ ธ๋‚˜์˜ค๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.


์„ธ ๋ฒˆ์งธ ์ฝ”๋“œ ๋ถ„์„ (async / await)

ES8์— ์ ์šฉ๋œ async / await ๋ฌธ๋ฒ•์œผ๋กœ Promise๋ฅผ ์‰ฝ๊ฒŒ ๋‹ค๋ฃฐ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

asyncํ‚ค์›Œ๋“œ๋กœ Promise๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” await ๋น„๋™ํ‚ค ํ•จ์ˆ˜ ์ฝ”๋“œ ์˜ˆ์ œ๋ฅผ ๋งˆ์ง€๋ง‰์œผ๋กœ ์‚ดํŽด๋ณด๊ณ  ๋งˆ๋ฌด๋ฆฌํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

const one = () => Promise.resolve('One!');

async function myFunc() {
  console.log('In function!');
  const res = await one();
  console.log(res);
}

console.log('Before function!');
myFunc();
console.log('After function!');

์œ„ ์ฝ”๋“œ์˜ ์‹คํ–‰ ๊ฒฐ๊ณผ์™€ ๊ณผ์ •์€ ์–ด๋–ป๊ฒŒ ๋ ๊นŒ์š”?


๋จผ์ € console.log๊ฐ€ ์ฝœ ์Šคํƒ์— ์ถ”๊ฐ€๋œ ํ›„ "Before function!"์ด ์ถœ๋ ฅ๋ฉ๋‹ˆ๋‹ค.


๋‹ค์Œ์œผ๋กœ myFunc ํ•จ์ˆ˜๊ฐ€ ํ˜ธ์ถœ๋˜์–ด ์ฝœ ์Šคํƒ์— ์ถ”๊ฐ€๋ฉ๋‹ˆ๋‹ค.

๊ทธ๋ฆฌ๊ณ  myFunc์˜ ์ฒซ ๋ฒˆ์งธ ์ค„์—์„œ console.log๊ฐ€ ์ฝœ ์Šคํƒ์— ์ถ”๊ฐ€๋œ ํ›„ "In function!"์„ ์ถœ๋ ฅํ•œ ํ›„ ์ฝœ ์Šคํƒ์—์„œ ๋น ์ ธ๋‚˜์˜ต๋‹ˆ๋‹ค.


๋‹ค์Œ์œผ๋กœ one ํ•จ์ˆ˜๋Š” Promise๋ฅผ ๋ฆฌํ„ดํ•˜๊ธฐ ์ด์ „์˜ ํ•จ์ˆ˜์ž…๋‹ˆ๋‹ค.

๊ทธ๋ž˜์„œ one ํ•จ์ˆ˜๋ฅผ ์ฝœ ์Šคํƒ์— ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.

one ํ•จ์ˆ˜๋Š” ์„ฑ๊ณต๋œ Promise (resolve)๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

๊ฒฐ๊ตญ one ํ•จ์ˆ˜๋Š” ์‹คํ–‰์ด ์™„๋ฃŒ๋˜์—ˆ๊ธฐ ๋•Œ๋ฌธ์— ์ฝœ ์Šคํƒ์—์„œ ๋น ์ ธ๋‚˜๊ฐ€๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

ํ•˜์ง€๋งŒ one ํ•จ์ˆ˜ ์•ž์— await ํ‚ค์›Œ๋“œ๊ฐ€ ๋ถ™์–ด์žˆ๊ธฐ ๋•Œ๋ฌธ์— ํ•ด๋‹น ํ•จ์ˆ˜(myFunc)๋Š” ์ผ์‹œ ์ •์ง€ ๋˜๊ณ  ๋งˆ์ดํฌ๋กœํƒœ์Šคํฌ ํ๋กœ ์ด๋™ํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.


await ํ‚ค์›Œ๋“œ๋ฅผ ๋งŒ๋‚˜๋ฉด ๋น„๋™๊ธฐ ํ•จ์ˆ˜๊ฐ€ ์ผ์‹œ ์ค‘์ง€ ๋˜๋ฏ€๋กœ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ์—”์ง„์€ ๋น„๋™๊ธฐ ํ•จ์ˆ˜(myFunc)์—์„œ ๋น ์ ธ๋‚˜์˜จ ํ›„,

๋น„๋™๊ธฐ ํ•จ์ˆ˜๊ฐ€ ํ˜ธ์ถœ ์‹คํ–‰ ์ปจํ…์Šค(ํ˜„์žฌ ์ฝ”๋“œ๋Š” myFunc์„ ํ˜ธ์ถœํ•œ ๊ณณ์€ ์ „์—ญ ์‹คํ–‰ ์ปจํ…์ŠคํŠธ)์—์„œ ๊ณ„์† ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.


๋งˆ์ง€๋ง‰์œผ๋กœ ์ „์—ญ ์ปจํ…์ŠคํŠธ์—์„œ ์‹คํ–‰ํ•  ์ฝ”๋“œ๊ฐ€ ์—†๊ธฐ ๋•Œ๋ฌธ์— ์ด๋ฒคํŠธ ๋ฃจํ”„๊ฐ€ ๋งˆ์ดํฌ๋กœํƒœ์Šคํฌ ํ์— ๋Œ€๊ธฐํ•˜๋Š” ์ž‘์—…์ด ์žˆ๋Š”์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.

ํ™•์ธ ๊ฒฐ๊ณผ, myFunc์ด ์กด์žฌํ•˜๊ธฐ ๋•Œ๋ฌธ์— one ํ•จ์ˆ˜๊ฐ€ ํ˜ธ์ถœ๋˜๊ณ  ์ฝœ ์Šคํƒ์—์„œ ๋น ์ ธ๋‚˜๊ฐ€๊ณ  ์ค‘๋‹จ๋˜์—ˆ๋˜ ์œ„์น˜์— ๋‹ค์‹œ ์‹คํ–‰๋˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

๊ทธ๋ž˜์„œ ๋งˆ์ง€๋ง‰์œผ๋กœ console.log๋ฅผ ์ฝœ ์Šคํƒ์— ์ถ”๊ฐ€ํ•œ ํ›„ ๋ฐ˜ํ™˜ ๋œ res์˜ ๊ฐ’์„ ์ถœ๋ ฅํ•˜๊ณ  ์ฝœ ์Šคํƒ์—์„œ ๋น ์ ธ๋‚˜์˜ค๊ฒŒ ๋˜๋ฉด์„œ ๋งˆ๋ฌด๋ฆฌ๊ฐ€ ๋ฉ๋‹ˆ๋‹ค.

 

aysnc / await์™€ Promise๋Š” ๋ชจ๋‘ ๋น„๋™๊ธฐ ์ž‘์—…์„ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐฉ๋ฒ•์ด์ง€๋งŒ ๋™์ž‘ ๋ฐฉ์‹์˜ ์ฐจ์ด์ ์ด ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.

  • Promise: Promise ๊ฐ์ฒด๊ฐ€ resolve ๋˜๋Š” reject ๋˜๋ฉด .thene() ๋˜๋Š” .catch() ๋‚ด๋ถ€์˜ ์ฝœ๋ฐฑ ํ•จ์ˆ˜๊ฐ€ ๋งˆ์ดํฌ๋กœํƒœ์Šคํฌ ํ์— ์ถ”๊ฐ€๋ฉ๋‹ˆ๋‹ค.
  • async / await: asyncํ•จ์ˆ˜ ๋‚ด์—์„œ await ํ‚ค์›Œ๋“œ๋ฅผ ๋งŒ๋‚˜๋ฉด, ํ•ด๋‹น ํ•จ์ˆ˜์˜ ์‹คํ–‰์ด ์ผ์‹œ ์ค‘๋‹จ๋ฉ๋‹ˆ๋‹ค. ์ด๋•Œ ๋ฐ˜ํ™˜๋œ ๊ฐ’์€ Promise ๊ฐ์ฒด์ž…๋‹ˆ๋‹ค. await ํ‚ค์›Œ๋“œ ๋’ค์˜ Promise๊ฐ€ resolve ๋˜๋ฉด, ๊ทธ ๊ฒฐ๊ณผ ๊ฐ’์€ await ํ‘œํ˜„์‹ ์ž์ฒด๋ฅผ ๋Œ€์ฒดํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋‚˜์„œ ํ•จ์ˆ˜์˜ ๋‚˜๋จธ์ง€ ๋ถ€๋ถ„์ด ๋งˆ์ดํฌ๋กœํƒœ์Šคํฌ ํ์— ์ถ”๊ฐ€๋˜์–ด ํ›„์† ์ฒ˜๋ฆฌ๋ฉ๋‹ˆ๋‹ค.

๐Ÿ“• ๋งˆ์น˜๋ฉฐ

์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์˜ ํ•ต์‹ฌ ๊ฐœ๋… ์ค‘ ํ•˜๋‚˜์ธ ์ด๋ฒคํŠธ ๋ฃจํ”„์— ๋Œ€ํ•ด์„œ ์•Œ์•„๋ณด์•˜์Šต๋‹ˆ๋‹ค.

์ฒ˜์Œ์—๋Š” ๋ณต์žกํ•˜๊ฒŒ ๋Š๊ปด์ง€๋Š” ๊ฑด ์‚ฌ์‹ค์ด์ง€๋งŒ, ์—ฌ๋Ÿฌ ๋ฒˆ ๋ณด๊ณ  ์ด๋ฒคํŠธ ๋ฃจํ”„์™€ ๊ฐ ํ์˜ ๋™์ž‘ ๋ฐฉ์‹์„ ์ตํ˜€๋‘๋ฉด ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ์ฝ”๋“œ์˜ ๋™์ž‘ ์›๋ฆฌ๋ฅผ ๊นŠ๊ฒŒ ์ดํ•ดํ•˜๊ณ  ์„ฑ๋Šฅ ์ตœ์ ํ™”์™€ ๋””๋ฒ„๊น…์—์„œ ํฐ ๋„์›€์„ ์–ป์„ ์ˆ˜ ์žˆ๋‹ค๋Š” ์ ๋„ ์•Œ๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

 

์ฐธ๊ณ  ๋ฌธํ—Œ:

๋ฐ˜์‘ํ˜•
profile

๐Ÿ’ป์šฉ๋‡ฝ ๊ฐœ๋ฐœ ๋…ธํŠธ๐Ÿ’ป

@์šฉ๋‡ฝ

ํฌ์ŠคํŒ…์ด ์ข‹์•˜๋‹ค๋ฉด "์ข‹์•„์š”โค๏ธ" ๋˜๋Š” "๊ตฌ๋…๐Ÿ‘๐Ÿป" ํ•ด์ฃผ์„ธ์š”!