Frontend/Javascript

[Javascript] ์ฝœ๋ฐฑ ์ง€์˜ฅ ํƒˆ์ถœํ•˜๊ธฐ - Promise

oneyenee 2024. 2. 15. 00:19

 

๐Ÿ’ก ์ฝœ๋ฐฑ ์ง€์˜ฅ (Callback Hell) ?

 

์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋Š” ๋น„๋™๊ธฐ ์ž‘์—…์„ ์ฒ˜๋ฆฌํ•  ๋•Œ, ์ฝœ๋ฐฑ ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.

๋งŒ์•ฝ, ๋น„๋™๊ธฐ ์ž‘์—…์˜ ๊ฒฐ๊ณผ๋ฅผ ๊ฐ€์ง€๊ณ  ์ฝœ๋ฐฑ ๋‚ด๋ถ€์—์„œ ๋˜๋‹ค๋ฅธ ์ฝœ๋ฐฑ ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค๋ฉด ์–ด๋–ป๊ฒŒ ๋ ๊นŒ? 

์œ„ ์‚ฌ์ง„์ฒ˜๋Ÿผ ์ฝœ๋ฐฑ์˜ ์ฝœ๋ฐฑ์ด ์ค‘์ฒฉ๋˜๋ฉด์„œ ์ฝ”๋“œ์˜ ๊ฐ€๋…์„ฑ์ด ๋‚˜๋น ์ง€๊ณ  ์œ ์ง€๋ณด์ˆ˜๋„ ์–ด๋ ค์›Œ์ง„๋‹ค.

์ด๋Ÿฌํ•œ ๋ฌธ์ œ๋ฅผ "์ฝœ๋ฐฑ ์ง€์˜ฅ" ์ด๋ผ๊ณ  ํ•œ๋‹ค.

 

 

๊ทธ๋ ‡๋‹ค๋ฉด ์œ„ ์ฝ”๋“œ์ฒ˜๋Ÿผ ์ฝœ๋ฐฑ์ง€์˜ฅ์—์„œ ๋ฒ—์–ด๋‚˜๋ ค๋ฉด ์–ด๋–ป๊ฒŒ ํ•ด์•ผํ•˜๋Š” ๊ฑธ๊นŒ?

 


 

 

๐Ÿ’ก Promise

 

  • Promise๋Š” ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ์— ์‚ฌ์šฉ๋˜๋Š” ๊ฐ์ฒด์ด๋‹ค.
  • ์ฝœ๋ฐฑ ํŒจํ„ด์ด ๊ฐ€์ง„ ๋‹จ์ ์„ ๋ณด์™„ํ•˜๊ณ  ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ ์‹œ์ ์„ ๋ช…ํ™•ํ•˜๊ฒŒ ํ‘œํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ์žฅ์ ์ด ์žˆ๋‹ค.

 

 

 

โœ” Promise์˜ 3๊ฐ€์ง€ ์ƒํƒœ

ํ”„๋กœ๋ฏธ์Šค๋Š” ๋น„๋™๊ธฐ ์ž‘์—…์˜ ๊ฒฐ๊ณผ๋ฅผ ์•ฝ์†ํ•œ๋‹ค.

ํ”„๋กœ๋ฏธ์Šค ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๋ฉด, ๋น„๋™๊ธฐ ์ž‘์—…์€ ์ง„ํ–‰์ค‘์ด๊ฑฐ๋‚˜, ์„ฑ๊ณตํ•˜๊ฑฐ๋‚˜, ์‹คํŒจํ•œ๋‹ค.

์ด๋Ÿฌํ•œ ์ƒํƒœ๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” ๊ฒƒ์ด ํ”„๋กœ๋ฏธ์Šค์˜ ์ƒํƒœ(State)๋ผ๊ณ  ํ•œ๋‹ค.

 

 

1) Pending(๋Œ€๊ธฐ ์ƒํƒœ)

 

