관리 메뉴

Daehyunii's Dev-blog

42μž₯ 비동기 ν”„λ‘œκ·Έλž˜λ° λ³Έλ¬Έ

πŸ“š Language & CS knowledge/JavaScript (λͺ¨λ˜μžλ°”μŠ€ν¬λ¦½νŠΈ Deep Dive)

42μž₯ 비동기 ν”„λ‘œκ·Έλž˜λ°

Daehyunii 2022. 7. 29. 20:47

42.1 동기 μ²˜λ¦¬μ™€ 비동기 처리

  ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•˜λ©΄ ν•¨μˆ˜ μ½”λ“œκ°€ ν‰κ°€λ˜μ–΄ ν•¨μˆ˜ μ‹€ν–‰ μ»¨ν…μŠ€νŠΈκ°€ μƒμ„±λœλ‹€. μ΄λ•Œ μƒμ„±λœ ν•¨μˆ˜ μ‹€ν–‰ μ»¨ν…μŠ€νŠΈλŠ” μ‹€ν–‰ μ»¨ν…μŠ€νŠΈ μŠ€νƒ(콜 μŠ€νƒ)에 ν‘Έμ‹œλ˜κ³  ν•¨μˆ˜μ½”λ“œκ°€ μ‹€ν–‰λœλ‹€. ν•¨μˆ˜ μ½”λ“œμ˜ 싀행이 μ’…λ£Œν•˜λ©΄ ν•¨μˆ˜ μ‹€ν–‰ μ»¨ν…μŠ€νŠΈλŠ” μ‹€ν–‰ μ»¨ν…μŠ€νŠΈ μŠ€νƒμ—μ„œ νŒλ˜μ–΄ μ œκ±°λœλ‹€. 

2022.07.20 - [μ–Έμ–΄ 곡뢀 및 정리/μžλ°”μŠ€ν¬λ¦½νŠΈ[λͺ¨λ˜μžλ°”μŠ€ν¬λ¦½νŠΈ]] - 23μž₯ μ‹€ν–‰ μ»¨ν…μŠ€νŠΈ

 

23μž₯ μ‹€ν–‰ μ»¨ν…μŠ€νŠΈ

μ‹€ν–‰ μ»¨ν…μŠ€νŠΈλŠ” μžλ°”μŠ€ν¬λ¦½νŠΈμ˜ λ™μž‘ 원리λ₯Ό λ‹΄κ³  μžˆλŠ” 핡심 κ°œλ…μ΄λ‹€. 이 κ°œλ…μ„ λͺ…ν™•ν•˜κ²Œ μ΄ν•΄ν•˜λ©΄ μžλ°”μŠ€ν¬λ¦½νŠΈκ°€ μŠ€μ½”ν”„ 기반으둜 μ‹λ³„μžμ™€ μ‹λ³„μžμ— λ°”μΈλ”©λœ 값을 κ΄€λ¦¬ν•˜λŠ” 방식과 호

pinetree93.tistory.com

μžλ°”μŠ€ν¬λ¦½νŠΈ 엔진은 단 ν•˜λ‚˜μ˜ μ‹€ν–‰ μ»¨ν…μŠ€νŠΈ μŠ€νƒμ„ κ°–λŠ”λ‹€. μ΄λŠ” ν•œ λ²ˆμ— ν•˜λ‚˜μ˜ νƒœμŠ€ν¬λ§Œ μ‹€ν–‰ν•  수 μžˆλ‹€λŠ” 뜻이고, λ‹€μ‹œ 말해 μžλ°”μŠ€ν¬λ¦½νŠΈ 엔진은 ν•œ λ²ˆμ— ν•˜λ‚˜μ˜ νƒœμŠ€ν¬λ§Œ μ‹€ν–‰ν•  수 μžˆλŠ” μ‹±κΈ€ μŠ€λ ˆλ“œ λ°©μ‹μœΌλ‘œ λ™μž‘ν•œλ‹€. μ‹±κΈ€ μŠ€λ ˆλ“œ 방식은 ν•˜λ‚˜μ˜ νƒœμŠ€ν¬λ§Œ μ‹€ν–‰ν•  수 있기 λ•Œλ¬Έμ— μ²˜λ¦¬μ— μ‹œκ°„μ΄ κ±Έλ¦¬λŠ” νƒœμŠ€ν¬λ₯Ό μ‹€ν–‰ν•˜λŠ” 경우 λΈ”λ‘œν‚Ή(μž‘μ—… 쀑단)이 λ°œμƒν•œλ‹€.

