[JS] ๐Ÿš€๋ณ‘๋ ฌ๋กœ ๋น„๋™๊ธฐ ๋ฐ์ดํ„ฐ ํ•œ ๋ฒˆ์— ๋ฐ›์•„์˜ค๊ธฐ

article_thumbnail

์ธ๋„ค์ผ ๋ฉ”์ด์ปค(๋งํฌ) ์ž˜ ๋งŒ๋“ค์—ˆ์œผ๋‹ˆ ๋‹ค๋“ค ๊ฐ€์„œ ํ™•์ธํ•ด๋ณด์„ธ์š”!

0. ์•”ํŠผ ๊ธฐ๋‹ค๋ ค์ค˜!

์ตœ๊ทผ์— ๊ทธ๋Ÿฐ ์งˆ๋ฌธ์„ ๋ดค์—ˆ๋‹ค.

setTimeout์„ ์ด์šฉํ•ด ๋น„๋™๊ธฐ์ฒ˜๋Ÿผ ํ™˜๊ฒฝ์„ ๊ตฌ์„ฑํ•ด์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ›์•„์™€ ์ฒ˜๋ฆฌํ•˜๋Š” ์ฝ”๋“œ์ธ๋ฐ ์ด๊ฒŒ ์™œ ์•ˆ ๋Œ์•„๊ฐ€๋ƒ๊ณ .

์ฝ”๋“œ๋Š” ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์—†๊ณ , ๋Œ€์ถฉ ์›ํ•˜๋Š” ๊ฒฐ๊ณผ๋Š” ์ด๋Ÿฌํ–ˆ๋‹ค.

1
2
3
Done!

์œ„์ฒ˜๋Ÿผ ๋‚˜์˜ค๊ฒŒ ํ•˜๊ณ  ์‹ถ์€๋ฐ

Done!
1
2
3

๊ฒฐ๊ณผ๋Š” ์ด๋žฌ๋‹ค๋Š” ๊ฒƒ์ด๋‹ค.

๋น„๋™๊ธฐ๋ฅผ ๋ชจ๋ฅด๋Š” ๊ฐœ๋ฐœ์ž๋‚˜, Promise์— ๋Œ€ํ•ด ๊นŠ์ด ์ƒ๊ฐํ•ด๋ณด์ง€ ์•Š์€ ๊ฐœ๋ฐœ์ž์˜€๋‹ค๋ฉด ์–ด๋ผ ์ด๊ฑฐ ์™œ ์ด๋Ÿฌ์ง€?? ๋ผ๊ณ  ์ƒ๊ฐํ–ˆ์„ ๊ฒƒ์ด๋‹ค.

๊ทธ๋Ÿฌ๋‚˜ ๋‚˜๋Š” ์ฝ”๋“œ๋ฅผ ๋ณด์ž๋งˆ์ž ๋ฌธ์ œ์ ์„ ๋– ์˜ฌ๋ ธ๋‹ค.

์ด๊ฑฐ Promise ๊ฐ€ ์—†๋„ค

๊ทธ๋žฌ๋‹ค. Promise ์—†์ด ๊ทธ์ € setTimeout๊ณผ async/await๋ฅผ ํ˜ผํ•ฉํ•ด ๋†“๊ณ ์„  setTimeout์„ await๋ฅผ ํ†ตํ•ด ๊ธฐ๋‹ค๋ฆฌ๋ผ๊ณ  ํ–ˆ๋˜ ๊ฒƒ์ด๋‹ค.

์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ์ตœ์‹  ๋ฌธ๋ฒ•๋งŒ์„ ๋ฐฐ์šฐ๋Š” ๋‰ด๋น„๋“ค์—๊ฒŒ์„œ ์ž์ฃผ ๋‚˜ํƒ€๋‚˜๋Š” ๋ฌธ์ œ์ด๋‹ค. async/await๋ฅผ ๋งน์‹ ํ•œ ๋‚˜๋จธ์ง€ Promise๋ฅผ ๊ตฌ์‹œ๋Œ€์˜ ์œ ๋ฌผ๋กœ ์ทจ๊ธ‰ํ•˜์—ฌ ์“ฐ์ง€ ์•Š์œผ๋ ค๋Š” ๋ฌธ์ œ.

๋ฌผ๋ก  ์ตœ์‹  ๋ฌธ๋ฒ•์ด ํŽธํ•œ ๊ฑด ๋งž์ง€๋งŒ, async/await๋Š” ๊ธธ์–ด์ง€๋Š” ์ฝœ๋ฐฑ ์ง€์˜ฅ, ๋ฉ”์„œ๋“œ ์ฒด์ด๋‹์„ ํ”ผํ•˜๊ธฐ ์œ„ํ•œ ๋ฐฉ๋ฒ•์ด์ง€, Promise๋ฅผ ์ € ๋ฐ‘๋ฐ”๋‹ฅ์œผ๋กœ ๋ณด๋‚ด๋ฒ„๋ฆฌ๋Š” ๋ฐฉ๋ฒ•์ด ์ ˆ๋Œ€ ์•„๋‹ˆ๋‹ค!

