πŸ‘Ίμ½œλ°± 지μ˜₯κ³Ό 동기, 비동기

βœπŸ»μžλ°”μŠ€ν¬λ¦½νŠΈλŠ” Synchronous ν•˜λ‹€

μžλ°”μŠ€ν¬λ¦½νŠΈλŠ” 동기적이닀.

ν˜Έμ΄μŠ€νŒ…μ΄ 된 이후뢀터 μž‘μ„±λœ μˆœμ„œλŒ€λ‘œ μ‹€ν–‰λœλ‹€.

Hoisting μ΄λž€, var κ³Ό function declaration 이 μžλ™μ μœΌλ‘œ 제일 μœ„λ‘œ μ˜¬λΌκ°€κ²Œ λ˜λŠ” 것을 μ˜λ―Έν•œλ‹€.

λͺ¨λ“  ν•¨μˆ˜μ˜ 선언은 ν˜Έμ΄μŠ€νŒ… λœλ‹€.

console.log(1)
console.log(2)
console.log(3)

1, 2, 3 μˆœμ„œλŒ€λ‘œ μ°νžˆλŠ” 것을 확인 ν•  수 μžˆλ‹€.

⏲비동기 처리의 λŒ€ν‘œμ  μ˜ˆμ‹œ, setTimeout()

비동기 처리 (Asynchronous) 의 λŒ€ν‘œμ  API λŠ” setTimeout() 이 μžˆλ‹€.

setTimeout() λŠ” λΈŒλΌμš°μ € API 둜, 일정 μ‹œκ°„μ΄ μ§€λ‚˜λ©΄ μ§€μ •ν•œ μ½œλ°±ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•˜κ²Œ λœλ‹€.

μ•„λž˜ 비동기적인 μ‹€ν–‰ 방법을 보도둝 ν•˜μž.

console.log(1)
setTimeout(function() {
  console.log(2)
}, 1000)
console.log(3)
// 1, 3, 2 μˆœμ„œλ‘œ μ°νžŒλ‹€.

λ‘λ²ˆμ§Έ 쀄 setTimeout 은 ν•¨μˆ˜ ν˜Έμ΄μŠ€νŒ…μ— μ˜ν•΄ 맨 μœ„λ‘œ μ˜¬λΌκ°„ μƒνƒœμ—μ„œ

1이 λ¨Όμ € μ½˜μ†”μ°½μ— 좜λ ₯되고 setTimeout 의 콜백 ν•¨μˆ˜λŠ” λΈŒλΌμš°μ €μ—κ²Œ

β€œ1초 λ’€ μ½œλ°±ν•¨μˆ˜λ₯Ό μ‹€ν–‰ν•΄μ€˜!”

라고 λΈŒλΌμš°μ €μ—κ²Œ μš”μ²­μ„ λ„£κ²Œ λœλ‹€.

λ°”λ‘œ 뒀이어 숫자 3이 좜λ ₯되고 1초 λ’€, μ½œλ°±ν•¨μˆ˜κ°€ μ‹€ν–‰λ˜μ–΄ (Timehandler μ—­ν• ) λ“œλ””μ–΄ 숫자 2κ°€ 좜λ ₯λœλ‹€.

β˜ŽοΈλ‹€μ‹œ! setTimeout 콜백 ν•¨μˆ˜μ˜ μ •μ˜

ν•˜λ‚˜μ˜ Parameter 에 λ“€μ–΄κ°€λŠ” ν•¨μˆ˜, μ§€κΈˆ λ‹Ήμž₯ μ‹€ν–‰ν•˜μ§€λŠ” μ•Šκ³  λͺ‡ 초 뒀에 λ‚΄ ν•¨μˆ˜λ₯Ό 콜 (call) ν•΄μ€˜!

라고 μ „λ‹¬ν•˜λŠ” 것을 μ˜λ―Έν•œλ‹€. Callback, 주둜 Arrow function 을 μ‚¬μš©ν•΄μ„œ λ‚˜μ€‘μ— λ‹€μ‹œ λΆˆλŸ¬λ‹¬λΌκ³  ν•˜λŠ” 것이닀.

그러면 μ½œλ°±μ€ 항상 비동기 적일 λ•Œλ§Œ μ“ΈκΉŒ? No!