// sleep ν•¨μˆ˜λŠ” 일정 μ‹œκ°„μ΄ κ²½κ³Όν•œ 이후에 콜백 ν•¨μˆ˜(func)λ₯Ό ν˜ΈμΆœν•œλ‹€.
function sleep(func, delay){
    const delayUntil = Date.now() + delay;
    while (Date.now() < delayUntil);
    func(); 
}

function foo(){
    console.log('foo');
}

function bar(){
    console.log('bar');
}
//sleep ν•¨μˆ˜λŠ” 3초 이상 μ‹€ν–‰λœλ‹€.
sleep(foo, 3 * 1000);
//bar ν•¨μˆ˜λŠ” sleep ν•¨μˆ˜μ˜ 싀행이 μ’…λ£Œλœ 이후에 ν˜ΈμΆœλ˜λ―€λ‘œ 3초 이상 λΈ”λ‘œν‚Ήλœλ‹€.
bar();
//(3초 κ²½κ³Ό ν›„) foo 호좜 -> bar 호좜

  μœ„ μ½”λ“œ 처럼 μ‹€ν–‰ 쀑인 νƒœμŠ€ν¬κ°€ μ’…λ£Œν•  λ•ŒκΉŒμ§€ λ‹€μŒμ— 싀행될 νƒœμŠ€ν¬κ°€ λŒ€κΈ°ν•˜λŠ” 방식을 동기 처리라고 ν•œλ‹€. 동기 처리 방식은 νƒœμŠ€ν¬λ₯Ό μˆœμ„œλŒ€λ‘œ ν•˜λ‚˜μ”© μ²˜λ¦¬ν•˜λ―€λ‘œ μ‹€ν–‰ μˆœμ„œκ°€ 보μž₯λœλ‹€λŠ” μž₯점이 μžˆμ§€λ§Œ μ•žμ„  νƒœμŠ€ν¬κ°€ μ’…λ£Œν•  λ•ŒκΉŒμ§€ 이후 νƒœμŠ€ν¬λ“€μ΄ λΈ”λ‘œν‚Ήλ˜λŠ” 단점이 μžˆλ‹€.

function foo(){
    console.log('foo');
}

function bar(){
    console.log('bar');
}
// 타이머 ν•¨μˆ˜ setTimeout은 bar ν•¨μˆ˜λ₯Ό λΈ”λ‘œν‚Ήν•˜μ§€ μ•ŠλŠ”λ‹€.
setTimeout(foo, 3 * 1000);
bar();
// bar ν•¨μˆ˜ 호좜 -> 3초 κ²½κ³Ό ν›„ foo ν•¨μˆ˜ 호좜

  setTimeout ν•¨μˆ˜λŠ” sleep ν•¨μˆ˜μ™€ μœ μ‚¬ν•˜κ²Œ 일정 μ‹œκ°„μ΄ κ²½κ³Όν•œ 이후에 콜백 ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•˜μ§€λ§Œ setTimeout ν•¨μˆ˜ μ΄ν›„μ˜ νƒœμŠ€ν¬λ₯Ό λΈ”λ‘œν‚Ήν•˜μ§€ μ•Šκ³  κ³§λ°”λ‘œ μ‹€ν–‰ν•œλ‹€. 이처럼 ν˜„μž¬ μ‹€ν–‰ 쀑인 νƒœμŠ€ν¬κ°€ μ’…λ£Œλ˜μ§€ μ•Šμ€ μƒνƒœλΌ 해도 λ‹€μŒ νƒœμŠ€ν¬λ₯Ό κ³§λ°”λ‘œ μ‹€ν–‰ν•˜λŠ” 방식을 비동기 처리라고 ν•œλ‹€. 비동기 처리 방식은 ν˜„μž¬ μ‹€ν–‰ 쀑인 νƒœμŠ€ν¬κ°€ μ’…λ£Œλ˜μ§€ μ•Šμ€ μƒνƒœλΌ 해도 λ‹€μŒ νƒœμŠ€ν¬λ₯Ό κ³§λ°”λ‘œ μ‹€ν–‰ν•˜λ―€λ‘œ λΈ”λ‘œν‚Ήμ΄ λ°œμƒν•˜μ§€ μ•ŠλŠ”λ‹€λŠ” μž₯점이 μžˆμ§€λ§Œ, νƒœμŠ€ν¬μ˜ μ‹€ν–‰ μˆœμ„œκ°€ 보μž₯λ˜μ§€ μ•ŠλŠ” 단점이 μžˆλ‹€. 비동기 처리λ₯Ό μˆ˜ν–‰ν•˜λŠ” 비동기 ν•¨μˆ˜λŠ” μ „ν†΅μ μœΌλ‘œ 콜백 νŒ¨ν„΄μ„ μ‚¬μš©ν•œλ‹€. ν•˜μ§€λ§Œ 비동기 처리λ₯Ό μœ„ν•œ 콜백 νŒ¨ν„΄μ€ 콜백 헬을 λ°œμƒμ‹œμΌœ 가독성을 λ‚˜μ˜κ²Œ λ§Œλ“€κ³ , 비동기 처리 쀑 λ°œμƒν•œ μ—λŸ¬μ˜ μ˜ˆμ™Έ μ²˜λ¦¬κ°€ κ³€λž€ν•˜λ©°, μ—¬λŸ¬ 개의 비동기 처리λ₯Ό ν•œ λ²ˆμ— μ²˜λ¦¬ν•˜λŠ” 데도 ν•œκ³„κ°€ μžˆλ‹€. 

 

  타이머 ν•¨μˆ˜μΈ setTimeoutκ³Ό setInterval, HTTPμš”μ²­, 이벀트 ν•Έλ“€λŸ¬λŠ” 비동기 처리 λ°©μ‹μœΌλ‘œ λ™μž‘ν•œλ‹€. 비동기 μ²˜λ¦¬λŠ” 이벀트 루프와 νƒœμŠ€ν¬ 큐와 κΉŠμ€ 관계가 μžˆλ‹€.

 

