๐ŸŒฑ Background Story

JavaScript๋Š” ๋‹จ์ผ ์Šค๋ ˆ๋“œ ๊ธฐ๋ฐ˜์œผ๋กœ, ๋‘ ์Šคํฌ๋ฆฝํŠธ๋ฅผ ๋™์‹œ์— ์‹คํ–‰ํ•  ์ˆ˜ ์—†์œผ๋ฉฐ ์ฐจ๋ก€๋กœ ์‹คํ–‰ํ•ด์•ผ ํ•œ๋‹ค.

JS์—์„œ ์‹คํ–‰๋  ์ค€๋น„๊ฐ€ ๋œ ์ฝ”๋“œ ์กฐ๊ฐ์€ Job Queue(์ž‘์—… ๋Œ€๊ธฐ์—ด)์— ๋ณด๊ด€๋œ๋‹ค. ์ฝ”๋“œ ์‹คํ–‰์ด ๋๋‚˜๋ฉด, ์ด ๋Œ€๊ธฐ์—ด์„ ๊ด€๋ฆฌํ•˜๋Š” Event Loop์—์„œ ๋‹ค์Œ์— ๋Œ€๊ธฐ์ค‘์ธ ์ž‘์—…์„ ์‹คํ–‰ํ•œ๋‹ค.

Javascript์—์„œ ๋น„๋™๊ธฐ์ ์œผ๋กœ ๊ฒฐ๊ณผ๋ฅผ ์–ป๊ธฐ ์œ„ํ•œ ๋ฐฉ๋ฒ•์œผ๋กœ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ํŒจํ„ด์ด ์กด์žฌํ•œ๋‹ค.

โ˜๏ธ Event๋ฅผ ์ด์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•

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

์ด๋ฒคํŠธ๋Š” ๋™์ผ ๊ฐ์ฒด์— ์—ฌ๋Ÿฌ ๋ฒˆ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋Š” ๊ฐ„๋‹จํ•œ ์ž‘์—…์—๋Š” ์ข‹์ง€๋งŒ, ๋ฉ€ํ‹ฐ ์Šค๋ ˆ๋“œ ์ž‘์—…์— ์ตœ์„ ์˜ ๋ฐฉ๋ฒ•์€ ์•„๋‹ˆ๋‹ค. ๊ฐ€๋ น, ์—ฌ๋Ÿฌ ๊ฐœ์˜ ๋น„๋™๊ธฐ ํ˜ธ์ถœ์„ ํ•จ๊ป˜ ์—ฐ๊ฒฐํ•ด์•ผ ํ•œ๋‹ค๋ฉด ๋จผ์ € ๊ฐ ์ด๋ฒคํŠธ์— ๋Œ€ํ•œ ๋Œ€์ƒ์„ ์ถ”์ ํ•ด์•ผ ํ•œ๋‹ค. ๋˜ํ•œ ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•˜๊ธฐ ์ „์— ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๋ฅผ ์ถ”๊ฐ€ํ•ด์•ผ ํ•œ๋‹ค.

โœŒ๏ธCallback์„ ์ด์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•

JavaScript์—์„œ ํ•จ์ˆ˜๋Š” 1๊ธ‰ ๊ฐ์ฒด์ด๋ฏ€๋กœ, ํ•จ์ˆ˜๋ฅผ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ๋‹ค. ์ฝœ๋ฐฑ ํŒจํ„ด์€ ํ˜ธ์ถœํ•  ํ•จ์ˆ˜๊ฐ€ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ์ „๋‹ฌ๋œ๋‹ค๋Š” ์ ์—์„œ ์ด๋ฒคํŠธ์™€ ์ฐจ์ด๊ฐ€ ์žˆ๋‹ค. ์ด๋ ‡๊ฒŒ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ์ „๋‹ฌํ•œ ํ•จ์ˆ˜๋Š” Job Queue์˜ ๋์— ์ถ”๊ฐ€๋˜๊ณ , ์ฝœ๋ฐฑ ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•œ ํ•จ์ˆ˜์˜ ์ž‘์—…์ด ๋๋‚˜๋ฉด ์‹คํ–‰๋œ๋‹ค.