πŸ“±μ½œλ°± ν•¨μˆ˜μ˜ 2가지 μ’…λ₯˜

1. 동기 콜백 (Synchronous Callback)

첫번째, 동기 μ½œλ°±μ€ print λΌλŠ” μ½œλ°±ν•¨μˆ˜λ₯Ό νŒŒλΌλ―Έν„°λ‘œ λ°›μ•„μ„œ μ‹€ν–‰ν•œλ‹€.

function printImmediately(print) {
  print()
}
// μœ„ ν•¨μˆ˜μ˜ 선언을 톡해 ν•¨μˆ˜μ˜ 선언을 제일 μœ„λ‘œ (Hoisting) μ˜¬λ¦°λ‹€.

printImmediately(() => console.log('Hello'))

1, 3, Hello, 2 μˆœμ„œλ‘œ μ°νžŒλ‹€. μ™œ?

console.log(1)
setTimeout(function() {
  console.log(2)
}, 1000)
console.log(3)
printImmediately(() => console.log('Hello'))

Hoisting 에 따라 μ„ μ–Έν•œ μˆœμ„œ κ³ λŒ€λ‘œ 좜λ ₯λœλ‹€.

κ·Έλž˜μ„œ 1, 3, Hello, 2 μˆœμ„œλ‘œ 좜λ ₯λœλ‹€.

2. 비동기 콜백 (Asynchronous Callback)

λ‘λ²ˆμ§Έ, 비동기 μ½œλ°±ν•¨μˆ˜λ₯Ό μ„ μ–Έ 및 μ‹€ν–‰ν•΄ λ³΄μ•˜λ‹€.

function printWithDelay(print, timeout) {
  setTimeout(print, timeout)
}
printWithDelay(() => console.log('Async Callback'), 2000)
// 이제 1, 3, Hello, 2, Async Callback 으둜 μ°νžŒλ‹€.

μ•„κΉŒμ˜ λˆ„μ λœ 데이터λ₯Ό λ‹€μ‹œ λΆˆλŸ¬μ™€ 보면,

console.log(1)
setTimeout(function() {
  console.log(2)
}, 1000)
console.log(3)
printImmediately(() => console.log('Hello'))
printWithDelay(() => console.log('Async Callback'), 2000)

1, 3, Hello, 2, Async Callback 순으둜 좜λ ₯λ˜λŠ” μ΄μœ μ— λŒ€ν•΄ μˆ˜κΈν•  수 μžˆλ‹€.

πŸ‘λ°±μ—”λ“œ μ‚¬μš©μž 데이터λ₯Ό λ°›λŠ” μ €μž₯μ†Œ λ§Œλ“€κΈ°

class UserStorage {
  loginUser(id, password, onSuccess, onError) {
    setTimeout(() => {
      if (
        (id === 'seolleung' && password === 'daechidongganggunma') ||
        (id === 'gdragon' && password === 'yakkuk')
      ) {
        onSuccess(id)
      } else {
        onError(new Error('not Found'))
      }
    }, 2000)
  }
  getRoles(user, onSuccess, onError) {
    setTimeout(() => {
      if (user === 'seolleung') {
        onSuccess({ name: 'seolleung', role: 'admin' })
      } else {
        onError(new Error('No Access'))
      }
    }, 1000)
  }
}

loginUser ν•¨μˆ˜μ˜ μ—­ν• 

loginUser ν•¨μˆ˜λŠ” id 와 password λ₯Ό λ°›κ³ , μ‚¬μš©μžμ˜ 데이터 (id λ‚˜ password κ°€ μΌμΉ˜ν•˜λŠ”) κ°€ 적합할 λ•Œ

μ‚¬μš©μž 데이터와 ν•¨κ»˜ onSuccess λΌλŠ” μ½œλ°±ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•˜κ³ , μ ν•©ν•˜μ§€ μ•Šμ„ λ•ŒλŠ” onError λΌλŠ” μ½œλ°±ν•¨μˆ˜λ₯Ό 톡해

μ—λŸ¬ λ©”μ‹œμ§€λ₯Ό 보이도둝 ν•  것이닀.