๋น„๋™๊ธฐ ์ž‘์—…์ด ์ง„ํ–‰ ์ค‘์ด๊ฑฐ๋‚˜, ์‹œ์ž‘ํ•  ์ˆ˜ ์—†๋Š” ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•œ ์ƒํƒœ

 

 

2) Fulfilled(์„ฑ๊ณต)

 

๋น„๋™๊ธฐ ์ž‘์—…์ด ์˜๋„ํ•œ๋Œ€๋กœ ์ •์ƒ์ ์œผ๋กœ ์™„๋ฃŒ๋œ ์ƒํƒœ

 

 

3) Rejected(์‹คํŒจ)

 

๋น„๋™๊ธฐ ์ž‘์—…์ด ๋ชจ์ข…์˜ ์ด์œ ๋กœ ์‹คํŒจํ•œ ์ƒํƒœ.

ex) ์„œ๋ฒ„์‘๋‹ต X. ์‹œ๊ฐ„์ด ๋„ˆ๋ฌด ์˜ค๋ž˜ ๊ฑธ๋ฆฌ๋Š” ๊ฒฝ์šฐ...

 

 

 

 

โœ” Promise ์ž‘์„ฑ๋ฒ•

  • new ํ‚ค์›Œ๋“œ์™€ Promise ์ƒ์„ฑ์ž ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•ด ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค.
  • Promise ์ƒ์„ฑ์ž ํ•จ์ˆ˜์—๋Š” ์ฝœ๋ฐฑํ•จ์ˆ˜๋ฅผ ๋„ฃ๋Š”๋‹ค. ์ด๋•Œ, ์ฝœ๋ฐฑ ํ•จ์ˆ˜๋ฅผ executor ๋ผ๊ณ  ๋ถ€๋ฅธ๋‹ค.
  • executor๋Š” 2๊ฐœ์˜ ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ๊ฐ€์ง„๋‹ค.
  • ์ฒซ ๋ฒˆ์งธ ์ธ์ˆ˜๋Š” ์„ฑ๊ณต์„ ๋œปํ•˜๋Š” resolve ํ•จ์ˆ˜, ๋‘ ๋ฒˆ์งธ ์ธ์ˆ˜๋Š” ์‹คํŒจ๋ฅผ ๋œปํ•˜๋Š” reject ํ•จ์ˆ˜ ์ด๋‹ค.

 

function promiseA() {
	const executor = (resolve, reject) => {
            if (/*์„ฑ๊ณต์กฐ๊ฑด*/) {
                resolve(/*๊ฒฐ๊ณผ๊ฐ’*/)
            } else {
                reject(/*์—๋Ÿฌ๊ฐ’*/)
            }
        }

	return new Promise(executor)
}

 

 

์œ„ ์ฝ”๋“œ์˜ promiseA์˜ ๋ฐ˜ํ™˜๊ฐ’์€ Promise ๊ฐ์ฒด์ด๋‹ค. ๊ทธ๋Ÿผ ์ด ๊ฐ์ฒด๋ฅผ ์–ด๋–ป๊ฒŒ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์„๊นŒ?

 

 

 

โœ” Promise ๊ฐ์ฒด ์ฒ˜๋ฆฌ