์ฝœ๋ฐฑ์€ ์ด๋ฒคํŠธ๋ณด๋‹ค ๋น„๊ต์  ์—ฌ๋Ÿฌ ๊ฐœ์˜ ํ˜ธ์ถœ์„ ํ•จ๊ป˜ ์—ฐ๊ฒฐํ•˜๊ธฐ ์‰ฝ๋‹ค. ํ•˜์ง€๋งŒ ์—ฐ์†์ ์ธ ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ๋ฅผ ์œ„ํ•ด ๋„ˆ๋ฌด ๋งŽ์€ ์ฝœ๋ฐฑ์„ ์ค‘์ฒฉํ•˜์—ฌ ์‚ฌ์šฉํ–ˆ์„ ๋•Œ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค. ์ด๋Š” ์ฝœ๋ฐฑ ์ง€์˜ฅ์ด๋ผ ๋ถˆ๋ฆฌ๋Š” ๊ฒƒ์œผ๋กœ ์ฝœ๋ฐฑ ์†์— ์ฝœ๋ฐฑ, ๊ทธ๋ฆฌ๊ณ  ์ฝœ๋ฐฑ ์†์— ๋˜ ์ฝœ๋ฐฑ์ด ์ด์–ด์ง€๋Š” ์ดํ•ดํ•˜๊ธฐ ์–ด๋ ค์šด ์ฝ”๋“œ๋ฅผ ๋งŒ๋“ ๋‹ค.

๐Ÿค ํ”„๋ผ๋ฏธ์Šค(Promise)

ํ”„๋ผ๋ฏธ์Šค๋ž€?

ํ”„๋ผ๋ฏธ์Šค๋Š” ์ฝœ๋ฐฑ์˜ ๋‹จ์ ์„ ํ•ด๊ฒฐํ•˜๋ ค๋Š” ์‹œ๋„ ์†์—์„œ ๋งŒ๋“ค์–ด์กŒ๋‹ค. ํ•˜์ง€๋งŒ ํ”„๋ผ๋ฏธ์Šค๊ฐ€ ์ฝœ๋ฐฑ์„ ๋Œ€์ฒดํ•˜๋Š”๊ฒƒ์€ ์•„๋‹ˆ๋ฉฐ, ํ”„๋ผ๋ฏธ์Šค์—์„œ๋„ ์ฝœ๋ฐฑ์„ ์‚ฌ์šฉํ•œ๋‹ค. ๋‹ค๋งŒ, ์˜ˆ์ธก ๊ฐ€๋Šฅํ•œ ํŒจํ„ด์œผ๋กœ ์ฝœ๋ฐฑ์„ ์‚ฌ์šฉํ•˜๊ฒŒ ํ•˜์—ฌ ์ฝœ๋ฐฑ๋งŒ ์‚ฌ์šฉ ์‹œ ์ฐพ๊ธฐ ํž˜๋“  ๋ฒ„๊ทธ๋ฅผ ํ•ด๊ฒฐํ•œ๋‹ค

ํ”„๋ผ๋ฏธ์Šค๋Š” ์ด๋ฒคํŠธ ๋ฆฌ์Šค๋„ˆ์™€ ์œ ์‚ฌํ•˜๋‚˜, ๋‹ค์Œ์˜ ์ฐจ์ด๊ฐ€ ์žˆ๋‹ค.

  • ํ”„๋ผ๋ฏธ์Šค๋Š” ๋”ฑ ํ•œ ๋ฒˆ๋งŒ ์„ฑ๊ณต ๋˜๋Š” ์‹คํŒจํ•œ๋‹ค.
  • ํ”„๋ผ๋ฏธ์Šค๊ฐ€ ์„ฑ๊ณต ๋˜๋Š” ์‹คํŒจํ•œ ํ›„์— ๊ฐ๊ฐ์˜ ์ฝœ๋ฐฑ์„ ์ถ”๊ฐ€ํ•˜๋ฉด ์ด๋ฒคํŠธ๊ฐ€ ๋” ์ผ์ฐ ๋ฐœ์ƒํ•ด๋„ ์˜ฌ๋ฐ”๋ฅธ ์ฝœ๋ฐฑ์ด ํ˜ธ์ถœ๋œ๋‹ค.

์ด๋Š” ๋ฌด์–ธ๊ฐ€ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•ด์ง„ ์ •ํ™•ํ•œ ์‹œ๊ฐ„์„ ์•„๋Š” ๊ฒƒ๋ณด๋‹ค ๊ฒฐ๊ณผ์— ๋”ฐ๋ฅธ ์‘๋‹ต์ด ์ค‘์š”ํ•œ ๋น„๋™๊ธฐ ์ž‘์—…์— ์œ ์šฉํ•˜๋‹ค.

ํ”„๋ผ๋ฏธ์Šค์˜ ์ƒํƒœ

ํ”„๋กœ๋ฏธ์Šค๋Š” ์ƒํ˜ธ ๋ฐฐํƒ€์ ์ธ ์„ธ ๊ฐ€์ง€ ์ƒํƒœ๋ฅผ ๊ฐ€์ง„๋‹ค.

  • ์ฒ˜๋ฆฌ๋จ fulfilled : ํ”„๋กœ๋ฏธ์Šค์™€ ๊ด€๋ จ๋œ ์ž‘์—…์ด ์„ฑ๊ณต์ ์œผ๋กœ ์ˆ˜ํ–‰๋จ
  • ๊ฑฐ๋ถ€๋จ rejected : ํ”„๋กœ๋ฏธ์Šค์™€ ๊ด€๋ จ๋œ ์ž‘์—…์ด ์‹คํŒจํ•จ
  • ๋ณด๋ฅ˜๋จ pending : ์ฒ˜๋ฆฌ(fulfilled)๋˜๊ฑฐ๋‚˜ ๊ฑฐ๋ถ€(rejected)๋˜์ง€ ์•Š์€ ์ƒํƒœ

ํ”„๋ผ๋ฏธ์Šค์˜ ๊ฒฐ๊ณผ๋Š” ์„ฑ๊ณต(fulfilled)ํ•˜๊ฑฐ๋‚˜ ์‹คํŒจ(rejected)ํ•˜๊ฑฐ๋‚˜ ๋‹จ ๋‘ ๊ฐ€์ง€ ๋ฟ์ด๋ฉฐ, ์ด ๋•Œ ๊ฒฐ์ •๋๋‹ค(settled)๋ผ๊ณ  ํ•œ๋‹ค. ํ™•์‹คํ•œ ์„ฑ๊ณต ํ˜น์€ ์‹คํŒจ ๋‘ ๊ฐ€์ง€ ์ค‘ ๋‹จ ํ•˜๋‚˜๋งŒ ๋”ฑ ํ•œ๋ฒˆ ์ผ์–ด๋‚œ๋‹ค. ์„ฑ๊ณตํ–ˆ๋‹ค๊ฐ€ ์‹คํŒจํ•˜๋Š” ๊ฑด ์—†๋‹ค.

ํ”„๋ผ๋ฏธ์Šค์™€ ํ•จ๊ป˜ ์“ฐ์ด๋Š” resolved๋ผ๋Š” ๋‹จ์–ด๋Š” ๋‹ค๋ฅธ ํ”„๋ผ๋ฏธ์Šค์˜ ์ƒํƒœ์— ๋งž์ถฐ ์ฒ˜๋ฆฌ๋˜๊ฑฐ๋‚˜ ๊ฑฐ๋ถ€๋˜์–ด ์ƒํƒœ๊ฐ€ ๊ณ ์ •(locked in)๋˜์—ˆ๋‹ค๋Š” ์˜๋ฏธ์ด๋‹ค.

์ฝœ๋ฐฑ๊ณผ ๋‹ฌ๋ฆฌ ํ”„๋ผ๋ฏธ์Šค๋Š” ๊ฐ์ฒด์ด๋ฏ€๋กœ ์–ด๋””๋“  ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ๋‹ค. ๋”ฐ๋ผ์„œ ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ๋ฅผ ๋‹ค๋ฅธ ํ•จ์ˆ˜๋กœ ๋„˜๊ฒจ ์ฒ˜๋ฆฌํ•˜๊ฒŒ ํ•  ์ˆ˜๋„ ์žˆ๋‹ค.