loginUser ν•¨μˆ˜ λ‚΄ setTimeout 의 첫번째 인자둜 μ½œλ°±ν•¨μˆ˜κ°€ 였고, κ·Έ μ½œλ°±ν•¨μˆ˜μ˜ 역할은

  • νŠΉμ • 아이디와 λΉ„λ°€λ²ˆν˜Έκ°€ μΌμΉ˜ν•˜λŠ” 경우 (μ°ΈμΌλ•Œ)
  • onSuccess λΌλŠ” μ½œλ°±ν•¨μˆ˜μ— id λ₯Ό λ‹΄μ•„ μ „λ‹¬ν•˜κ²Œ ν•œλ‹€. onSuccess(id)
  • νŠΉμ • 아이디와 λΉ„λ°€λ²ˆν˜Έκ°€ μΌμΉ˜ν•˜μ§€ μ•Šμ„ λ•Œ (거짓쑰건)
  • Error λΌλŠ” Object λ₯Ό λ§Œλ“€μ–΄μ„œ (JS λ‚΄μž₯객체)
  • Not Found 라고 μ—λŸ¬ λ©”μ‹œμ§€λ₯Ό 전달할 것이닀.

getRoles ν•¨μˆ˜μ˜ μ—­ν• 

μ‚¬μš©μž 데이터λ₯Ό λ°›μ•„μ„œ Admin λ˜λŠ” guest κΆŒν•œμΈμ§€λ₯Ό λ°›μ•„μ˜€λŠ” 역할을 λ‹΄λ‹Ήν•œλ‹€.

ν•΄λ‹Ή 둜그인 μœ μ € 쀑에 μΌμΉ˜ν•˜λŠ” μœ μ €κ°€ μžˆλ‹€λ©΄, onSuccess ν•¨μˆ˜λ₯Ό 톡해 μœ μ €μ˜ 역할을 담은 객체λ₯Ό λ¦¬ν„΄ν•œλ‹€.

πŸ€€κ³Όμ • μš”μ•½

  • UserStorage μ—μ„œ id, password λ₯Ό λ°›μ•„μ˜¨λ‹€.
  • μž…λ ₯을 받아와 λ‘œκ·ΈμΈμ— μ„±κ³΅ν•˜λ©΄ id λ₯Ό λ‹€μ‹œ λ°›μ•„μ˜€λŠ”λ°,
  • onSucccess(id) λ₯Ό 톡해 Roles, 역할을 μš”μ²­ν•˜κ²Œ λœλ‹€. (getRoles)
  • 역할을 λ°›μ•„ 올 수 μžˆλ‹€λ©΄, μ‚¬μš©μžμ˜ 였브젝트 (이름, 역할이 λ“€μ–΄μžˆλŠ”)λ₯Ό 보이게 ν•œλ‹€.

βœπŸ»μ‚¬μš©ν•΄λ³΄κΈ°

const userStorage = new UserStorage()
const id = prompt('Enter your ID')
const password = prompt('Enter your Password')

userStorage.loginUser(
  id,
  password,
  user => {
    userStorage.getRoles(
      user,
      userWithRole => {
        alert(
          `Hello ${userWithRole.name}, you have a ${userWithRole.role} role`
        )
      },
      error => {
        console.log(error)
      }
    )
  },
  error => {
    console.log(error)
  }
)

callbackhell

πŸ‘»λ¬Έμ œμ 

  1. μ½”λ“œλ₯Ό 읽기가 λ„ˆλ¬΄ κ±°λΆν•˜λ‹€. 거뢁거뢁
  2. 가독성이 λ–¨μ–΄μ Έμ„œ ν•œλˆˆμ— μ•Œμ•„λ³΄κΈ°κ°€ μ–΄λ ΅λ‹€.
  3. 디버깅에 어렀움을 κ²ͺ을 수 μžˆλ‹€.
  4. 콜백체인이 κΈΈμ–΄μ Έ 쒋지 μ•Šλ‹€.

Written by@[DotoriMook]
ν”„λ‘ νŠΈμ—”λ“œ μ£Όλ‹ˆμ–΄ 개발자 λ„ν† λ¦¬λ¬΅μ˜ 기술개발 λΈ”λ‘œκ·Έ μž…λ‹ˆλ‹€.

GitHubMediumTwitterFacebook