42.2 이벀트 루프와 νƒœμŠ€ν¬ 큐

  μžλ°”μŠ€ν¬λ¦½νŠΈμ˜ νŠΉμ§• 쀑 ν•˜λ‚˜λŠ” μ‹±κΈ€ μŠ€λ ˆλ“œλ‘œ λ™μž‘ν•œλ‹€λŠ” 것이닀. ν•˜μ§€λ§Œ λΈŒλΌμš°μ €κ°€ λ™μž‘ν•˜λŠ” 것을 μ‚΄νŽ΄λ³΄λ©΄ λ§Žμ€ νƒœμŠ€ν¬κ°€ λ™μ‹œμ— μ²˜λ¦¬λ˜λŠ” κ²ƒμ²˜λŸΌ λŠκ»΄μ§„λ‹€. 이처럼 μžλ°”μŠ€ν¬λ¦½νŠΈμ˜ λ™μ‹œμ„±μ„ μ§€μ›ν•˜λŠ” 것이 λ°”λ‘œ 이벀트 루프닀. 이벀트 λ£¨ν”„λŠ” λΈŒλΌμš°μ €μ— λ‚΄μž₯λ˜μ–΄ μžˆλŠ” κΈ°λŠ₯ 쀑 ν•˜λ‚˜λ‹€. 

 

  μžλ°”μŠ€ν¬λ¦½νŠΈ 엔진은 크게  콜 μŠ€νƒ(μ‹€ν–‰ μ»¨ν…μŠ€νŠΈ)와 νž™(객체가 μ €μž₯λ˜λŠ” λ©”λͺ¨λ¦¬ 곡간)으둜 κ΅¬μ„±λœλ‹€. μžλ°”μŠ€ν¬λ¦½νŠΈ 엔진은 λ‹¨μˆœνžˆ νƒœμŠ€ν¬κ°€ μš”μ²­λ˜λ©΄ 콜 μŠ€νƒμ„ 톡해 μš”μ²­λœ μž‘μ—…μ„ 순차적으둜 μ‹€ν–‰ν•  뿐이닀. 비동기 μ²˜λ¦¬μ—μ„œ μ†ŒμŠ€μ½”λ“œμ˜ 평가와 싀행을 μ œμ™Έν•œ λͺ¨λ“  μ²˜λ¦¬λŠ” μžλ°”μŠ€ν¬λ¦½νŠΈ 엔진을 κ΅¬λ™ν•˜λŠ” ν™˜κ²½μΈ λΈŒλΌμš°μ €λ‚˜ Node.jsμ—μ„œ λ‹΄λ‹Ήν•œλ‹€. 

 