ํ”„๋ผ๋ฏธ์Šค ์˜ˆ์ œ

ํ”„๋ผ๋ฏธ์Šค๋ฅผ ๋งŒ๋“œ๋Š” ๊ธฐ๋ณธ์ ์ธ ๋ฐฉ๋ฒ•์€ resolve์™€ reject ์ฝœ๋ฐฑ์ด ์žˆ๋Š” ํ•จ์ˆ˜๋กœ Promise ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

    // seconds๋งŒํผ์˜ ์นด์šดํŠธ๋‹ค์šด์ด ๋๋‚˜๋ฉด ํ”„๋ผ๋ฏธ์Šค ๋ฐ˜ํ™˜ํ•˜๋Š” ํ•จ์ˆ˜
    function contdown (seconds){
      return new Promise(
            funciton(resolve, reject){
            for(let i=seconds; i >=0; i--){
              setTimeout(function(){
                if(i>0)
                  console.log(i+ '...');
                else
                  resolve(console.log('GO!'));
              }, (seconds-1) * 1000);
            }
      });
    }

    // ์‚ฌ์šฉ๋ฒ• 1 : then์œผ๋กœ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ”๋กœ ์ฒ˜๋ฆฌํ•˜๊ธฐ
    countdown(5).then({
      function(){ 
            console.log('success!'); 
    }, function(err){
            console.log('error!');
    } })

    // ์‚ฌ์šฉ๋ฒ• 2 : ํ”„๋ผ๋ฏธ์Šค๋ฅผ ๋ณ€์ˆ˜์— ํ• ๋‹นํ•œ ํ›„ then๊ณผ catch๋ฅผ ์ด์šฉํ•ด ์ฒ˜๋ฆฌํ•˜๊ธฐ
    const p = countdown(5);
    p.then(function(){
        console.log('success');
    });
    p.catch(function(){
        console.log('error');
    });
  • resolve ์™€ reject๋Š” ํ•จ์ˆ˜์ด์ง€๋งŒ, ์ฒซ ๋ฒˆ์งธ๋งŒ ํ˜ธ์ถœํ•œ ๊ฒƒ๋งŒ ์˜๋ฏธ๊ฐ€ ์žˆ๋‹ค. (์—ฌ๋Ÿฌ๋ฒˆ ํ˜ธ์ถœํ•ด๋„ ์˜๋ฏธ์—†๋‹ค)

  • ์‚ฌ์šฉ๋ฒ• 1: ๋ฐ˜ํ™˜๋œ ํ”„๋ผ๋ฏธ์Šค๋ฅผ ๋ณ€์ˆ˜์— ํ• ๋‹นํ•˜์ง€ ์•Š๊ณ  then ํ•ธ๋“ค๋Ÿฌ ํ˜ธ์ถœ ํ›„ ์„ฑ๊ณต ํ˜น์€ ์—๋Ÿฌ ์ฝœ๋ฐฑ์„ ๋ฐ›๋Š”๋‹ค.

  • ์‚ฌ์šฉ๋ฒ• 2: ํ”„๋ผ๋ฏธ์Šค๋ฅผ ๋ณ€์ˆ˜์— ํ• ๋‹นํ•œ๋‹ค. ํ”„๋ผ๋ฏธ์Šค๋Š” catch ํ•ธ๋“ค๋Ÿฌ๋„ ์ง€์›ํ•˜๋ฏ€๋กœ ๋‘˜๋กœ ๋‚˜๋ˆ ์„œ ์จ๋„ ๋œ๋‹ค.

์ฐธ๊ณ 

๋Ÿฌ๋‹ ์ž๋ฐ” ์Šคํฌ๋ฆฝํŠธ : ES6๋กœ ์ œ๋Œ€๋กœ ์ž…๋ฌธํ•˜๋Š” ๋ชจ๋˜ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ์›น ๊ฐœ๋ฐœ(์ด์„  ๋ธŒ๋ผ์šด, ํ•œ๋น›๋ฏธ๋””์–ด)
https://github.com/domenic/promises-unwrapping/blob/master/docs/states-and-fates.md
https://developers.google.com/web/fundamentals/primers/promises?hl=ko