Promise ๊ฐ์ฒด์˜ ๋น„๋™๊ธฐ ์ž‘์—…์ด ์™„๋ฃŒ๋œ ํ›„ ์ž‘์—… ๊ฒฐ๊ณผ์— ๋”ฐ๋ผ ๋ฉ”์„œ๋“œ ์ฒด์ด๋‹์„ ํ†ตํ•ด ํ›„์† ์ฒ˜๋ฆฌ๊ฐ€ ๊ฐ€๋Šฅํ•˜๋‹ค.

  • ์ฒ˜๋ฆฌ ์„ฑ๊ณต ์‹œ
    • resolve(๊ฒฐ๊ณผ๊ฐ’) ํ˜ธ์ถœ
    • .then() ์œผ๋กœ ์ด์–ด์ ธ ์„ฑ๊ณต์— ๋Œ€ํ•œ ์ถ”๊ฐ€ ์ฒ˜๋ฆฌ ์ง„ํ–‰
    • .then() ์€ resolve ํ•จ์ˆ˜์˜ argument ๊ฐ’์ด then ์ธ์ž๋กœ ๋“ค์–ด๊ฐ„๋‹ค.
    • ex) resolve(data) -> .then(data) ๋กœ ์‚ฌ์šฉ๊ฐ€๋Šฅ
  • ์ฒ˜๋ฆฌ ์‹คํŒจ ์‹œ
    • reject() ํ˜ธ์ถœ
    • .catch() ๋กœ ์ด์–ด์ ธ ์‹คํŒจ์— ๋Œ€ํ•œ ์ถ”๊ฐ€ ์ฒ˜๋ฆฌ ์ง„ํ–‰
    • resolve์™€ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ์ „๋‹ฌํ•œ ๊ฐ’์€ catch์˜ ์ธ์ž๋กœ ๋ฐ›์•„ ํ•ธ๋“ค๋ง์ด ๊ฐ€๋Šฅํ•˜๋‹ค.

 

function promiseA () {
	return new Promise((resolve, reject)=>{
            if (/* ์„ฑ๊ณต์กฐ๊ฑด */) {
                resolve(/* ๊ฒฐ๊ณผ ๊ฐ’ */)
            } else {
                reject(/* ์—๋Ÿฌ ๊ฐ’ */)
            }
    	})
}


promiseA()
	.then((res)=>{
            // ์„ฑ๊ณต ์‹œ ์‹คํ–‰ํ•  ์ฝœ๋ฐฑ ํ•จ์ˆ˜ -> ๊ฒฐ๊ณผ ๊ฐ’ ์‚ฌ์šฉ ๊ฐ€๋Šฅ
        })
        .catch((err)=>{
            // ์‹คํŒจ ์‹œ ์‹คํ–‰ํ•  ์ฝœ๋ฐฑ ํ•จ์ˆ˜ -> ์—๋Ÿฌ ๊ฐ’ ์‚ฌ์šฉ ๊ฐ€๋Šฅ
        })

 

 

 

 

โœ” Promise ์—ฌ๋Ÿฌ๊ฐœ ์‚ฌ์šฉํ•˜๊ธฐ

์—ฌ๋Ÿฌ ๊ฐœ์˜ ๋น„๋™๊ธฐ ์ž‘์—…์„ ์ˆœ์ฐจ์ ์œผ๋กœ ํ•˜๋Š” ๋ฐฉ๋ฒ•์ด ์žˆ์„๊นŒ?

์ •๋‹ต์€ ํ”„๋กœ๋ฏธ์Šค ๊ฐ์ฒด๋ฅผ ์—ฐ๋‹ฌ์•„ ์—ฐ๊ฒฐํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

 

๋น„๋™๊ธฐ ํ•จ์ˆ˜ A, B, C ๊ฐ€ ์žˆ๋‹ค.

์ˆœ์„œ๋Œ€๋กœ A->B->C ์ˆœ์œผ๋กœ ์‹คํ–‰๋œ๋‹ค๊ณ  ๊ฐ€์ •ํ–ˆ์„ ๋•Œ, A์˜ ๊ฒฐ๊ณผ๊ฐ’์œผ๋กœ B๋ฅผ ์‹คํ–‰ํ•˜๊ณ  B์˜ ๊ฒฐ๊ณผ๊ฐ’์œผ๋กœ C๋ฅผ ์‹คํ–‰ํ•˜๊ณ ์ž ํ•œ๋‹ค. 

 

  • ํ•จ์ˆ˜ A ๋Š” ์‹คํ–‰ ์‹œ, 3์ดˆ ๋’ค ๋‘ ๊ฐœ์˜ ์ž…๋ ฅ๊ฐ’ a, b๋ฅผ ๋”ํ•œ ๊ฐ’์„ ๊ฒฐ๊ณผ ๊ฐ’์œผ๋กœ ํ•œ๋‹ค.
  • ํ•จ์ˆ˜ B ๋Š” ์‹คํ–‰ ์‹œ, 1์ดˆ ๋’ค ์ž…๋ ฅ๊ฐ’ a์— 2๋ฅผ ๊ณฑํ•œ ๊ฐ’์„ ๊ฒฐ๊ณผ ๊ฐ’์œผ๋กœ ํ•œ๋‹ค.
  • ํ•จ์ˆ˜ C ๋Š” ์‹คํ–‰ ์‹œ, 2์ดˆ ๋’ค ์ž…๋ ฅ๊ฐ’ a์— -1๋ฅผ ๊ณฑํ•œ ๊ฐ’์„ ๊ฒฐ๊ณผ ๊ฐ’์œผ๋กœ ํ•œ๋‹ค.

 