예λ₯Ό λ“€μ–΄, 비동기 λ°©μ‹μœΌλ‘œ λ™μž‘ν•˜λŠ” setTImeout의 콜백 ν•¨μˆ˜μ˜ 평가와 싀행은 μžλ°”μŠ€ν¬λ¦½νŠΈ 엔진이 λ‹΄λ‹Ήν•˜μ§€λ§Œ 호좜 μŠ€μΌ€μ€„λ§μ„ μœ„ν•œ 타이머 μ„€μ •κ³Ό 콜백 ν•¨μˆ˜μ˜ 등둝은 λΈŒλΌμš°μ € λ˜λŠ” Node.jsκ°€ λ‹΄λ‹Ήν•œλ‹€. 이λ₯Ό μœ„ν•΄ λΈŒλΌμš°μ € ν™˜κ²½μ€ νƒœμŠ€ν¬ 큐와 이벀트 루프λ₯Ό μ œκ³΅ν•œλ‹€.

 

1. νƒœμŠ€ν¬ 큐

setTimeoutμ΄λ‚˜ setIntervalκ³Ό 같은 비동기 ν•¨μˆ˜μ˜ 콜백 ν•¨μˆ˜ λ˜λŠ” 이벀트 ν•Έλ“€λŸ¬κ°€ μΌμ‹œμ μœΌλ‘œ λ³΄κ΄€λ˜λŠ” μ˜μ—­

 

2.이벀트 루프

콜 μŠ€νƒμ— ν˜„μž¬ μ‹€ν–‰ 쀑인 μ‹€ν–‰ μ»¨ν…μŠ€νŠΈκ°€ μžˆλŠ”μ§€, 그리고 νƒœμŠ€ν¬ 큐에 λŒ€κΈ° 쀑인 ν•¨μˆ˜κ°€ μžˆλŠ”μ§€ λ°˜λ³΅ν•΄μ„œ ν™•μΈν•˜κ³  콜 μŠ€νƒμ΄ λΉ„μ–΄ 있고 νƒœμŠ€ν¬ 큐에 λŒ€κΈ° 쀑인 ν•¨μˆ˜κ°€ μžˆλ‹€λ©΄ 이벀트 λ£¨ν”„λŠ” 순차적으둜 νƒœμŠ€ν¬ 큐에 λŒ€κΈ° 쀑인 ν•¨μˆ˜λ₯Ό 콜 μŠ€νƒμœΌλ‘œ μ΄λ™μ‹œν‚¨λ‹€. 즉, νƒœμŠ€ν¬ 큐에 μΌμ‹œ λ³΄κ΄€λœ ν•¨μˆ˜λ“€μ€ 비동기 처리 λ°©μ‹μœΌλ‘œ λ™μž‘ν•œλ‹€.

 

μ£Όμ˜ν•΄μ•Ό ν•  것은 μ‹±κΈ€ μŠ€λ ˆλ“œ λ°©μ‹μœΌλ‘œ λ™μž‘ν•˜λŠ” 것은 λΈŒλΌμš°μ €κ°€ μ•„λ‹ˆλΌ λΈŒλΌμš°μ €μ— λ‚΄μž₯된 μžλ°”μŠ€ν¬λ₯΄λΉ„νŠΈ μ—”μ§„μ΄λΌλŠ” 것에 μ£Όμ˜ν•΄μ•Ό ν•œλ‹€. λ§Œμ•½ λͺ¨λ“  μžλ°”μŠ€ν¬λ¦½νŠΈ μ½”λ“œκ°€ μžλ°” 슀크립트 μ—”μ§„μ—μ„œ μ‹±κΈ€ μŠ€λ ˆλ“œ λ°©μ‹μœΌλ‘œ λ™μž‘ν•œλ‹€λ©΄ μžλ°”μŠ€ν¬λ¦½νŠΈλŠ” λΉ„λ™κΈ°λ‘œ λ™μž‘ν•  수 μ—†λ‹€.  즉, μžλ°”μŠ€ν¬λ¦½νŠΈ 엔진은 μ‹±κΈ€ μŠ€λ ˆλ“œλ‘œ λ™μž‘ν•˜μ§€λ§Œ λΈŒλΌμš°μ €λŠ” λ©€ν‹° μŠ€λ ˆλ“œλ‘œ λ™μž‘ν•˜κΈ° λ•Œλ¬Έμ— 비동기 μ²˜λ¦¬κ°€ κ°€λŠ₯ν•œ 것이닀.