์ด์ œ๋ถ€ํ„ฐ Promise์™€ async/await ๋ฅผ ์‚ฌ์šฉํ•ด ๋น„๋™๊ธฐ ์ตœ์ ํ™”๋ฅผ ํ•ด๋ณด์ž!

1. Promise๋Š” ์•„์ง ํ•„์š”ํ•˜๊ณ , await๋Š” ๋งŒ๋Šฅ์ด ์•„๋‹ˆ๋‹ค.

Promise์—๋Š” ์—ฌ๋Ÿฌ ๋ฉ”์„œ๋“œ๋“ค์ด ์žˆ๋‹ค. ์—ฌ๋Ÿฌ ๋น„๋™๊ธฐ ์ค‘ ๊ฐ€์žฅ ๋นจ๋ฆฌ ๊ฐ€์ ธ์˜ค๋Š” ๊ฒƒ๋งŒ ๋ฐ˜ํ™˜ํ•œ๋‹ค๋“ ์ง€, ์—ฌ๋Ÿฌ ๊ฐœ์˜ ๋น„๋™๊ธฐ๋ฅผ ๋ณ‘๋ ฌ๋กœ ํ•œ ๋ฒˆ์— ๊ฐ€์ ธ์˜จ๋‹ค๋“ ์ง€ ํ•˜๋Š” ๋“ฑ๋“ฑโ€ฆ

๊ทธ๋ฆฌ๊ณ  ์šฐ๋ฆฌ๋Š” ํ›„์ž๋ฅผ ์‚ดํŽด๋ณผ ๊ฒƒ์ด๋‹ค.

Promise

MDN Promise ๋ฌธ์„œ

์‚ฌ์‹ค ๋ฌธ์„œ๋ฅผ ์ฝ๋Š” ๊ฒŒ ์ •๋ง ์ •๋ง ์ข‹์€ ์„ ํƒ์ด์ง€๋งŒ, TL;DR๋ฅผ ์œ„ํ•ด ๊ฐ„๋‹จํžˆ ์š”์•ฝํ•˜์ž๋ฉด,

return new Promise((resolve, reject) => {
  //์„ฑ๊ณตํ•˜๋ฉด
  resolve('๋ฐ˜ํ™˜ ๊ฐ’')

  //์‹คํŒจํ•˜๋ฉด
  reject('๋ฐ˜ํ™˜ ๊ฐ’')
})

์ด๋ ‡๊ฒŒ Promise ๊ตฌ์กฐ๋ฅผ ์ตํ˜€๋‘๋ฉด ๋œ๋‹ค. ์ฃผ๋กœ setTimeout์„ ์•ˆ์—์„œ ์‚ฌ์šฉํ•ด ์‹œ๊ฐ„์ด ์ง€๋‚˜๋ฉด resolveํ•˜๊ฒŒ ํ•˜๋Š” ์‹์œผ๋กœ ํ…Œ์ŠคํŠธ๋ฅผ ํ•˜๊ณค ํ•œ๋‹ค.

async / await

์—ญ์‹œ๋‚˜ TL;DR๋ฅผ ์œ„ํ•ด์„œ ๊ฐ„๋‹จํžˆ ํ•˜๊ณ  ์‹ถ์€ ๋ง๋งŒ ํ•˜์ž๋ฉด,

await๋Š” ๋ญ๋“  ์—ฐ์‚ฐ์ด ๋๋‚  ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ ค์ฃผ๋Š” ๋งŒ๋Šฅ ์ฝ”๋“œ๊ฐ€ ์•„๋‹ˆ๋‹ค!

await๋Š” Promise์˜ pending ์ƒํƒœ๊ฐ€ ๋๋‚  ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ ค์ฃผ๋Š” ๊ฒƒ์ด์ง€, setTimeout์˜ ์ผ์ • ์‹œ๊ฐ„ ์ดํ›„์— ์‹คํ–‰ ์ปจํ…์ŠคํŠธ์— ์ถ”๊ฐ€๋˜๊ณ  ์‹คํ–‰๋˜๋Š” ๊ฒƒ์„ ๊ธฐ๋‹ค๋ ค์ฃผ๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋‹ค.

์ด ๋ถ€๋ถ„์€ ๋”ฐ๋กœ ์‹คํ–‰ ์ปจํ…์ŠคํŠธ๋ฅผ ๊ณต๋ถ€ํ•˜๋ฉด ์ดํ•ดํ•˜๊ฒŒ ๋  ๊ฒƒ์ด๋‹ค.

2. ๋ณ‘๋ ฌ๋กœ ๋น„๋™๊ธฐ ๋ฐ์ดํ„ฐ๋ฅผ ํ•œ ๋ฒˆ์— ๋ฐ›์•„์˜จ๋‹ค๊ณ ?

์›๋ž˜ ์ดํ•ดํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ๋‹จ๊ณ„๊ฐ€ ํ•„์š”ํ•˜๋‹ค.

  1. setTimeout์œผ๋กœ ๋น„๋™๊ธฐ์ฒ˜๋Ÿผ ๊พธ๋ฏธ๊ธฐ
  2. ๋ฐฐ์—ด์„ ๋น„๋™๊ธฐ๋กœ ๊ฐ€์ ธ์˜ค๊ธฐ
  3. ๋ฐฐ์—ด์˜ ์•„์ดํ…œ์„ ๊ฐ๊ฐ ์ˆœ์„œ๋Œ€๋กœ ๋น„๋™๊ธฐ๋กœ ๊ฐ€์ ธ์™€๋ณด๊ธฐ
  4. ์–ด๋ผ ์•ˆ ๋˜๋„ค?
  5. await๋ฅผ ์‚ฌ์šฉํ•ด์„œ ๋‹ค์‹œ ๊ฐ๊ฐ ์ˆœ์„œ๋Œ€๋กœ ๋น„๋™๊ธฐ๋กœ ๊ฐ€์ ธ์™€๋ณด๊ธฐ
  6. ์–ด๋ผ ๋ฐฐ์—ด ๋ฉ”์„œ๋“œ๋“ค์ด ์•ˆ ๋จนํžˆ๋„ค?
  7. ๊ธฐ๋ณธ for ๋ฌธ์„ ์‚ฌ์šฉํ•˜๋ฉด ๋˜๋Š”๊ตฌ๋‚˜!
  8. ์ˆœ์ฐจ์ ์œผ๋กœ ๋ถˆ๋Ÿฌ์˜ค๋Š” ๊ฑด ๊ฐ€๋Šฅํ•œ๋ฐ, ์ด๋Ÿฌ๋ฉด ์‹œ๊ฐ„์ด ์˜ค๋ž˜ ๊ฑธ๋ ค
  9. ๋‹ค๋ฅธ ๋ฐฉ๋ฒ•์ด ์—†์„๊นŒ?

์ด๋Ÿฌํ•œ ์ค‘๊ฐ„ ๊ณผ์ • ๋‹ค ์ƒ๋žตํ•˜๊ณ , ์šฐ๋ฆฌ๊ฐ€ ์›ํ•˜๋Š” ๊ฒฐ๊ณผ๋ฅผ ๋น ๋ฅด๊ฒŒ ๋ณด์ž.

๋ฐฐ์—ด์˜ ์•„์ดํ…œ์„ Promise.all()์„ ์‚ฌ์šฉํ•ด ๋ณ‘๋ ฌ๋กœ ํ•œ ๋ฒˆ์— ๊ฐ€์ ธ์˜ค๊ธฐ

๋ฐฑ๋ฌธ์ด ๋ถˆ์—ฌ์ผ๊ฒฌ์ด๋ผ๊ณ , ์ฝ”๋“œ๋ฅผ ๋ณด๋ฉด ์ดํ•ด๊ฐ€ ์‰ฝ๋‹ค.

const getPromiseCrewList = () => {
  // ํฌ๋ฃจ ๋ฆฌ์ŠคํŠธ๋ฅผ ๋น„๋™๊ธฐ๋กœ ๋ฐ˜ํ™˜ํ•˜๋Š” ํ•จ์ˆ˜
  return new Promise(resolve => {
    // Promise๋ฅผ ๋ฐ˜ํ™˜ํ•ด์ค˜์•ผ await ์‚ฌ์šฉ๊ฐ€๋Šฅ
    setTimeout(() => {
      const crewList = ['Spike', 'Ain', 'Jet', 'Faye', 'Edward']
      resolve(crewList) // crewList๋ฅผ ๋ฐ˜ํ™˜ํ•ด์ค€๋‹ค.
    }, 2000)
  })
}

const processParallelPromise = name => {
  // ๊ฐ๊ฐ์˜ ์ด๋ฆ„๋“ค์— ๋Œ€ํ•ด ๋น„๋™๊ธฐ๋กœ ๋™์ž‘ํ•˜๋Š” ํ•จ์ˆ˜
  return new Promise(resolve => {
    setTimeout(() => {
      name.length > 3 ? resolve(true) : resolve(false)
    }, 1000)
  })
}

const startParallelPromise = async () => {
  // ๋น„๋™๊ธฐ๋กœ ๊ฐ€์ ธ์˜จ ๋ฐฐ์—ด์˜ ์•„์ดํ…œ์„ ๊ฐ๊ฐ ๋น„๋™๊ธฐ ํ•จ์ˆ˜์— ๋„˜๊ฒจ์ฃผ๋Š” ํ•จ์ˆ˜
  console.time('Parallel')
  const crew = await getPromiseCrewList()
  // ["Spike", "Ain", "Jet", "Faye", "Edward"], 3์ดˆ ๋’ค์— ๋ฐฐ์—ด์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค.
  const mappingPromiseArray = crew.map(c => processParallelPromise(c))
  // [Promise, Promise, Promise, Promise, Promise], ์ด์ฒ˜๋Ÿผ Promise์˜ ๋ฐฐ์—ด๋กœ ๋งŒ๋“ค์–ด์ค€๋‹ค.
  const makeParallelPromiseArray = Promise.all(mappingPromiseArray)
  // Promise {<pending>}, Promise์˜ ๋ฐฐ์—ด์ด๊ธฐ์— Promise.all์—๊ฒŒ ๋„˜๊ฒจ์ฃผ๋Š” ๊ฒŒ ๊ฐ€๋Šฅํ•ด์ง„๋‹ค.
  const isOverThree = await makeParallelPromiseArray
  // Promise.all() ๋•๋ถ„์— ๋ณ‘๋ ฌ๋กœ ๋ถˆ๋Ÿฌ์˜ค๊ฒŒ ๋œ๋‹ค.

  console.log(isOverThree) // [true, false, false, true, true]
  console.timeEnd('Parallel') // about 3002ms
}

startParallelPromise()

๋งŒ์•ฝ ๋ณ‘๋ ฌ๋กœ ์•ˆ ๋ถˆ๋Ÿฌ์™”๋‹ค๋ฉด, ์ดˆ๊ธฐ 2000ms + ๊ฐ๊ฐ 1000ms * 5๊ฐ€ ๋˜์–ด 7์ดˆ๊ฐ€ ๊ฑธ๋ ธ์„ ๊ฒƒ์ด๋‹ค. ํ•˜์ง€๋งŒ ๋ณ‘๋ ฌ๋กœ ๋ถˆ๋Ÿฌ์˜จ ๋•๋ถ„์— ์ดˆ๊ธฐ 2000ms + 1000ms๊ฐ€ ๋˜์–ด ๊ฒจ์šฐ 3์ดˆ๋งŒ์— ๋ชจ๋“  ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ๊ฒŒ ๊ฐ€๋Šฅ!

์ฝ”๋“œ ์ƒŒ๋“œ๋ฐ•์Šค๋กœ ์ง์ ‘ ๋ณด๊ธฐ

์ฝ˜์†”์ฐฝ์„ ๋ณด๋ฉด 3์ดˆ๋งŒ์— ๋ชจ๋“  ๊ฐ’์„ ๊ฐ€์ ธ์˜จ ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค.

3. ๊ฐ™์ด ๋ณด๊ธฐ

์œ„ ์ฝ”๋“œ๋ฅผ ๋ณด๋ฉด์„œ ์ดํ•ดํ•˜๋ฉด ๋‹คํ–‰์ด์ง€๋งŒ, ๊ทธ๊ฒŒ ์•„๋‹ˆ๋ผ๋ฉด ์•„๋ž˜์˜ ์ฐธ๊ณ  ๋ฌธ์„œ ์ฝ์–ด๋ณด๊ธธ ๊ถŒํ•œ๋‹ค.

๋น„๋™๊ธฐ๋Š” ์–ด๋Š ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ๊ฐœ๋ฐœ์ž์—๊ฒŒ๋‚˜ ์–ด๋ ค์šด ๊ณผ์ œ์ด๋‹ค. ๋‚™๋‹ดํ•˜์ง€ ๋ง๊ณ  ์ด๋ก ์„ ์ž˜ ์‚ดํŽด๋ณด๋ฉด ๊ธธ์ด ๋ณด์ผ ๊ฒƒ์ด๋‹ค!


Written by@Caesiumy
๐ŸŒ์˜๋ฌธ๊ณผ์—์„œ ์ถœ๋ฐœํ•ด ๐Ÿ’ป์ปดํ“จํ„ฐ๊ณตํ•™์œผ๋กœ ๋„์ฐฉํ•˜๋Š” ํ˜ผ์ข… ๐Ÿ‘จโ€๐Ÿ’ป๊ฐœ๋ฐœ์ž!