ํ•จ์ˆ˜ A, B, C๋กœ ํ”„๋กœ๋ฏธ์Šค ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๋ฉด ์•„๋ž˜์™€ ๊ฐ™๋‹ค.

 

function promiseA(a, b) {
	return new Promise((resolve, reject) => {
            setTimeOut(()=>{ resolve(a+b) }, 3000)
        })
}

function promiseB(a) {
	return new Promise((resolve, reject) => {
            setTimeOut(()=>{ resolve(a*2) }, 1000)
        })
}

function promiseC(a) {
	return new Promise((resolve, reject) => {
            setTimeOut(()=>{ resolve(a*-1) }, 2000)
        })
}

 

 

  • ํ•จ์ˆ˜ A ์˜ ๊ฒฐ๊ณผ ๊ฐ’์œผ๋กœ B๋ฅผ ์‹คํ–‰ํ•œ๋‹ค.
  • ํ•จ์ˆ˜ B ์˜ ๊ฒฐ๊ณผ ๊ฐ’์œผ๋กœ C๋ฅผ ์‹คํ–‰ํ•œ๋‹ค.
  • ๊ฐ ํ•จ์ˆ˜๋Š” ๊ฒฐ๊ณผ ๊ฐ’ ๋„์ถœ ์‹œ, ํ˜„์žฌ์˜ ๊ฒฐ๊ณผ๊ฐ’์„ ์ฝ˜์†”์— ๋„์šด๋‹ค.

 

์œ„ ์กฐ๊ฑด์œผ๋กœ 3๊ฐœ์˜ ํ•จ์ˆ˜๋ฅผ ํ”„๋กœ๋ฏธ์Šค๋กœ ์—ฐ๋‹ฌ์•„ ์‚ฌ์šฉํ•ด๋ณด์ž.

 

promiseA(3,5)
	.then((a_res)=>{
            console.log('A ํ•จ์ˆ˜์˜ ๊ฒฐ๊ณผ ๊ฐ’ : ', a_res);   // 3์ดˆ ๋’ค, A ํ•จ์ˆ˜์˜ ๊ฒฐ๊ณผ ๊ฐ’ : 8
            return promiseB(a_res);
        })
        .then((b_res)=>{
            console.log('B ํ•จ์ˆ˜์˜ ๊ฒฐ๊ณผ ๊ฐ’ : ', b_res);  // 1์ดˆ ๋’ค, B ํ•จ์ˆ˜์˜ ๊ฒฐ๊ณผ ๊ฐ’ : 16
            return promiseC(b_res);
        })
        .then((c_res)=>{
            console.log('C ํ•จ์ˆ˜์˜ ๊ฒฐ๊ณผ ๊ฐ’ : ', c_res);   // 2์ดˆ ๋’ค, C ํ•จ์ˆ˜์˜ ๊ฒฐ๊ณผ ๊ฐ’ : -16
        })

 

 

ํ•ต์‹ฌ์€ return์œผ๋กœ promise ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

promise ๊ฐ์ฒด๋Š” then์œผ๋กœ ์ ‘๊ทผ ๊ฐ€๋Šฅํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์œ„์™€ ๊ฐ™์€ ์ฝ”๋“œ๋ฅผ ์™„์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค.