π μλ°μ€ν¬λ¦½νΈκ° λ³λ ¬μ²λ¦¬?
μλ§ μλ
λ§λΆν° 2μκΉμ§ μμ
νλ μμ
μ€ κ°μ₯ λ§μ΄ ν μμ
μ€ νλκ° μμ°¨μ μΌλ‘ μ§νλλ λΉλκΈ° μ½λλ₯Ό Promise.all()μ μ΄μ©ν΄ νλ²μ λμν μ μκ² μ΅μ ννλ μμ
μ΄μλ€.
μ¬λλ€μκ² λ§ν λλ λ³λ ¬μ²λ¦¬λΌκ³ νννκ³€ νμ§λ§ λ΄μμ μ΄μν¨μ΄ λκ»΄μ‘λ€. μλ°μ€ν¬λ¦½νΈλ μ±κΈμ€λ λ μΈμ΄μΈλ° μ΄λ»κ² μ¬λ¬κ°μ§ μΌμ λμμ μ²λ¦¬νλ κ±ΈκΉμ λν μ§λ¬Έμ μ°Ύμκ°λ κ³Όμ μ μ 리ν΄λ³΄λ € νλ€.
π€ μλ°μ€ν¬λ¦½νΈ μμ§μ λμ νν€μ³λ³΄κΈ°
μλ°μ€ν¬λ¦½νΈλ μ±κΈ μ€λ λ μΈμ΄λ€. μ΄λ§μ μλ―Έλ νλ²μ νλμ μΌλ§ ν μ μκ² μ€κ³λμ΄ μλ μΈμ΄λ‘ μ΄λ²€νΈ 루νλ₯Ό μ΄μ©ν΄ call stackμΌλ‘ λ€μ΄μ¨ νλμ μΌλ§ νλ²μ μ²λ¦¬ν μ μλ€. κ·Έλ¬λ©΄ μ΄λ»κ² Promise.all([...]) κ°μ μ½λλ₯Ό ν΅ν΄ λμμ μ¬λ¬κ°μ§ μΌμ λμμ μ²λ¦¬νλ κ²μ΄ κ°λ₯ν κΉ.
Sequence vs Parallel vs Concurrent
μλ°μ€ν¬λ¦½νΈμμ μ¬λ¬κ°μ§ μΌμ λμμ μ²λ¦¬νλ κ²μ λν΄ μ ννκ² μ΄ν΄νκΈ° μν΄μλ Sequence, Parallel, Concurrentμ μ°¨μ΄λ₯Ό μ΄ν΄ν΄μΌ νλ€.
- Sequence: μμ°¨μ μΌλ‘ μ€νλλ κ²μ μλ―Ένλ€. A -> B -> C μμλλ‘ μ€νλλ κ²μ μλ―Ένλ€.
- Parallel: λ§κ·Έλλ‘ λμμ μ€νλλ κ²μ μλ―Ένλ€. A, B, Cκ° λμμ μ€νλλ κ²μ μλ―Ένλ€.
- Concurrent: λ³λ ¬μ μΌλ‘ μ€νλλ κ²μ²λΌ 보μ΄μ§λ§, μ€μ λ‘λ λμμ μ€νλμ§ μλ κ²μ μλ―Ένλ€. A, B, Cκ° λμμ μ€νλλ κ²μ²λΌ 보μ΄μ§λ§, μ€μ λ‘λ Aκ° μ€νλκ³ , Bκ° μ€νλκ³ , Cκ° μ€νλλ κ²μ μλ―Ένλ€.
λ°λΌμ μ μ μμ λ°λΌ μλ°μ€ν¬λ¦½νΈκ° μ¬λ¬κ°μ§ μΌμ λμμ μ²λ¦¬ν μ μλ€λ κ²μ μλ―Έκ° parallelμ΄λΌλ©΄ μ€μ λ‘ μ¬λ¬κ°μ§ μΌμ λμμ μ€ννλ κ²μΌλ‘, concurrentνλ€λ©΄ μμ°¨μ μΌλ‘ μ§ννμ§λ§ λΉ λ₯΄κ² μ§νλκΈ°μ λμμ μ§νλλ κ²μ²λΌ 보μΈλ€κ³ ν μ μλ€. parallelκ³Ό concurrent λκ°μ§ λμ μ€ μ΄λ€ κ² λ§λμ§ νμΈνκΈ° μν΄ μλ₯Ό λ€μ΄, μ½λμ ν¨κ» μμ보μ.
μλ°μ€ν¬λ¦½νΈ μ€λ λλ₯Ό μ¨μ΄ν°λ‘ μλ₯Ό λ λ€λ©΄ λ€μκ³Ό κ°μ΄ μ 리ν μ μλ€.
- Sequence: μ¨μ΄ν°κ° νλμ ν μ΄λΈμ λν΄ μ£Όλ¬Έμ λ°κ³ μμμ΄ λμ€λ©΄, λ€μ ν μ΄λΈμ λν΄ μ£Όλ¬Έμ λ°λ κ²μ μλ―Ένλ€.
- Parallel: μ¬λ¬ μ¨μ΄ν°κ° μ¬λ¬ ν μ΄λΈμ λν΄ λμμ μ£Όλ¬Έμ λ°κ³ λμμ μμμ΄ λμ€λ κ²μ μλ―Ένλ€.
- Concurrent: νλͺ
μ μ¨μ΄ν°κ° μ¬λ¬ ν
μ΄λΈμ μ£Όλ¬Έμ μμλλ‘ λ°κ³ μ£Όλ¬Έμ λ£μ§λ§ λΉ λ₯΄κ² μ΄ κ³Όμ μ΄ μ§νλλ€ λ³΄λ μ¬λ¬ ν
μ΄λΈμ λν μμμ΄
κ±°μ λμμ λμ€λ κ²μ μλ―Ένλ€.
κ·Έλ¬λ©΄ μμ μ½λλ₯Ό μ΄μ©ν΄ μ μΈκ°μ§ μν©μ λν΄ νμΈν΄λ³΄μ. μλ μ½λλ orderAndServeλΌλ ν¨μλ₯Ό μ΄μ©ν΄ ν
μ΄λΈμ λν μ£Όλ¬Έμ λ°κ³ μμμ μλΉνλ μ½λμ΄λ€.
function orderAndServe(startTime, ms, tableNumber) {
console.log(`ν
μ΄λΈ ${tableNumber} λμ°© - ${new Date() - startTime}ms`)
return new Promise(resolve => {
console.log(`ν
μ΄λΈ ${tableNumber} μ£Όλ¬Έ λ°μ - ${new Date() - startTime}ms`)
return setTimeout(() => {
resolve(tableNumber)
}, ms)
}).then(number => {
console.log(
`ν
μ΄λΈ ${number} ${ms}ms ν μμ λμ΄ - $${new Date() - startTime}ms`
)
})
}
async function sequenceRun(startTime) {
await orderAndServe(startTime, 1000, 1)
await orderAndServe(startTime, 1000, 2)
}
async function concurrentOrParallelRun(startTime) {
await Promise.all([
orderAndServe(startTime, 1000, 1),
orderAndServe(startTime, 1000, 2),
])
}λ§μ½ μλ°μ€ν¬λ¦½νΈκ° Parallelνκ² λμνλ€λ©΄ λκ°μ§ κ°μ μ ν΄λ³Ό μ μλ€.
- μ€νν λ λ§λ€ λλλ ν μ΄λΈμ μμκ° λ€λ₯Ό μ μλ€. λ 립μ μΈ μ€λ λμμ μ§νλκΈ° λλ¬Έμ κ²°κ³Όμ μμκ° λ³΄μ₯λμ§ μμ μ μλ€.
- κ° ν μ΄λΈμ λμ°©νλ μκ°, μ£Όλ¬Έμ λ°λ μκ°, μμμ΄ λμ€λ μκ°μ΄ κ°λ€.
| Sequential | Concurrent |
|---|---|
|
|
μ μ¬μ§μ λκ°μ§ ν
μ΄λΈμ λν΄μ κ° ν¨μλ₯Ό μ€νν κ²°κ³Όλ‘, sequentialμ²λΌ νμ ν
μ΄λΈ1μμ ν
μ΄λΈ 2λ‘ κ°μ μμλ‘ μ§νλλ κ²μ λ³Ό μ μλ€.
μ κ°μ νλ λκ°μ§ μ€ parallel νλ€λ κ°μ μ 첫λ²μ§Έκ° μ΄κΈλ κ²μ λ³Ό μ μλ€. νμ§λ§ λ λ²μ§Έ κ°μ μ΄μλ ν μ΄λΈλ³ λμ°©, μ£Όλ¬Έ, μλΉ μκ°μ΄ κ°λ€λ κ°μ μ λ§λ κ²μ λ³Ό μ μλ€. κ·Έλ¬λ©΄ μ‘°κΈ λ λ§μ ν μ΄λΈμ μλΉνκ² ν΄λ³΄μ
function orderAndServe(startTime, ms, tableNumber) {
console.log(`ν
μ΄λΈ ${tableNumber} λμ°© - ${new Date() - startTime}ms`)
return new Promise(resolve => {
console.log(`ν
μ΄λΈ ${tableNumber} μ£Όλ¬Έ λ°μ - ${new Date() - startTime}ms`)
return setTimeout(() => {
resolve(tableNumber)
}, ms)
}).then(number => {
console.log(
`ν
μ΄λΈ ${number} ${ms}ms ν μμ λμ΄ - $${new Date() - startTime}ms`
)
})
}
const tables = Array.from({ length: 10 }, (_, i) => i + 1)
async function concurrentOrParallelRun(startTime) {
await Promise.all(
tables.map(tableNumber => orderAndServe(startTime, 1000, tableNumber))
)
}
concurrentRun(new Date())μλ μ¬μ§μ μ 10κ°μ ν μ΄λΈμ λν μ½λλ₯Ό μ€νν κ²°κ³Όλ€. μλκ²°κ³Όλ₯Ό 보면 ν μ΄λΈ 1λΆν° 10κΉμ§ μμκ° μ μ§λκ³ , ν μ΄λΈλ³ κ° λμ μλ£μκ°μ μ°¨μ΄κ° λλ κ²μ λ³Ό μ μλ€.
μ΄λ₯Ό ν΅ν΄ Promise.all()μ λ³λ ¬μ (parallelism)μΌλ‘ μ²λ¦¬νλ κ²μ΄ μλλΌ μλ°μ€ν¬λ¦½νΈμ λμμ±(concurrency)μ μ΄μ©ν΄ μμ°¨μ μΌλ‘ μ§ννμ§λ§ λΉ λ₯΄κ² μ§νν¨μΌλ‘μ μ±λ₯μ μ΄μ μ μ»μ μ μλ λ©μλμμ μ μ μμλ€.
λ²μΈ: λ³λ ¬μ μ§μνλ©΄ κ²°κ³Όκ° μ΄λ»κ² λ¬λΌμ§κΉ
λ΄κ° νλ parallelismμ λν λκ°μ§ κ°μ μ΄ μ€μ λ³λ ¬ μ²λ¦¬ μ§μνλ μΈμ΄μμ μ μλ―Ένκ² λμνλμ§μ λν΄ μμλ³΄κ³ μ ChatGPTλ₯Ό μ΄μ©ν΄ GoμΈμ΄λ‘ μ μ¬ν μ½λλ₯Ό μμ±ν΄λ³΄μλ€.
package main
import (
"fmt"
"sync"
"time"
)
func orderAndServe(startTime time.Time, ms time.Duration, tableNumber int, wg *sync.WaitGroup) {
defer wg.Done() // μ΄ ν¨μκ° λλλ©΄ WaitGroupμ μΉ΄μ΄ν°λ₯Ό κ°μμν¨λ€.
fmt.Printf("ν
μ΄λΈ %d λμ°© - %vms\n", tableNumber, time.Since(startTime).Milliseconds())
fmt.Printf("ν
μ΄λΈ %d μ£Όλ¬Έ λ°μ - %vms\n", tableNumber, time.Since(startTime).Milliseconds())
time.Sleep(ms)
fmt.Printf("ν
μ΄λΈ %d %vms ν μμ λμ΄ - %vms\n", tableNumber, ms.Milliseconds(), time.Since(startTime).Milliseconds())
}
func main() {
startTime := time.Now()
var wg sync.WaitGroup
// 10κ°μ ν
μ΄λΈμ λν΄ λ³λ ¬λ‘ μ²λ¦¬
for i := 1; i <= 10; i++ {
wg.Add(1) // WaitGroupμ μΉ΄μ΄ν°λ₯Ό μ¦κ°μν¨λ€.
go orderAndServe(startTime, 1000*time.Millisecond, i, &wg)
}
wg.Wait() // λͺ¨λ κ³ λ£¨ν΄μ΄ μλ£λ λκΉμ§ κΈ°λ€λ¦°λ€.
}μ μ½λλ goμΈμ΄λ‘ μμ±ν μ½λλ‘, sync.WaitGroupμ μ΄μ©ν΄ λ³λ ¬λ‘ ν¨μλ₯Ό μ§νμμΌ°λ€. μλλ μ μ½λλ₯Ό μ€νν κ²°κ³Όλ€.
κ²°κ³Όλ₯Ό 보면 ν μ΄λΈ λμ°©κ³Ό μ£Όλ¬Έλ°μκΉμ§ μ§ν μμκ° ν μ΄λΈ 1λΆν° μ§ννμ§ μκ³ (첫λ²μ§Έ κ°μ μ λ 립μ μΈ μ€λ λ), μλ£ν μκ°μ 보면 λμΌνκ² μ²λ¦¬λ κ² (λλ²μ§Έ κ°μ μ κ°μ μκ°μ μλ£)μ λ³Ό μ μμλ€. μ΄λ₯Ό ν΅ν΄ μμ λκ°μ§ κ°μ μ΄ λ³λ ¬μ²λ¦¬κ° κ°λ₯ν μΈμ΄μ νΉμ§μ μ보μ¬μ£Όλ κ°μ μ΄μκ³ , Promise.all()μ λ³λ ¬μ μΌλ‘ μ²λ¦¬νλ κ²μ΄ μλλΌ μλ°μ€ν¬λ¦½νΈμ λμμ±μ μ΄μ©νλ λ©μλμμ νλ² λ νμΈν μ μμλ€.
[μ°Έμ‘°]